author Liudmila Molkova <lmolkova@microsoft.com> 1576626312 -0800
committer Liudmila Molkova <lmolkova@microsoft.com> 1576862429 -0800

Link, SpanContext to struct
This commit is contained in:
Liudmila Molkova 2019-12-20 10:31:50 -08:00 committed by Sergey Kanzhelev
parent d49ce958a3
commit 18e5b2f127
31 changed files with 412 additions and 130 deletions

View File

@ -49,6 +49,9 @@ namespace Benchmarks
[Benchmark]
public ISpan CreateSpan_Sampled() => SpanCreationScenarios.CreateSpan(this.alwaysSampleTracer);
[Benchmark]
public ISpan CreateSpan_ParentContext() => SpanCreationScenarios.CreateSpan_ParentContext(this.alwaysSampleTracer);
[Benchmark]
public ISpan CreateSpan_Attributes_Sampled() => SpanCreationScenarios.CreateSpan_Attributes(this.alwaysSampleTracer);

View File

@ -14,6 +14,7 @@
// limitations under the License.
// </copyright>
using System.Diagnostics;
using OpenTelemetry.Trace;
namespace Benchmarks.Tracing
@ -27,6 +28,14 @@ namespace Benchmarks.Tracing
return span;
}
public static ISpan CreateSpan_ParentContext(Tracer tracer)
{
var parentContext = new SpanContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, true);
var span = tracer.StartSpan("span", parentContext);
span.End();
return span;
}
public static ISpan CreateSpan_Attributes(Tracer tracer)
{
var span = tracer.StartSpan("span");

View File

@ -98,7 +98,7 @@ namespace OpenTelemetry.Context.Propagation
/// <inheritdoc />
public byte[] ToByteArray(SpanContext spanContext)
{
if (spanContext == null || !spanContext.IsValid)
if (!spanContext.IsValid)
{
return InvalidContext;
}

View File

@ -82,7 +82,7 @@ namespace OpenTelemetry.Context.Propagation
/// <inheritdoc/>
public void Inject<T>(SpanContext spanContext, T carrier, Action<T, string, string> setter)
{
if (spanContext == null || !spanContext.IsValid)
if (!spanContext.IsValid)
{
OpenTelemetryApiEventSource.Log.FailedToInjectSpanContext("Invalid context");
return;

View File

@ -21,7 +21,7 @@ namespace OpenTelemetry.Trace
/// <summary>
/// Sampling decision.
/// </summary>
public struct Decision
public readonly struct Decision
{
/// <summary>
/// Initializes a new instance of the <see cref="Decision"/> struct.
@ -38,7 +38,7 @@ namespace OpenTelemetry.Trace
/// </summary>
/// <param name="isSampled">True if sampled, false otherwise.</param>
/// <param name="attributes">Attributes associated with the sampling decision. Attributes list passed to
/// this method must be imutable. Mutations of the collection and/or attribute values may lead to unexpected behavior.</param>
/// this method must be immutable. Mutations of the collection and/or attribute values may lead to unexpected behavior.</param>
public Decision(bool isSampled, IEnumerable<KeyValuePair<string, object>> attributes)
{
this.IsSampled = isSampled;
@ -53,11 +53,46 @@ namespace OpenTelemetry.Trace
/// Gets a value indicating whether Span was sampled or not.
/// The value is not suppose to change over time and can be cached.
/// </summary>
public bool IsSampled { get; private set; }
public bool IsSampled { get; }
/// <summary>
/// Gets a map of attributes associated with the sampling decision.
/// </summary>
public IEnumerable<KeyValuePair<string, object>> Attributes { get; private set; }
public IEnumerable<KeyValuePair<string, object>> Attributes { get; }
/// <summary>
/// Compare two <see cref="Decision"/> for equality.
/// </summary>
/// <param name="decision1">First Decision to compare.</param>
/// <param name="decision2">Second Decision to compare.</param>
public static bool operator ==(Decision decision1, Decision decision2) => decision1.Equals(decision2);
/// <summary>
/// Compare two <see cref="Decision"/> for not equality.
/// </summary>
/// <param name="decision1">First Decision to compare.</param>
/// <param name="decision2">Second Decision to compare.</param>
public static bool operator !=(Decision decision1, Decision decision2) => !decision1.Equals(decision2);
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (!(obj is Decision))
{
return false;
}
var that = (Decision)obj;
return this.IsSampled == that.IsSampled && this.Attributes == that.Attributes;
}
/// <inheritdoc/>
public override int GetHashCode()
{
var result = 1;
result = (31 * result) + this.IsSampled.GetHashCode();
result = (31 * result) + this.Attributes.GetHashCode();
return result;
}
}
}

View File

@ -21,27 +21,27 @@ namespace OpenTelemetry.Trace
/// <summary>
/// Link associated with the span.
/// </summary>
public sealed class Link
public readonly struct Link
{
private static readonly IDictionary<string, object> EmptyAttributes = new Dictionary<string, object>();
/// <summary>
/// Initializes a new instance of the <see cref="Link"/> class.
/// Initializes a new instance of the <see cref="Link"/> struct.
/// </summary>
/// <param name="spanContext">Span context of a linked span.</param>
public Link(SpanContext spanContext)
public Link(in SpanContext spanContext)
: this(spanContext, EmptyAttributes)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Link"/> class.
/// Initializes a new instance of the <see cref="Link"/> struct.
/// </summary>
/// <param name="spanContext">Span context of a linked span.</param>
/// <param name="attributes">Link attributes.</param>
public Link(SpanContext spanContext, IDictionary<string, object> attributes)
public Link(in SpanContext spanContext, IDictionary<string, object> attributes)
{
this.Context = spanContext ?? SpanContext.BlankLocal;
this.Context = spanContext.IsValid ? spanContext : SpanContext.BlankLocal;
this.Attributes = attributes ?? EmptyAttributes;
}
@ -54,5 +54,41 @@ namespace OpenTelemetry.Trace
/// Gets the collection of attributes associated with the link.
/// </summary>
public IDictionary<string, object> Attributes { get; }
/// <summary>
/// Compare two <see cref="Link"/> for equality.
/// </summary>
/// <param name="link1">First link to compare.</param>
/// <param name="link2">Second link to compare.</param>
public static bool operator ==(Link link1, Link link2) => link1.Equals(link2);
/// <summary>
/// Compare two <see cref="Link"/> for not equality.
/// </summary>
/// <param name="link1">First link to compare.</param>
/// <param name="link2">Second link to compare.</param>
public static bool operator !=(Link link1, Link link2) => !link1.Equals(link2);
/// <inheritdoc />
public override bool Equals(object obj)
{
if (!(obj is Link))
{
return false;
}
Link that = (Link)obj;
return that.Context == this.Context &&
that.Attributes == this.Attributes;
}
/// <inheritdoc />
public override int GetHashCode()
{
var result = 1;
result = (31 * result) + this.Context.GetHashCode();
result = (31 * result) + this.Attributes.GetHashCode();
return result;
}
}
}

View File

@ -24,7 +24,7 @@ namespace OpenTelemetry.Trace
/// child <see cref="ISpan"/> and across process boundaries. It contains the identifiers <see cref="ActivityTraceId"/>
/// and <see cref="ActivitySpanId"/> associated with the <see cref="ISpan"/> and a set of <see cref="TraceOptions"/>.
/// </summary>
public sealed class SpanContext
public readonly struct SpanContext
{
/// <summary>
/// A blank <see cref="SpanContext"/> that can be used for no-op operations.
@ -37,7 +37,7 @@ namespace OpenTelemetry.Trace
public static readonly SpanContext BlankRemote = new SpanContext(default, default, ActivityTraceFlags.None, true);
/// <summary>
/// Initializes a new instance of the <see cref="SpanContext"/> class with the given identifiers and options.
/// Initializes a new instance of the <see cref="SpanContext"/> struct with the given identifiers and options.
/// </summary>
/// <param name="traceId">The <see cref="ActivityTraceId"/> to associate with the <see cref="SpanContext"/>.</param>
/// <param name="spanId">The <see cref="ActivitySpanId"/> to associate with the <see cref="SpanContext"/>.</param>
@ -45,7 +45,7 @@ namespace OpenTelemetry.Trace
/// associate with the <see cref="SpanContext"/>.</param>
/// <param name="isRemote">The value indicating whether this <see cref="SpanContext"/> was propagated from the remote parent.</param>
/// <param name="tracestate">The tracestate to associate with the <see cref="SpanContext"/>.</param>
public SpanContext(ActivityTraceId traceId, ActivitySpanId spanId, ActivityTraceFlags traceOptions, bool isRemote = false, IEnumerable<KeyValuePair<string, string>> tracestate = null)
public SpanContext(in ActivityTraceId traceId, in ActivitySpanId spanId, ActivityTraceFlags traceOptions, bool isRemote = false, IEnumerable<KeyValuePair<string, string>> tracestate = null)
{
this.TraceId = traceId;
this.SpanId = spanId;
@ -85,6 +85,20 @@ namespace OpenTelemetry.Trace
/// </summary>
public IEnumerable<KeyValuePair<string, string>> Tracestate { get; }
/// <summary>
/// Compare two <see cref="SpanContext"/> for equality.
/// </summary>
/// <param name="spanContext1">First SpanContext to compare.</param>
/// <param name="spanContext2">Second SpanContext to compare.</param>
public static bool operator ==(SpanContext spanContext1, SpanContext spanContext2) => spanContext1.Equals(spanContext2);
/// <summary>
/// Compare two <see cref="SpanContext"/> for not equality.
/// </summary>
/// <param name="spanContext1">First SpanContext to compare.</param>
/// <param name="spanContext2">Second SpanContext to compare.</param>
public static bool operator !=(SpanContext spanContext1, SpanContext spanContext2) => !spanContext1.Equals(spanContext2);
/// <inheritdoc/>
public override int GetHashCode()
{
@ -99,21 +113,18 @@ namespace OpenTelemetry.Trace
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == this)
{
return true;
}
if (!(obj is SpanContext))
{
return false;
}
var that = (SpanContext)obj;
return this.TraceId.Equals(that.TraceId)
&& this.SpanId.Equals(that.SpanId)
&& this.TraceOptions.Equals(that.TraceOptions)
&& this.Tracestate.Equals(that.Tracestate);
&& this.IsRemote == that.IsRemote
&& ((this.Tracestate == null && that.Tracestate == null) || (this.Tracestate != null && this.Tracestate.Equals(that.Tracestate)));
}
private bool IsTraceIdValid(ActivityTraceId traceId)

View File

@ -19,7 +19,7 @@ namespace OpenTelemetry.Trace
/// <summary>
/// Span execution status.
/// </summary>
public struct Status
public readonly struct Status
{
/// <summary>
/// The operation completed successfully.
@ -153,7 +153,7 @@ namespace OpenTelemetry.Trace
/// Gets a value indicating whether this is a valid-to-use status.
/// Only status instances created with a CanonicalCode (optional Description) are considered valid.
/// </summary>
public bool IsValid { get; private set; }
public bool IsValid { get; }
/// <summary>
/// Gets the canonical code from this status.
@ -168,13 +168,21 @@ namespace OpenTelemetry.Trace
/// <summary>
/// Gets a value indicating whether span completed sucessfully.
/// </summary>
public bool IsOk
{
get
{
return this.CanonicalCode == CanonicalCode.Ok;
}
}
public bool IsOk => this.CanonicalCode == CanonicalCode.Ok;
/// <summary>
/// Compare two <see cref="Status"/> for equality.
/// </summary>
/// <param name="status1">First Status to compare.</param>
/// <param name="status2">Second Status to compare.</param>
public static bool operator ==(Status status1, Status status2) => status1.Equals(status2);
/// <summary>
/// Compare two <see cref="Status"/> for not equality.
/// </summary>
/// <param name="status1">First Status to compare.</param>
/// <param name="status2">Second Status to compare.</param>
public static bool operator !=(Status status1, Status status2) => !status1.Equals(status2);
/// <summary>
/// Returns a new instance of a status with the description populated.

View File

@ -99,9 +99,16 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
refs = span.Links.Select(l => l.ToJaegerSpanRef()).Where(l => l != null).AsEnumerable();
}
var traceId = span?.Context?.TraceId == null ? Int128.Empty : new Int128(span.Context.TraceId);
var spanId = span?.Context?.SpanId == null ? Int128.Empty : new Int128(span.Context.SpanId);
var parentSpanId = span?.ParentSpanId == null ? Int128.Empty : new Int128(span.ParentSpanId);
var traceId = Int128.Empty;
var spanId = Int128.Empty;
var parentSpanId = Int128.Empty;
if (span != null && span.Context.IsValid)
{
traceId = new Int128(span.Context.TraceId);
spanId = new Int128(span.Context.SpanId);
parentSpanId = new Int128(span.ParentSpanId);
}
return new JaegerSpan
{
@ -157,7 +164,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
var traceId = Int128.Empty;
var spanId = Int128.Empty;
if (link != null)
if (link != default)
{
traceId = new Int128(link.Context.TraceId);
spanId = new Int128(link.Context.SpanId);

View File

@ -87,7 +87,7 @@ namespace OpenTelemetry.Shims.OpenTracing
private global::OpenTracing.IScopeManager ScopeManager { get; }
private bool ParentSet => this.parentSpan != null || (this.parentSpanContext != null && this.parentSpanContext.IsValid);
private bool ParentSet => this.parentSpan != null || this.parentSpanContext.IsValid;
/// <inheritdoc/>
public ISpanBuilder AsChildOf(ISpanContext parent)
@ -176,11 +176,11 @@ namespace OpenTelemetry.Shims.OpenTracing
{
span = this.tracer.StartSpan(this.spanName, this.parentSpan, this.spanKind, options);
}
else if (this.parentSpanContext != null && this.parentSpanContext.IsValid)
else if (this.parentSpanContext.IsValid)
{
span = this.tracer.StartSpan(this.spanName, this.parentSpanContext, this.spanKind, options);
}
else if (this.parentSpan == null && (this.parentSpanContext == null || !this.parentSpanContext.IsValid) && (this.tracer.CurrentSpan == null || this.tracer.CurrentSpan == Trace.BlankSpan.Instance))
else if (this.parentSpan == null && !this.parentSpanContext.IsValid && (this.tracer.CurrentSpan == null || this.tracer.CurrentSpan == Trace.BlankSpan.Instance))
{
// We need to know if we should inherit an existing Activity-based context or start a new one.
if (System.Diagnostics.Activity.Current != null && System.Diagnostics.Activity.Current.IdFormat == System.Diagnostics.ActivityIdFormat.W3C)

View File

@ -22,13 +22,8 @@ namespace OpenTelemetry.Shims.OpenTracing
{
public sealed class SpanContextShim : ISpanContext
{
public SpanContextShim(Trace.SpanContext spanContext)
public SpanContextShim(in Trace.SpanContext spanContext)
{
if (spanContext == null)
{
throw new ArgumentNullException(nameof(spanContext));
}
if (!spanContext.IsValid)
{
throw new ArgumentException(nameof(spanContext));

View File

@ -46,11 +46,6 @@ namespace OpenTelemetry.Shims.OpenTracing
{
this.Span = span ?? throw new ArgumentNullException(nameof(span));
if (this.Span.Context == null)
{
throw new ArgumentNullException(nameof(this.Span.Context));
}
if (!this.Span.Context.IsValid)
{
throw new ArgumentException(nameof(this.Span.Context));

View File

@ -60,7 +60,7 @@ namespace OpenTelemetry.Shims.OpenTracing
throw new ArgumentNullException(nameof(carrier));
}
Trace.SpanContext spanContext = null;
Trace.SpanContext spanContext = default;
if ((format == BuiltinFormats.TextMap || format == BuiltinFormats.HttpHeaders) && carrier is ITextMap textMapCarrier)
{
@ -81,18 +81,21 @@ namespace OpenTelemetry.Shims.OpenTracing
return value;
}
spanContext = this.tracer.TextFormat?.Extract(carrierMap, GetCarrierKeyValue);
if (this.tracer.TextFormat != null)
{
spanContext = this.tracer.TextFormat.Extract(carrierMap, GetCarrierKeyValue);
}
}
else if (format == BuiltinFormats.Binary && carrier is IBinary binaryCarrier)
{
var ms = binaryCarrier.Get();
if (ms != null)
if (ms != null && this.tracer.BinaryFormat != null)
{
spanContext = this.tracer.BinaryFormat?.FromByteArray(ms.ToArray());
spanContext = this.tracer.BinaryFormat.FromByteArray(ms.ToArray());
}
}
return (spanContext == null || !spanContext.IsValid) ? null : new SpanContextShim(spanContext);
return !spanContext.IsValid ? null : new SpanContextShim(spanContext);
}
/// <inheritdoc/>

View File

@ -112,12 +112,6 @@ namespace OpenTelemetry.Context.Propagation
/// <inheritdoc/>
public void Inject<T>(SpanContext spanContext, T carrier, Action<T, string, string> setter)
{
if (spanContext == null)
{
OpenTelemetrySdkEventSource.Log.FailedToInjectContext("null context");
return;
}
if (!spanContext.IsValid)
{
OpenTelemetrySdkEventSource.Log.FailedToInjectContext("invalid context");

View File

@ -42,6 +42,6 @@ namespace OpenTelemetry.Trace
/// <param name="attributes">Initial set of Attributes for the Span being constructed.</param>
/// <param name="links">Links associated with the span.</param>
/// <returns>Sampling decision on whether Span needs to be sampled or not.</returns>
public abstract Decision ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> links);
public abstract Decision ShouldSample(in SpanContext parentContext, in ActivityTraceId traceId, in ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> links);
}
}

View File

@ -23,9 +23,9 @@ namespace OpenTelemetry.Trace.Samplers
public override string Description { get; } = nameof(AlwaysParentSampler);
/// <inheritdoc />
public override Decision ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> parentLinks)
public override Decision ShouldSample(in SpanContext parentContext, in ActivityTraceId traceId, in ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> parentLinks)
{
if (parentContext != null && parentContext.TraceOptions.HasFlag(ActivityTraceFlags.Recorded))
if (parentContext.IsValid && parentContext.TraceOptions.HasFlag(ActivityTraceFlags.Recorded))
{
return new Decision(true);
}

View File

@ -23,7 +23,7 @@ namespace OpenTelemetry.Trace.Samplers
public override string Description { get; } = nameof(AlwaysSampleSampler);
/// <inheritdoc />
public override Decision ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> parentLinks)
public override Decision ShouldSample(in SpanContext parentContext, in ActivityTraceId traceId, in ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> parentLinks)
{
return new Decision(true);
}

View File

@ -23,7 +23,7 @@ namespace OpenTelemetry.Trace.Samplers
public override string Description { get; } = nameof(NeverSampleSampler);
/// <inheritdoc />
public override Decision ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> links)
public override Decision ShouldSample(in SpanContext parentContext, in ActivityTraceId traceId, in ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> links)
{
return new Decision(false);
}

View File

@ -57,11 +57,10 @@ namespace OpenTelemetry.Trace.Samplers
public override string Description { get; }
/// <inheritdoc />
public override Decision ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> links)
public override Decision ShouldSample(in SpanContext parentContext, in ActivityTraceId traceId, in ActivitySpanId spanId, string name, IDictionary<string, object> attributes, IEnumerable<Link> links)
{
// If the parent is sampled keep the sampling decision.
if (parentContext != null &&
parentContext.IsValid &&
if (parentContext.IsValid &&
(parentContext.TraceOptions & ActivityTraceFlags.Recorded) != 0)
{
return new Decision(true);

View File

@ -614,7 +614,7 @@ namespace OpenTelemetry.Trace
var activity = new Activity(spanName);
IEnumerable<KeyValuePair<string, string>> tracestate = null;
if (parentContext != null && parentContext.IsValid)
if (parentContext.IsValid)
{
activity.SetParentId(parentContext.TraceId,
parentContext.SpanId,
@ -675,7 +675,7 @@ namespace OpenTelemetry.Trace
activity.ActivityTraceFlags);
}
return null;
return SpanContext.BlankLocal;
}
private void SetLinks(IEnumerable<Link> links)

View File

@ -103,7 +103,7 @@ namespace OpenTelemetry.Trace
/// <inheritdoc/>
public override ISpan StartSpan(string operationName, in SpanContext parent, SpanKind kind, SpanCreationOptions options)
{
if (parent != null)
if (parent.IsValid)
{
return Span.CreateFromParentContext(operationName, parent, kind, options, this.sampler, this.tracerConfiguration,
this.spanProcessor, this.LibraryResource);

View File

@ -115,7 +115,9 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
});
var spanContextSetter = typeof(Span).GetMethod("set_Context", BindingFlags.Instance | BindingFlags.NonPublic);
spanContextSetter.Invoke(span, new []{ new SpanContext(traceId, ActivitySpanId.CreateFromString(spanId.AsSpan()), ActivityTraceFlags.Recorded) });
ActivitySpanId activitySpanId = ActivitySpanId.CreateFromString(spanId.AsSpan());
spanContextSetter.Invoke(span, new []{ (object)new SpanContext(in traceId, in activitySpanId, ActivityTraceFlags.Recorded) });
foreach (var attribute in attributes)
{

View File

@ -25,8 +25,9 @@ namespace OpenTelemetry.Shims.OpenTracing.Tests
[Fact]
public void CtorArgumentValidation()
{
Assert.Throws<ArgumentNullException>(() => new SpanContextShim(null));
Assert.Throws<ArgumentException>(() => new SpanContextShim(default));
Assert.Throws<ArgumentException>(() => new SpanContextShim(SpanContext.BlankLocal));
Assert.Throws<ArgumentException>(() => new SpanContextShim(SpanContext.BlankRemote));
Assert.Throws<ArgumentException>(() => new SpanContextShim(new SpanContext(default, default, ActivityTraceFlags.None)));
}

View File

@ -24,7 +24,6 @@ namespace OpenTelemetry.Trace.Test
{
private readonly IDictionary<string, object> attributesMap = new Dictionary<string, object>();
private readonly SpanContext spanContext;
public LinkTest()
{
@ -53,6 +52,46 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(attributesMap, link.Attributes);
}
[Fact]
public void Equality()
{
var link1 = new Link(spanContext);
var link2 = new Link(spanContext);
Assert.Equal(link1, link2);
Assert.True(link1 == link2);
}
[Fact]
public void Equality_WithAttributes()
{
var link1 = new Link(spanContext, attributesMap);
var link2 = new Link(spanContext, attributesMap);
Assert.Equal(link1, link2);
Assert.True(link1 == link2);
}
[Fact]
public void NotEquality()
{
var link1 = new Link(new SpanContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None));
var link2 = new Link(new SpanContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None));
Assert.NotEqual(link1, link2);
Assert.True(link1 != link2);
}
[Fact]
public void NotEquality_WithAttributes()
{
var link1 = new Link(spanContext, new Dictionary<string, object>());
var link2 = new Link(spanContext, this.attributesMap);
Assert.NotEqual(link1, link2);
Assert.True(link1 != link2);
}
public void Dispose()
{
Activity.Current = null;

View File

@ -15,7 +15,6 @@
// </copyright>
using System.Diagnostics;
using OpenTelemetry.Trace;
using System;
using Xunit;
namespace OpenTelemetry.Context.Propagation.Test
@ -53,14 +52,21 @@ namespace OpenTelemetry.Context.Propagation.Test
TestSpanContextConversion(new SpanContext(TraceId, SpanId, ActivityTraceFlags.None));
}
[Fact]
public void ToBinaryValue_NullSpanContext()
public void ToBinaryValue_InvalidSpanContext_Default()
{
Assert.Empty(binaryFormat.ToByteArray(null));
Assert.Empty(binaryFormat.ToByteArray(default));
}
[Fact]
public void ToBinaryValue_InvalidSpanContext()
public void ToBinaryValue_InvalidSpanContext_Remote()
{
Assert.Empty(binaryFormat.ToByteArray(SpanContext.BlankRemote));
}
[Fact]
public void ToBinaryValue_InvalidSpanContext_Local()
{
Assert.Empty(binaryFormat.ToByteArray(SpanContext.BlankLocal));
}

View File

@ -126,7 +126,7 @@ namespace OpenTelemetry.Tests.Impl.Trace
Assert.Equal(SpanKind.Server, span.Kind);
Assert.Equal(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -157,7 +157,7 @@ namespace OpenTelemetry.Tests.Impl.Trace
Assert.Equal(SpanKind.Server, span.Kind);
Assert.Equal(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -188,7 +188,7 @@ namespace OpenTelemetry.Tests.Impl.Trace
Assert.Equal(SpanKind.Client, span.Kind);
Assert.Equal(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -215,7 +215,7 @@ namespace OpenTelemetry.Tests.Impl.Trace
Assert.Equal(activity.StartTimeUtc, span.StartTimestamp.DateTime);
Assert.Equal(activity, span.Activity);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -248,7 +248,7 @@ namespace OpenTelemetry.Tests.Impl.Trace
Assert.Equal(SpanKind.Consumer, span.Kind);
Assert.Equal(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
}

View File

@ -238,7 +238,7 @@ namespace OpenTelemetry.Trace.Samplers.Test
});
Assert.True(
defaultProbability.ShouldSample(
null,
default,
sampledtraceId,
ActivitySpanId.CreateRandom(),
SpanName,

View File

@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System.Collections.Generic;
using System.Diagnostics;
using Xunit;
@ -20,25 +22,23 @@ namespace OpenTelemetry.Trace.Test
{
public class SpanContextTest
{
private static readonly byte[] firstTraceIdBytes =
new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)'a' };
private static readonly byte[] firstTraceIdBytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)'a' };
private static readonly byte[] secondTraceIdBytes =
new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)'0', 0, 0, 0, 0, 0, 0, 0, 0 };
private static readonly byte[] secondTraceIdBytes = { 0, 0, 0, 0, 0, 0, 0, (byte)'0', 0, 0, 0, 0, 0, 0, 0, 0 };
private static readonly byte[] firstSpanIdBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)'a' };
private static readonly byte[] secondSpanIdBytes = new byte[] { (byte)'0', 0, 0, 0, 0, 0, 0, 0 };
private static readonly byte[] firstSpanIdBytes = { 0, 0, 0, 0, 0, 0, 0, (byte)'a' };
private static readonly byte[] secondSpanIdBytes = { (byte)'0', 0, 0, 0, 0, 0, 0, 0 };
private static readonly SpanContext first =
new SpanContext(
ActivityTraceId.CreateFromBytes(firstTraceIdBytes),
ActivitySpanId.CreateFromBytes(firstSpanIdBytes),
ActivityTraceFlags.None);
new SpanContext(
ActivityTraceId.CreateFromBytes(firstTraceIdBytes),
ActivitySpanId.CreateFromBytes(firstSpanIdBytes),
ActivityTraceFlags.None);
private static readonly SpanContext second =
new SpanContext(
ActivityTraceId.CreateFromBytes(secondTraceIdBytes),
ActivitySpanId.CreateFromBytes(secondSpanIdBytes),
ActivityTraceFlags.Recorded);
new SpanContext(
ActivityTraceId.CreateFromBytes(secondTraceIdBytes),
ActivitySpanId.CreateFromBytes(secondSpanIdBytes),
ActivityTraceFlags.Recorded);
[Fact]
public void InvalidSpanContext()
@ -84,5 +84,103 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(ActivityTraceFlags.None, first.TraceOptions);
Assert.Equal(ActivityTraceFlags.Recorded, second.TraceOptions);
}
[Fact]
public void Equality1()
{
var traceId = ActivityTraceId.CreateRandom();
var spanId = ActivitySpanId.CreateRandom();
var context1 = new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded);
var context2 = new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded);
Assert.Equal(context1, context2);
Assert.True(context1 == context2);
}
[Fact]
public void Equality2()
{
var traceId = ActivityTraceId.CreateRandom();
var spanId = ActivitySpanId.CreateRandom();
var context1 = new SpanContext(traceId, spanId, ActivityTraceFlags.None, true);
var context2 = new SpanContext(traceId, spanId, ActivityTraceFlags.None, true);
Assert.Equal(context1, context2);
Assert.True(context1 == context2);
}
[Fact]
public void Equality3()
{
var traceId = ActivityTraceId.CreateRandom();
var spanId = ActivitySpanId.CreateRandom();
IEnumerable<KeyValuePair<string, string>> tracestate = new List<KeyValuePair<string, string>>();
var context1 = new SpanContext(traceId, spanId, ActivityTraceFlags.None, false, tracestate);
var context2 = new SpanContext(traceId, spanId, ActivityTraceFlags.None, false, tracestate);
Assert.Equal(context1, context2);
Assert.True(context1 == context2);
}
[Fact]
public void Not_Equality1()
{
var spanId = ActivitySpanId.CreateRandom();
var context1 = new SpanContext(ActivityTraceId.CreateRandom(), spanId, ActivityTraceFlags.Recorded);
var context2 = new SpanContext(ActivityTraceId.CreateRandom(), spanId, ActivityTraceFlags.Recorded);
Assert.NotEqual(context1, context2);
Assert.True(context1 != context2);
}
[Fact]
public void Not_Equality2()
{
var traceId = ActivityTraceId.CreateRandom();
var context1 = new SpanContext(traceId, ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, true);
var context2 = new SpanContext(traceId, ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, true);
Assert.NotEqual(context1, context2);
Assert.True(context1 != context2);
}
[Fact]
public void Not_Equality3()
{
var traceId = ActivityTraceId.CreateRandom();
var spanId = ActivitySpanId.CreateRandom();
IEnumerable<KeyValuePair<string, string>> tracestate = new List<KeyValuePair<string, string>>();
var context1 = new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded, false, tracestate);
var context2 = new SpanContext(traceId, spanId, ActivityTraceFlags.None, false, tracestate);
Assert.NotEqual(context1, context2);
Assert.True(context1 != context2);
}
[Fact]
public void Not_Equality4()
{
var traceId = ActivityTraceId.CreateRandom();
var spanId = ActivitySpanId.CreateRandom();
IEnumerable<KeyValuePair<string, string>> tracestate = new List<KeyValuePair<string, string>>();
var context1 = new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded, true, tracestate);
var context2 = new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded, false, tracestate);
Assert.NotEqual(context1, context2);
Assert.True(context1 != context2);
}
[Fact]
public void Not_Equality5()
{
var traceId = ActivityTraceId.CreateRandom();
var spanId = ActivitySpanId.CreateRandom();
IEnumerable<KeyValuePair<string, string>> tracestate = new List<KeyValuePair<string, string>>();
var context1 = new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded, true, null);
var context2 = new SpanContext(traceId, spanId, ActivityTraceFlags.Recorded, false, tracestate);
Assert.NotEqual(context1, context2);
Assert.True(context1 != context2);
}
}
}

