public void CreateFromString_CreatesIdCorrectly() { var traceId = TraceId.CreateRandom(); var recreatedId = TraceId.CreateFromString(traceId.ToString()); recreatedId.Should().Be(traceId); }
public SpanContext Extract <T>(T carrier, Func <T, string, IEnumerable <string> > getter) { var traceParentCollection = getter(carrier, W3CHeaderNames.TraceParent).ToList(); if (traceParentCollection.Count != 1) { Log.Warning("Header {HeaderName} needs exactly 1 value", W3CHeaderNames.TraceParent); return(null); } var traceParentHeader = traceParentCollection.First(); var traceIdString = traceParentHeader.Substring(VersionPrefixIdLength, TraceIdLength); var traceId = TraceId.CreateFromString(traceIdString); if (traceId == TraceId.Zero) { Log.Warning("Could not parse {HeaderName} headers: {HeaderValues}", W3CHeaderNames.TraceParent, string.Join(",", traceParentCollection)); return(null); } var spanIdString = traceParentHeader.Substring(VersionAndTraceIdLength, SpanIdLength); if (!ulong.TryParse(spanIdString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var spanId)) { Log.Warning("Could not parse {HeaderName} headers: {HeaderValues}", W3CHeaderNames.TraceParent, string.Join(",", traceParentCollection)); return(null); } var traceStateCollection = getter(carrier, W3CHeaderNames.TraceState); var traceState = ExtractTraceState(traceStateCollection); return(spanId == 0 ? null : new SpanContext(traceId, spanId, samplingPriority: null, serviceName: null, traceState)); }
internal void HttpRequestMessage_InjectExtract_Identity_WithParent(IHeadersCollection headers) { var traceId = TraceId.CreateFromString("52686470458518446744073709551615"); const ulong spanId = 18446744073709551614; const SamplingPriority samplingPriority = SamplingPriority.UserKeep; var parentContext = new SpanContext(traceId, spanId, samplingPriority); var traceContext = new TraceContext(null) { SamplingPriority = samplingPriority }; var context = new SpanContext(parentContext, traceContext, null); _propagator.Inject(context, headers); AssertExpected(headers, B3HttpHeaderNames.B3TraceId, "52686470458518446744073709551615"); AssertExpected(headers, B3HttpHeaderNames.B3SpanId, context.SpanId.ToString("x16")); AssertExpected(headers, B3HttpHeaderNames.B3ParentId, "fffffffffffffffe"); AssertExpected(headers, B3HttpHeaderNames.B3Flags, "1"); AssertMissing(headers, B3HttpHeaderNames.B3Sampled); var resultContext = _propagator.Extract(headers); Assert.NotNull(resultContext); Assert.Equal(context.SpanId, resultContext.SpanId); Assert.Equal(context.TraceId, resultContext.TraceId); Assert.Equal(samplingPriority, resultContext.SamplingPriority); }
internal void Inject_DoNotCreateCorrectTraceStateHeaderIfNotPresent(IHeadersCollection headers) { var traceId = TraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c"); const ulong spanId = 67667974448284343; var spanContext = new SpanContext(traceId, spanId, traceState: null); var propagator = new W3CSpanContextPropagator(new OtelTraceIdConvention()); propagator.Inject(spanContext, headers); headers.GetValues(W3CHeaderNames.TraceState).Should().HaveCount(0); }
internal void Inject_CreateCorrectTraceStateHeaderIfPresent(IHeadersCollection headers) { var traceId = TraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c"); const ulong spanId = 67667974448284343; var spanContext = new SpanContext(traceId, spanId, samplingPriority: null, serviceName: null, "state"); var propagator = W3CSpanContextPropagator.Instance; propagator.Inject(spanContext, headers); headers.GetValues(W3CHeaderNames.TraceState).Should().Equal("state"); }
internal void Inject_CratesCorrectTraceParentHeader(IHeadersCollection headers) { var traceId = TraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c"); const ulong spanId = 67667974448284343; var spanContext = new SpanContext(traceId, spanId, samplingPriority: null); var propagator = W3CSpanContextPropagator.Instance; propagator.Inject(spanContext, headers); headers.GetValues(W3CHeaderNames.TraceParent).Should().Equal("00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"); }
public void Equals_WorksCorrectlyBetween64And128BitIds() { var traceId1 = TraceId.CreateRandomDataDogCompatible(); var traceId2 = TraceId.CreateFromString(TraceId.Zero.Lower.ToString("x16") + traceId1.Lower.ToString("x16")); using (new AssertionScope()) { traceId1.Lower.Should().Be(traceId2.Lower); traceId1.Should().NotBe(TraceId.CreateFromString(traceId2.ToString())); traceId2.Should().NotBe(TraceId.CreateDataDogCompatibleFromDecimalString(traceId1.ToString())); traceId1.GetHashCode().Should().NotBe(traceId2.GetHashCode()); } }
public void Equals_WorksCorrectlyFor128BitId() { var traceId1 = TraceId.CreateRandom(); var traceId2 = TraceId.CreateRandom(); using (new AssertionScope()) { traceId1.Should().Be(TraceId.CreateFromString(traceId1.ToString())); traceId2.Should().Be(TraceId.CreateFromString(traceId2.ToString())); traceId1.Should().NotBe(TraceId.CreateFromString(traceId2.ToString())); traceId2.Should().NotBe(TraceId.CreateFromString(traceId1.ToString())); } }
internal void Extract_ReturnCorrectTraceAndSpanIdInContext(IHeadersCollection headers) { var propagator = new W3CSpanContextPropagator(new OtelTraceIdConvention()); headers.Set(W3CHeaderNames.TraceParent, "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"); var spanContext = propagator.Extract(headers); using (new AssertionScope()) { spanContext.SpanId.Should().Be(67667974448284343); spanContext.TraceId.Should().Be(TraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c")); } }
internal void InjectExtract_Identity(IHeadersCollection headers) { var traceId = TraceId.CreateFromString("52686470458518446744073709551615"); const int spanId = 7; const SamplingPriority samplingPriority = SamplingPriority.UserKeep; var context = new SpanContext(traceId, spanId, samplingPriority); _propagator.Inject(context, headers); var resultContext = _propagator.Extract(headers); Assert.NotNull(resultContext); Assert.Equal(context.SpanId, resultContext.SpanId); Assert.Equal(context.TraceId, resultContext.TraceId); Assert.Equal(context.SamplingPriority, resultContext.SamplingPriority); }
internal void Inject_CreateCorrectTraceStateHeaderIfPresent(IHeadersCollection headers) { var traceId = TraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c"); const ulong spanId = 67667974448284343; var spanContext = new SpanContext(traceId, spanId, "state"); var propagator = new W3CSpanContextPropagator(new OtelTraceIdConvention()); propagator.Inject(spanContext, headers); using (new AssertionScope()) { headers.GetValues(W3CHeaderNames.TraceState).Should().HaveCount(1); headers.GetValues(W3CHeaderNames.TraceState).Should().BeEquivalentTo(new List <string> { "state" }); } }
internal void Extract_InvalidSpanId(IHeadersCollection headers, string spanId) { var traceId = TraceId.CreateFromString("52686470458518446744073709551615"); const SamplingPriority samplingPriority = SamplingPriority.UserKeep; InjectContext( headers, traceId.ToString(), spanId, ((int)samplingPriority).ToString(CultureInfo.InvariantCulture)); var resultContext = _propagator.Extract(headers); Assert.NotNull(resultContext); Assert.Equal(traceId, resultContext.TraceId); Assert.Equal(default(ulong), resultContext.SpanId); Assert.Equal(samplingPriority, resultContext.SamplingPriority); }
internal void Extract_InvalidSamplingPriority(IHeadersCollection headers, string samplingPriority) { var traceId = TraceId.CreateFromString("52686470458518446744073709551615"); const ulong spanId = 7; InjectContext( headers, traceId.ToString(), spanId.ToString("x16", CultureInfo.InvariantCulture), samplingPriority); var resultContext = _propagator.Extract(headers); Assert.NotNull(resultContext); Assert.Equal(traceId, resultContext.TraceId); Assert.Equal(spanId, resultContext.SpanId); Assert.Null(resultContext.SamplingPriority); }
internal static void Contains(this log4net.Core.LoggingEvent logEvent, TraceId traceId, ulong spanId, string service, string environment) { // First, verify that the properties are attached to the LogEvent Assert.Contains(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys()); Assert.Equal(traceId, TraceId.CreateFromString(logEvent.Properties[CorrelationIdentifier.TraceIdKey].ToString())); Assert.Contains(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys()); Assert.Equal <ulong>(spanId, Convert.ToUInt64(logEvent.Properties[CorrelationIdentifier.SpanIdKey].ToString(), 16)); Assert.Contains(CorrelationIdentifier.ServiceNameKey, logEvent.Properties.GetKeys()); Assert.Equal(service, logEvent.Properties[CorrelationIdentifier.ServiceNameKey].ToString()); Assert.Contains(CorrelationIdentifier.ServiceEnvironmentKey, logEvent.Properties.GetKeys()); Assert.Equal(environment, logEvent.Properties[CorrelationIdentifier.ServiceEnvironmentKey].ToString()); // Second, verify that the message formatting correctly encloses the // values in quotes, since they are string values var layout = new Log4NetLogProviderTests.Log4NetJsonLayout(); string formattedMessage = layout.Format(logEvent); Assert.Contains(string.Format(Log4NetExpectedStringFormat, CorrelationIdentifier.TraceIdKey, traceId), formattedMessage); Assert.Contains(string.Format(Log4NetExpectedStringFormat, CorrelationIdentifier.SpanIdKey, spanId), formattedMessage); }
internal void WebRequest_InjectExtract_Identity(IHeadersCollection headers) { var traceId = TraceId.CreateFromString("52686470458518446744073709551615"); const int spanId = 2147483646; const SamplingPriority samplingPriority = SamplingPriority.AutoReject; var context = new SpanContext(traceId, spanId, samplingPriority); _propagator.Inject(context, headers); AssertExpected(headers, B3HttpHeaderNames.B3TraceId, "52686470458518446744073709551615"); AssertExpected(headers, B3HttpHeaderNames.B3SpanId, "000000007ffffffe"); AssertExpected(headers, B3HttpHeaderNames.B3Sampled, "0"); AssertMissing(headers, B3HttpHeaderNames.B3ParentId); AssertMissing(headers, B3HttpHeaderNames.B3Flags); var resultContext = _propagator.Extract(headers); Assert.NotNull(resultContext); Assert.Equal(context.SpanId, resultContext.SpanId); Assert.Equal(context.TraceId, resultContext.TraceId); Assert.Equal(context.SamplingPriority, resultContext.SamplingPriority); }
internal static void Contains(this Serilog.Events.LogEvent logEvent, Scope scope) { string SanitizedProperty(string correlationIdentifier) { return(logEvent.Properties[correlationIdentifier].ToString().Trim(new[] { '\"' })); } var traceId = scope.Span.TraceId; var spanId = scope.Span.SpanId; // First, verify that the properties are attached to the LogEvent Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.TraceIdKey)); Assert.Equal(traceId, TraceId.CreateFromString(SanitizedProperty(CorrelationIdentifier.TraceIdKey))); Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.SpanIdKey)); Assert.Equal <ulong>(spanId, Convert.ToUInt64(SanitizedProperty(CorrelationIdentifier.SpanIdKey), fromBase: 16)); Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.ServiceNameKey)); Assert.Equal(ServiceName, SanitizedProperty(CorrelationIdentifier.ServiceNameKey)); Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.ServiceEnvironmentKey)); Assert.Equal(ServiceEnvironment, SanitizedProperty(CorrelationIdentifier.ServiceEnvironmentKey)); // Second, verify that the message formatting correctly encloses the // values in quotes, since they are string values // Use the built-in formatting to render the message like the console output would, // but this must write to a TextWriter so use a StringWriter/StringBuilder to shuttle // the message to our in-memory list const string outputTemplate = "{Message}|{Properties}"; var textFormatter = new MessageTemplateTextFormatter(outputTemplate, CultureInfo.InvariantCulture); var sw = new StringWriter(new StringBuilder()); textFormatter.Format(logEvent, sw); var formattedMessage = sw.ToString(); Assert.Contains(string.Format(SerilogExpectedStringFormat, CorrelationIdentifier.TraceIdKey, traceId), formattedMessage); Assert.Contains(string.Format(SerilogExpectedStringFormat, CorrelationIdentifier.SpanIdKey, spanId), formattedMessage); }
public TraceId CreateFromString(string id) => TraceId.CreateFromString(id);
public bool TryExtract <TCarrier, TCarrierGetter>(TCarrier carrier, TCarrierGetter carrierGetter, out SpanContext?spanContext) where TCarrierGetter : struct, ICarrierGetter <TCarrier> { spanContext = null; var brValue = ParseUtility.ParseString(carrier, carrierGetter, B3)?.Trim(); if (!string.IsNullOrEmpty(brValue)) { // We found a trace parent (we are reading from the Http Headers) // 80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90 // 80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1 // e457b5a2e4d86bd1-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90 // e457b5a2e4d86bd1-e457b5a2e4d86bd1-1 if (brValue !.Length != 68 && brValue !.Length != 51 && brValue !.Length != 52 && brValue !.Length != 35) { return(false); } #if NETCOREAPP ReadOnlySpan <char> rawTraceId = null; ReadOnlySpan <char> rawSpanId = null; char rawSampled = '0'; if (brValue.Length > 50 && brValue[32] == '-' && brValue[49] == '-') { // 128 bits trace id rawTraceId = brValue.AsSpan(0, 32); rawSpanId = brValue.AsSpan(33, 16); rawSampled = brValue[50]; } else if (brValue.Length > 34 && brValue[16] == '-' && brValue[33] == '-') { // 64 bits trace id rawTraceId = brValue.AsSpan(0, 16); rawSpanId = brValue.AsSpan(17, 16); rawSampled = brValue[34]; } else { return(false); } var traceId = TraceId.CreateFromString(rawTraceId.ToString()); var parentId = ParseUtility.ParseFromHexOrDefault(rawSpanId); var samplingPriority = rawSampled == '1' ? 1 : 0; spanContext = new SpanContext(traceId, parentId, samplingPriority, serviceName: null, null, rawTraceId.ToString(), rawSpanId.ToString()); #else string?rawTraceId = null; string?rawSpanId = null; char rawSampled = '0'; if (brValue.Length > 50 && brValue[32] == '-' && brValue[49] == '-') { // 128 bits trace id rawTraceId = brValue.Substring(0, 32); rawSpanId = brValue.Substring(33, 16); rawSampled = brValue[50]; } else if (brValue.Length > 34 && brValue[16] == '-' && brValue[33] == '-') { // 64 bits trace id rawTraceId = brValue.Substring(0, 16); rawSpanId = brValue.Substring(17, 16); rawSampled = brValue[34]; } else { return(false); } var traceId = TraceId.CreateFromString(rawTraceId); var parentId = ParseUtility.ParseFromHexOrDefault(rawSpanId); var samplingPriority = rawSampled == '1' ? 1 : 0; spanContext = new SpanContext(traceId, parentId, samplingPriority, serviceName: null, null, rawTraceId, rawSpanId); #endif return(true); } return(false); }
public void Equals_WorksCorrectly() { var traceId1 = TraceId.CreateRandom(); traceId1.Should().Be(TraceId.CreateFromString(traceId1.ToString())); }
public bool TryExtract <TCarrier, TCarrierGetter>(TCarrier carrier, TCarrierGetter carrierGetter, out SpanContext?spanContext) where TCarrierGetter : struct, ICarrierGetter <TCarrier> { spanContext = null; var traceParent = ParseUtility.ParseString(carrier, carrierGetter, TraceParent)?.Trim(); if (!string.IsNullOrEmpty(traceParent)) { // We found a trace parent (we are reading from the Http Headers) /* (https://www.w3.org/TR/trace-context/) * Valid traceparent when caller sampled this request: * * Value = 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01 * base16(version) = 00 * base16(trace-id) = 4bf92f3577b34da6a3ce929d0e0e4736 * base16(parent-id) = 00f067aa0ba902b7 * base16(trace-flags) = 01 // sampled * Valid traceparent when caller didn’t sample this request: * * Value = 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00 * base16(version) = 00 * base16(trace-id) = 4bf92f3577b34da6a3ce929d0e0e4736 * base16(parent-id) = 00f067aa0ba902b7 * base16(trace-flags) = 00 // not sampled */ if (traceParent !.Length != 55 || traceParent[2] != '-' || traceParent[35] != '-' || traceParent[52] != '-') { return(false); } char w3cSampled = traceParent[54]; if (traceParent[53] != '0' || (w3cSampled != '0' && w3cSampled != '1')) { return(false); } var samplingPriority = w3cSampled == '0' ? 0 : 1; #if NETCOREAPP var w3cTraceId = traceParent.AsSpan(3, 32); var w3cSpanId = traceParent.AsSpan(36, 16); var traceId = TraceId.CreateFromString(w3cTraceId.ToString()); if (traceId == TraceId.Zero) { return(false); } var parentId = ParseUtility.ParseFromHexOrDefault(w3cSpanId); spanContext = new SpanContext(traceId, parentId, samplingPriority, serviceName: null, null, w3cTraceId.ToString(), w3cSpanId.ToString()); #else var w3cTraceId = traceParent.Substring(3, 32); var w3cSpanId = traceParent.Substring(36, 16); if (!IsValidTraceId(w3cTraceId, out var traceId)) { return(false); } var parentId = ParseUtility.ParseFromHexOrDefault(w3cSpanId); spanContext = new SpanContext(traceId, parentId, samplingPriority, serviceName: null, null, w3cTraceId, w3cSpanId); #endif return(true); } return(false); }