221 lines
7.4 KiB
C#
221 lines
7.4 KiB
C#
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
using System.Diagnostics;
|
|
using OpenTelemetry.Context.Propagation;
|
|
using Xunit;
|
|
|
|
namespace OpenTelemetry.Extensions.Propagators.Tests;
|
|
|
|
public class JaegerPropagatorTest
|
|
{
|
|
private const string JaegerHeader = "uber-trace-id";
|
|
private const string JaegerDelimiter = ":";
|
|
private const string JaegerDelimiterEncoded = "%3A";
|
|
|
|
private const string TraceId = "0007651916cd43dd8448eb211c803177";
|
|
private const string TraceIdShort = "7651916cd43dd8448eb211c803177";
|
|
private const string SpanId = "0007c989f9791877";
|
|
private const string SpanIdShort = "7c989f9791877";
|
|
private const string ParentSpanId = "0";
|
|
private const string FlagSampled = "1";
|
|
private const string FlagNotSampled = "0";
|
|
|
|
private static readonly Func<IDictionary<string, string[]>, string, IEnumerable<string>> Getter = (headers, name) =>
|
|
{
|
|
if (headers.TryGetValue(name, out var value))
|
|
{
|
|
return value;
|
|
}
|
|
|
|
return Array.Empty<string>();
|
|
};
|
|
|
|
private static readonly Action<IDictionary<string, string>, string, string> Setter = (carrier, name, value) =>
|
|
{
|
|
carrier[name] = value;
|
|
};
|
|
|
|
[Fact]
|
|
public void ExtractReturnsOriginalContextIfContextIsAlreadyValid()
|
|
{
|
|
// arrange
|
|
var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan());
|
|
var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan());
|
|
var propagationContext = new PropagationContext(
|
|
new ActivityContext(traceId, spanId, ActivityTraceFlags.Recorded, isRemote: true),
|
|
default);
|
|
|
|
var headers = new Dictionary<string, string[]>();
|
|
|
|
// act
|
|
var result = new JaegerPropagator().Extract(propagationContext, headers, Getter);
|
|
|
|
// assert
|
|
Assert.Equal(propagationContext, result);
|
|
}
|
|
|
|
[Fact]
|
|
public void ExtractReturnsOriginalContextIfCarrierIsNull()
|
|
{
|
|
// arrange
|
|
var propagationContext = default(PropagationContext);
|
|
|
|
// act
|
|
var result = new JaegerPropagator().Extract(propagationContext, null, Getter!);
|
|
|
|
// assert
|
|
Assert.Equal(propagationContext, result);
|
|
}
|
|
|
|
[Fact]
|
|
public void ExtractReturnsOriginalContextIfGetterIsNull()
|
|
{
|
|
// arrange
|
|
var propagationContext = default(PropagationContext);
|
|
|
|
var headers = new Dictionary<string, string[]>();
|
|
|
|
// act
|
|
var result = new JaegerPropagator().Extract(propagationContext, headers, null!);
|
|
|
|
// assert
|
|
Assert.Equal(propagationContext, result);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("", SpanId, ParentSpanId, FlagSampled, JaegerDelimiter)]
|
|
[InlineData(TraceId, "", ParentSpanId, FlagSampled, JaegerDelimiter)]
|
|
[InlineData(TraceId, SpanId, "", FlagSampled, JaegerDelimiter)]
|
|
[InlineData(TraceId, SpanId, ParentSpanId, "", JaegerDelimiter)]
|
|
[InlineData(TraceId, SpanId, ParentSpanId, FlagSampled, "")]
|
|
[InlineData("invalid trace id", SpanId, ParentSpanId, FlagSampled, JaegerDelimiter)]
|
|
[InlineData(TraceId, "invalid span id", ParentSpanId, FlagSampled, JaegerDelimiter)]
|
|
[InlineData(TraceId, SpanId, $"too many {JaegerDelimiter} records", FlagSampled, JaegerDelimiter)]
|
|
public void ExtractReturnsOriginalContextIfHeaderIsNotValid(string traceId, string spanId, string parentSpanId, string flags, string delimiter)
|
|
{
|
|
// arrange
|
|
var propagationContext = default(PropagationContext);
|
|
|
|
var formattedHeader = string.Join(
|
|
delimiter,
|
|
traceId,
|
|
spanId,
|
|
parentSpanId,
|
|
flags);
|
|
|
|
var headers = new Dictionary<string, string[]> { { JaegerHeader, new[] { formattedHeader } } };
|
|
|
|
// act
|
|
var result = new JaegerPropagator().Extract(propagationContext, headers, Getter);
|
|
|
|
// assert
|
|
Assert.Equal(propagationContext, result);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(TraceId, SpanId, ParentSpanId, FlagSampled, JaegerDelimiter)]
|
|
[InlineData(TraceIdShort, SpanIdShort, ParentSpanId, FlagNotSampled, JaegerDelimiterEncoded)]
|
|
public void ExtractReturnsNewContextIfHeaderIsValid(string traceId, string spanId, string parentSpanId, string flags, string delimiter)
|
|
{
|
|
// arrange
|
|
var propagationContext = default(PropagationContext);
|
|
|
|
var formattedHeader = string.Join(
|
|
delimiter,
|
|
traceId,
|
|
spanId,
|
|
parentSpanId,
|
|
flags);
|
|
|
|
var headers = new Dictionary<string, string[]> { { JaegerHeader, new[] { formattedHeader } } };
|
|
|
|
// act
|
|
var result = new JaegerPropagator().Extract(propagationContext, headers, Getter);
|
|
|
|
// assert
|
|
Assert.Equal(traceId.PadLeft(TraceId.Length, '0'), result.ActivityContext.TraceId.ToString());
|
|
Assert.Equal(spanId.PadLeft(SpanId.Length, '0'), result.ActivityContext.SpanId.ToString());
|
|
Assert.Equal(flags == "1" ? ActivityTraceFlags.Recorded : ActivityTraceFlags.None, result.ActivityContext.TraceFlags);
|
|
}
|
|
|
|
[Fact]
|
|
public void InjectDoesNoopIfContextIsInvalid()
|
|
{
|
|
// arrange
|
|
var propagationContext = default(PropagationContext);
|
|
|
|
var headers = new Dictionary<string, string>();
|
|
|
|
// act
|
|
new JaegerPropagator().Inject(propagationContext, headers, Setter);
|
|
|
|
// assert
|
|
Assert.Empty(headers);
|
|
}
|
|
|
|
[Fact]
|
|
public void InjectDoesNoopIfCarrierIsNull()
|
|
{
|
|
// arrange
|
|
var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan());
|
|
var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan());
|
|
var propagationContext = new PropagationContext(
|
|
new ActivityContext(traceId, spanId, ActivityTraceFlags.Recorded, isRemote: true),
|
|
default);
|
|
|
|
// act
|
|
new JaegerPropagator().Inject(propagationContext, null, Setter!);
|
|
|
|
// assert
|
|
}
|
|
|
|
[Fact]
|
|
public void InjectDoesNoopIfSetterIsNull()
|
|
{
|
|
// arrange
|
|
var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan());
|
|
var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan());
|
|
var propagationContext = new PropagationContext(
|
|
new ActivityContext(traceId, spanId, ActivityTraceFlags.Recorded, isRemote: true),
|
|
default);
|
|
|
|
var headers = new Dictionary<string, string>();
|
|
|
|
// act
|
|
new JaegerPropagator().Inject(propagationContext, headers, null!);
|
|
|
|
// assert
|
|
Assert.Empty(headers);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(FlagSampled)]
|
|
[InlineData(FlagNotSampled)]
|
|
public void InjectWillAddJaegerFormattedTraceToCarrier(string sampledFlag)
|
|
{
|
|
// arrange
|
|
var traceId = ActivityTraceId.CreateFromString(TraceId.AsSpan());
|
|
var spanId = ActivitySpanId.CreateFromString(SpanId.AsSpan());
|
|
var flags = sampledFlag == "1" ? ActivityTraceFlags.Recorded : ActivityTraceFlags.None;
|
|
|
|
var propagationContext = new PropagationContext(new ActivityContext(traceId, spanId, flags, isRemote: true), default);
|
|
|
|
var expectedValue = string.Join(
|
|
JaegerDelimiter,
|
|
traceId,
|
|
spanId,
|
|
ParentSpanId,
|
|
sampledFlag);
|
|
|
|
var headers = new Dictionary<string, string>();
|
|
|
|
// act
|
|
new JaegerPropagator().Inject(propagationContext, headers, Setter);
|
|
|
|
// assert
|
|
Assert.Single(headers);
|
|
Assert.Equal(expectedValue, headers[JaegerHeader]);
|
|
}
|
|
}
|