View File

@ -146,7 +146,7 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(SpanKind.Server, span.Kind);
AssertApproxSameTimestamp(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -164,7 +164,7 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(SpanKind.Server, span.Kind);
AssertApproxSameTimestamp(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -269,7 +269,7 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(SpanKind.Server, span.Kind);
Assert.Equal(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -365,7 +365,7 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(SpanKind.Server, span.Kind);
AssertApproxSameTimestamp(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
[Fact]
@ -384,8 +384,8 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(SpanKind.Server, span.Kind);
AssertApproxSameTimestamp(startTimestamp, span.StartTimestamp);
Assert.Equal(2, span.Links.Count());
Assert.Same(firstLinkContext, span.Links.First().Context);
Assert.Same(secondLinkContext, span.Links.Last().Context);
Assert.Equal(firstLinkContext, span.Links.First().Context);
Assert.Equal(secondLinkContext, span.Links.Last().Context);
}
[Fact]
@ -495,8 +495,8 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(activity.StartTimeUtc, span.StartTimestamp.DateTime);
Assert.Equal(activity, span.Activity);
Assert.Equal(2, span.Links.Count());
Assert.Same(firstLinkContext, span.Links.First().Context);
Assert.Same(secondLinkContext, span.Links.Last().Context);
Assert.Equal(firstLinkContext, span.Links.First().Context);
Assert.Equal(secondLinkContext, span.Links.Last().Context);
}
[Fact]
@ -555,7 +555,7 @@ namespace OpenTelemetry.Trace.Test
AssertApproxSameTimestamp(startTime, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.First().Context);
Assert.Equal(linkContext, span.Links.First().Context);
}
[Fact]
@ -711,7 +711,7 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(SpanKind.Server, span.Kind);
Assert.Equal(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
}
@ -732,7 +732,7 @@ namespace OpenTelemetry.Trace.Test
Assert.Equal(SpanKind.Server, span.Kind);
Assert.Equal(startTimestamp, span.StartTimestamp);
Assert.Single(span.Links);
Assert.Same(linkContext, span.Links.Single().Context);
Assert.Equal(linkContext, span.Links.Single().Context);
}
}
@ -783,7 +783,7 @@ namespace OpenTelemetry.Trace.Test
.Setup(s => s.OnStart(It.IsAny<Span>()))
.Callback<Span>(s =>
{
spanPassedToSpanProcessorHasSpanContext = s.Context != null;
spanPassedToSpanProcessorHasSpanContext = s.Context.IsValid;
});
var span = (Span)tracer.StartSpan(SpanName, SpanKind.Client, new SpanCreationOptions { StartTimestamp = startTime, LinksFactory = () => new[] { link } });
@ -1437,9 +1437,9 @@ namespace OpenTelemetry.Trace.Test
.GetTracer(null);
samplerMock.Setup(s => s.ShouldSample(
It.IsAny<SpanContext>(),
It.IsAny<ActivityTraceId>(),
It.IsAny<ActivitySpanId>(),
in It.Ref<SpanContext>.IsAny,
in It.Ref<ActivityTraceId>.IsAny,
in It.Ref<ActivitySpanId>.IsAny,
It.IsAny<string>(),
It.IsAny<IDictionary<string, object>>(),
It.IsAny<IEnumerable<Link>>())).Returns(new Decision(true));
@ -1448,9 +1448,9 @@ namespace OpenTelemetry.Trace.Test
span.Attributes.AssertAreSame(this.attributes);
samplerMock.Verify(o => o.ShouldSample(
It.IsAny<SpanContext>(),
It.IsAny<ActivityTraceId>(),
It.IsAny<ActivitySpanId>(),
in It.Ref<SpanContext>.IsAny,
in It.Ref<ActivityTraceId>.IsAny,
in It.Ref<ActivitySpanId>.IsAny,
It.IsAny<string>(),
It.Is<IDictionary<string, object>>(a => a == this.attributes),
It.IsAny<IEnumerable<Link>>()), Times.Once);
@ -1466,9 +1466,9 @@ namespace OpenTelemetry.Trace.Test
.GetTracer(null);
samplerMock.Setup(s => s.ShouldSample(
It.IsAny<SpanContext>(),
It.IsAny<ActivityTraceId>(),
It.IsAny<ActivitySpanId>(),
in It.Ref<SpanContext>.IsAny,
in It.Ref<ActivityTraceId>.IsAny,
in It.Ref<ActivitySpanId>.IsAny,
It.IsAny<string>(),
It.IsAny<IDictionary<string, object>>(),
It.IsAny<IEnumerable<Link>>())).Returns(new Decision(false));
@ -1477,9 +1477,9 @@ namespace OpenTelemetry.Trace.Test
Assert.Empty(span.Attributes);
samplerMock.Verify(o => o.ShouldSample(
It.IsAny<SpanContext>(),
It.IsAny<ActivityTraceId>(),
It.IsAny<ActivitySpanId>(),
in It.Ref<SpanContext>.IsAny,
in It.Ref<ActivityTraceId>.IsAny,
in It.Ref<ActivitySpanId>.IsAny,
It.IsAny<string>(),
It.Is<IDictionary<string, object>>(a => a == this.attributes),
It.IsAny<IEnumerable<Link>>()), Times.Once);

