-
Notifications
You must be signed in to change notification settings - Fork 778
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Probability Sampler for Activity (#702)
* Merging changes in OpenTelemetrySdk * Renames from span to activity
- Loading branch information
Showing
10 changed files
with
545 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// <copyright file="ActivitySamplingParameters.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
|
||
namespace OpenTelemetry.Trace | ||
{ | ||
/// <summary> | ||
/// Sampling parameters passed to an <see cref="ActivitySampler"/> for it to make a sampling decision. | ||
/// </summary> | ||
public readonly struct ActivitySamplingParameters | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ActivitySamplingParameters"/> struct. | ||
/// </summary> | ||
/// <param name="parentContext">Parent activity context. Typically taken from the wire.</param> | ||
/// <param name="traceId">Trace ID of a activity to be created.</param> | ||
/// <param name="name">The name (DisplayName) of the activity to be created. Note, that the name of the activity is settable. | ||
/// So this name can be changed later and Sampler implementation should assume that. | ||
/// Typical example of a name change is when <see cref="Activity"/> representing incoming http request | ||
/// has a name of url path and then being updated with route name when routing complete. | ||
/// </param> | ||
/// <param name="kind">The kind of the Activity to be created.</param> | ||
/// <param name="tags">Initial set of Tags for the Activity being constructed.</param> | ||
/// <param name="links">Links associated with the activity.</param> | ||
public ActivitySamplingParameters( | ||
ActivityContext parentContext, | ||
ActivityTraceId traceId, | ||
string name, | ||
ActivityKind kind, | ||
IEnumerable<KeyValuePair<string, string>> tags = null, // TODO: Empty | ||
IEnumerable<ActivityLink> links = null) | ||
{ | ||
this.ParentContext = parentContext; | ||
this.TraceId = traceId; | ||
this.Name = name; | ||
this.Kind = kind; | ||
this.Tags = tags; | ||
this.Links = links; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the parent activity context. | ||
/// </summary> | ||
public ActivityContext ParentContext { get; } | ||
|
||
/// <summary> | ||
/// Gets the trace ID of parent activity or a new generated one for root span/activity. | ||
/// </summary> | ||
public ActivityTraceId TraceId { get; } | ||
|
||
/// <summary> | ||
/// Gets the name to be given to the span/activity. | ||
/// </summary> | ||
public string Name { get; } | ||
|
||
/// <summary> | ||
/// Gets the kind of span/activity to be created. | ||
/// </summary> | ||
public ActivityKind Kind { get; } | ||
|
||
/// <summary> | ||
/// Gets the tags to be associated to the span/activity to be created. | ||
/// </summary> | ||
public IEnumerable<KeyValuePair<string, string>> Tags { get; } | ||
|
||
/// <summary> | ||
/// Gets the links to be added to the activity to be created. | ||
/// </summary> | ||
public IEnumerable<ActivityLink> Links { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
src/OpenTelemetry/Trace/Samplers/ProbabilityActivitySampler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// <copyright file="ProbabilityActivitySampler.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
using System; | ||
using System.Diagnostics; | ||
using System.Globalization; | ||
|
||
namespace OpenTelemetry.Trace.Samplers | ||
{ | ||
/// <summary> | ||
/// Sampler implementation which will take a sample if parent Activity or any linked Activity is sampled. | ||
/// Otherwise, samples traces according to the specified probability. | ||
/// </summary> | ||
public sealed class ProbabilityActivitySampler : ActivitySampler | ||
{ | ||
private readonly long idUpperBound; | ||
private readonly double probability; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ProbabilityActivitySampler"/> class. | ||
/// </summary> | ||
/// <param name="probability">The desired probability of sampling. This must be between 0.0 and 1.0. | ||
/// Higher the value, higher is the probability of a given Activity to be sampled in. | ||
/// </param> | ||
public ProbabilityActivitySampler(double probability) | ||
{ | ||
if (probability < 0.0 || probability > 1.0) | ||
{ | ||
throw new ArgumentOutOfRangeException(nameof(probability), "Probability must be in range [0.0, 1.0]"); | ||
} | ||
|
||
this.probability = probability; | ||
|
||
// The expected description is like ProbabilityActivitySampler{0.000100} | ||
this.Description = "ProbabilityActivitySampler{" + this.probability.ToString("F6", CultureInfo.InvariantCulture) + "}"; | ||
|
||
// Special case the limits, to avoid any possible issues with lack of precision across | ||
// double/long boundaries. For probability == 0.0, we use Long.MIN_VALUE as this guarantees | ||
// that we will never sample a trace, even in the case where the id == Long.MIN_VALUE, since | ||
// Math.Abs(Long.MIN_VALUE) == Long.MIN_VALUE. | ||
if (this.probability == 0.0) | ||
{ | ||
this.idUpperBound = long.MinValue; | ||
} | ||
else if (this.probability == 1.0) | ||
{ | ||
this.idUpperBound = long.MaxValue; | ||
} | ||
else | ||
{ | ||
this.idUpperBound = (long)(probability * long.MaxValue); | ||
} | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override string Description { get; } | ||
|
||
/// <inheritdoc /> | ||
public override SamplingResult ShouldSample(in ActivitySamplingParameters samplingParameters) | ||
{ | ||
// If the parent is sampled keep the sampling decision. | ||
var parentContext = samplingParameters.ParentContext; | ||
if ((parentContext.TraceFlags & ActivityTraceFlags.Recorded) != 0) | ||
{ | ||
return new SamplingResult(true); | ||
} | ||
|
||
if (samplingParameters.Links != null) | ||
{ | ||
// If any parent link is sampled keep the sampling decision. | ||
foreach (var parentLink in samplingParameters.Links) | ||
{ | ||
if ((parentLink.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0) | ||
{ | ||
return new SamplingResult(true); | ||
} | ||
} | ||
} | ||
|
||
// Always sample if we are within probability range. This is true even for child activities (that | ||
// may have had a different sampling decision made) to allow for different sampling policies, | ||
// and dynamic increases to sampling probabilities for debugging purposes. | ||
// Note use of '<' for comparison. This ensures that we never sample for probability == 0.0, | ||
// while allowing for a (very) small chance of *not* sampling if the id == Long.MAX_VALUE. | ||
// This is considered a reasonable trade-off for the simplicity/performance requirements (this | ||
// code is executed in-line for every Activity creation). | ||
Span<byte> traceIdBytes = stackalloc byte[16]; | ||
samplingParameters.TraceId.CopyTo(traceIdBytes); | ||
return Math.Abs(this.GetLowerLong(traceIdBytes)) < this.idUpperBound ? new SamplingResult(true) : new SamplingResult(false); | ||
} | ||
|
||
private long GetLowerLong(ReadOnlySpan<byte> bytes) | ||
{ | ||
long result = 0; | ||
for (var i = 0; i < 8; i++) | ||
{ | ||
result <<= 8; | ||
#pragma warning disable CS0675 // Bitwise-or operator used on a sign-extended operand | ||
result |= bytes[i] & 0xff; | ||
#pragma warning restore CS0675 // Bitwise-or operator used on a sign-extended operand | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
} |
Oops, something went wrong.