Skip to content

Commit 7943d96

Browse files
Fix Samplers to match spec (#1037)
* Modified sampler to return Decision * Added missing functionalites affected with conflict. * Added test * Fix test * Removed IsAllDataRequested check from processor * Checking if sampler is null. * Adding code missed from conflict * Incorporating PR feedback * Fix test * Removed OpenTelemetry.Trace.Samplers namespace * Update to changelog * Moved test to tracersdk Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
1 parent ba077fb commit 7943d96

26 files changed

Lines changed: 456 additions & 172 deletions

docs/trace/building-your-own-sampler/MySampler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ internal class MySampler : Sampler
2020
{
2121
public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
2222
{
23-
return new SamplingResult(false);
23+
return new SamplingResult(SamplingDecision.NotRecord);
2424
}
2525
}

src/OpenTelemetry/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
* Modified Sampler implementation to match the spec
6+
([#1037](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1037))
57
* Changed `ActivityProcessor` to implement `IDisposable`
68
([#975](https://github.com/open-telemetry/opentelemetry-dotnet/pull/975))
79
* Samplers now get the actual TraceId of the Activity to be created.

src/OpenTelemetry/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ with sampling probability of 25%.
6464
```csharp
6565
using OpenTelemetry;
6666
using OpenTelemetry.Trace;
67-
using OpenTelemetry.Trace.Samplers;
6867

6968
using var otel = Sdk.CreateTracerProvider(b => b
7069
.AddActivitySource("MyCompany.MyProduct.MyLibrary")

src/OpenTelemetry/Trace/ActivitySourceAdapter.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,20 @@ private void RunGetRequestedData(Activity activity)
100100
activity.TagObjects,
101101
activity.Links);
102102

103-
var samplingDecision = this.sampler.ShouldSample(samplingParameters);
104-
activity.IsAllDataRequested = samplingDecision.IsSampled;
105-
if (samplingDecision.IsSampled)
103+
var samplingResult = this.sampler.ShouldSample(samplingParameters);
104+
105+
switch (samplingResult.Decision)
106106
{
107-
activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded;
107+
case SamplingDecision.NotRecord:
108+
activity.IsAllDataRequested = false;
109+
break;
110+
case SamplingDecision.Record:
111+
activity.IsAllDataRequested = true;
112+
break;
113+
case SamplingDecision.RecordAndSampled:
114+
activity.IsAllDataRequested = true;
115+
activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded;
116+
break;
108117
}
109118
}
110119
}

src/OpenTelemetry/Trace/Samplers/AlwaysOffSampler.cs renamed to src/OpenTelemetry/Trace/AlwaysOffSampler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// limitations under the License.
1515
// </copyright>
1616

17-
namespace OpenTelemetry.Trace.Samplers
17+
namespace OpenTelemetry.Trace
1818
{
1919
/// <summary>
2020
/// Sampler implementation which never samples any activity.
@@ -24,7 +24,7 @@ public sealed class AlwaysOffSampler : Sampler
2424
/// <inheritdoc />
2525
public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
2626
{
27-
return new SamplingResult(false);
27+
return new SamplingResult(SamplingDecision.NotRecord);
2828
}
2929
}
3030
}

src/OpenTelemetry/Trace/Samplers/AlwaysOnSampler.cs renamed to src/OpenTelemetry/Trace/AlwaysOnSampler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// limitations under the License.
1515
// </copyright>
1616

17-
namespace OpenTelemetry.Trace.Samplers
17+
namespace OpenTelemetry.Trace
1818
{
1919
/// <summary>
2020
/// Sampler implementation which samples every activity.
@@ -25,7 +25,7 @@ public sealed class AlwaysOnSampler : Sampler
2525
/// <inheritdoc />
2626
public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
2727
{
28-
return new SamplingResult(true);
28+
return new SamplingResult(SamplingDecision.RecordAndSampled);
2929
}
3030
}
3131
}

src/OpenTelemetry/Trace/BatchingActivityProcessor.cs

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -139,40 +139,43 @@ public BatchingActivityProcessor(ActivityExporter exporter, int maxQueueSize, Ti
139139
/// <inheritdoc/>
140140
public override void OnEnd(Activity activity)
141141
{
142-
// because of race-condition between checking the size and enqueueing,
143-
// we might end up with a bit more activities than maxQueueSize.
144-
// Let's just tolerate it to avoid extra synchronization.
145-
if (this.currentQueueSize >= this.maxQueueSize)
142+
if (activity.Recorded)
146143
{
147-
OpenTelemetrySdkEventSource.Log.SpanProcessorQueueIsExhausted();
148-
return;
149-
}
144+
// because of race-condition between checking the size and enqueueing,
145+
// we might end up with a bit more activities than maxQueueSize.
146+
// Let's just tolerate it to avoid extra synchronization.
147+
if (this.currentQueueSize >= this.maxQueueSize)
148+
{
149+
OpenTelemetrySdkEventSource.Log.SpanProcessorQueueIsExhausted();
150+
return;
151+
}
150152

151-
var size = Interlocked.Increment(ref this.currentQueueSize);
153+
var size = Interlocked.Increment(ref this.currentQueueSize);
152154

153-
this.exportQueue.Enqueue(activity);
155+
this.exportQueue.Enqueue(activity);
154156

155-
if (size >= this.maxExportBatchSize)
156-
{
157-
bool lockTaken = this.flushLock.Wait(0);
158-
if (lockTaken)
157+
if (size >= this.maxExportBatchSize)
159158
{
160-
Task.Run(async () =>
159+
bool lockTaken = this.flushLock.Wait(0);
160+
if (lockTaken)
161161
{
162-
try
163-
{
164-
await this.FlushAsyncInternal(drain: false, lockAlreadyHeld: true, CancellationToken.None).ConfigureAwait(false);
165-
}
166-
catch (Exception ex)
167-
{
168-
OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.OnEnd), ex);
169-
}
170-
finally
162+
Task.Run(async () =>
171163
{
172-
this.flushLock.Release();
173-
}
174-
});
175-
return;
164+
try
165+
{
166+
await this.FlushAsyncInternal(drain: false, lockAlreadyHeld: true, CancellationToken.None).ConfigureAwait(false);
167+
}
168+
catch (Exception ex)
169+
{
170+
OpenTelemetrySdkEventSource.Log.SpanProcessorException(nameof(this.OnEnd), ex);
171+
}
172+
finally
173+
{
174+
this.flushLock.Release();
175+
}
176+
});
177+
return;
178+
}
176179
}
177180
}
178181
}

src/OpenTelemetry/Trace/Samplers/ParentOrElseSampler.cs renamed to src/OpenTelemetry/Trace/ParentOrElseSampler.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
using System;
1717
using System.Diagnostics;
1818

19-
namespace OpenTelemetry.Trace.Samplers
19+
namespace OpenTelemetry.Trace
2020
{
2121
/// <summary>
2222
/// Sampler implementation which will take a sample if parent Activity or any linked Activity is sampled.
@@ -51,7 +51,7 @@ public override SamplingResult ShouldSample(in SamplingParameters samplingParame
5151
// If the parent is sampled keep the sampling decision.
5252
if ((parentContext.TraceFlags & ActivityTraceFlags.Recorded) != 0)
5353
{
54-
return new SamplingResult(true);
54+
return new SamplingResult(SamplingDecision.RecordAndSampled);
5555
}
5656

5757
if (samplingParameters.Links != null)
@@ -61,13 +61,13 @@ public override SamplingResult ShouldSample(in SamplingParameters samplingParame
6161
{
6262
if ((parentLink.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0)
6363
{
64-
return new SamplingResult(true);
64+
return new SamplingResult(SamplingDecision.RecordAndSampled);
6565
}
6666
}
6767
}
6868

6969
// If parent was not sampled, do not sample.
70-
return new SamplingResult(false);
70+
return new SamplingResult(SamplingDecision.NotRecord);
7171
}
7272
}
7373
}

src/OpenTelemetry/Trace/Samplers/ProbabilitySampler.cs renamed to src/OpenTelemetry/Trace/ProbabilitySampler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
using System;
1717
using System.Globalization;
1818

19-
namespace OpenTelemetry.Trace.Samplers
19+
namespace OpenTelemetry.Trace
2020
{
2121
/// <summary>
2222
/// Samples traces according to the specified probability.
@@ -74,7 +74,7 @@ public override SamplingResult ShouldSample(in SamplingParameters samplingParame
7474
// code is executed in-line for every Activity creation).
7575
Span<byte> traceIdBytes = stackalloc byte[16];
7676
samplingParameters.TraceId.CopyTo(traceIdBytes);
77-
return Math.Abs(this.GetLowerLong(traceIdBytes)) < this.idUpperBound ? new SamplingResult(true) : new SamplingResult(false);
77+
return new SamplingResult(Math.Abs(this.GetLowerLong(traceIdBytes)) < this.idUpperBound);
7878
}
7979

8080
private long GetLowerLong(ReadOnlySpan<byte> bytes)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// <copyright file="SamplingDecision.cs" company="OpenTelemetry Authors">
2+
// Copyright The OpenTelemetry Authors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
17+
namespace OpenTelemetry.Trace
18+
{
19+
/// <summary>
20+
/// Enumeration to define sampling decision.
21+
/// </summary>
22+
public enum SamplingDecision
23+
{
24+
/// <summary>
25+
/// The activity object needs to be created. It will have Name, Source, Id and Baggage.
26+
/// Other properties will be ignored.
27+
/// </summary>
28+
NotRecord,
29+
30+
/// <summary>
31+
/// The activity object should be populated with all the propagation info and also all other
32+
/// properties such as Links, Tags, and Events. Activity.IsAllDataRequested will return true.
33+
/// </summary>
34+
Record,
35+
36+
/// <summary>
37+
/// The activity object should be populated with all the propagation info and also all other
38+
/// properties such as Links, Tags, and Events.
39+
/// Both Activity.IsAllDataRequested and Activity.IsRecorded will return true.
40+
/// </summary>
41+
RecordAndSampled,
42+
}
43+
}

0 commit comments

Comments
 (0)