View File

@ -37,15 +37,56 @@ namespace OpenTelemetry.Trace.Test
}
[Fact]
public void Status_EqualsAndHashCode()
public void Equality()
{
// EqualsTester tester = new EqualsTester();
// tester.addEqualityGroup(Status.OK, Status.OK.withDescription(null));
// tester.addEqualityGroup(
// Status.CANCELLED.withDescription("ThisIsAnError"),
// Status.CANCELLED.withDescription("ThisIsAnError"));
// tester.addEqualityGroup(Status.UNKNOWN.withDescription("This is an error."));
// tester.testEquals();
var status1 = new Status(CanonicalCode.Ok);
var status2 = new Status(CanonicalCode.Ok);
Assert.Equal(status1, status2);
Assert.True(status1 == status2);
}
[Fact]
public void Equality_WithDescription()
{
var status1 = new Status(CanonicalCode.Unknown, "error");
var status2 = new Status(CanonicalCode.Unknown, "error");
Assert.Equal(status1, status2);
Assert.True(status1 == status2);
}
[Fact]
public void Not_Equality()
{
var status1 = new Status(CanonicalCode.Ok);
var status2 = new Status(CanonicalCode.Unknown);
Assert.NotEqual(status1, status2);
Assert.True(status1 != status2);
}
[Fact]
public void Not_Equality_WithDescription1()
{
var status1 = new Status(CanonicalCode.Ok, "ok");
var status2 = new Status(CanonicalCode.Unknown, "error");
Assert.NotEqual(status1, status2);
Assert.True(status1 != status2);
}
[Fact]
public void Not_Equality_WithDescription2()
{
var status1 = new Status(CanonicalCode.Ok);
var status2 = new Status(CanonicalCode.Unknown, "error");
Assert.NotEqual(status1, status2);
Assert.True(status1 != status2);
}
}
}

View File

@ -22,7 +22,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
<PackageReference Include="Moq" Version="4.11.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>