internal static bool ShouldSample(SpanContext parentContext, string name, ISampler sampler, out SpanContext context, out SpanId parentSpanId) { var traceId = TraceId.Invalid; var tracestate = Tracestate.Empty; parentSpanId = SpanId.Invalid; var parentOptions = TraceOptions.Default; if (parentContext.IsValid) { traceId = parentContext.TraceId; parentSpanId = parentContext.SpanId; parentOptions = parentContext.TraceOptions; } else { traceId = TraceId.FromBytes(Guid.NewGuid().ToByteArray()); } var result = parentOptions.IsSampled; var spanId = SpanId.FromBytes(Guid.NewGuid().ToByteArray(), 8); var traceOptions = TraceOptions.Default; if (sampler != null) { var builder = TraceOptions.Builder(parentContext.TraceOptions); result = sampler.ShouldSample(parentContext, traceId, spanId, name, null); builder = builder.SetIsSampled(result); traceOptions = builder.Build(); } context = SpanContext.Create(traceId, spanId, traceOptions, parentContext.Tracestate); return(result); }
public void GenerateSpan() { ZipkinEndpoint localEndpoint = new ZipkinEndpoint() { ServiceName = "tweetiebird" }; var traceId = "d239036e7d5cec116b562147388b35bf"; var spanId = "9cc1e3049173be09"; var parentId = "8b03ab423da481c5"; Dictionary <string, IAttributeValue> attributes = new Dictionary <string, IAttributeValue>(); IList <ITimedEvent <IAnnotation> > annotations = new List <ITimedEvent <IAnnotation> >(); List <ITimedEvent <IMessageEvent> > networkEvents = new List <ITimedEvent <IMessageEvent> >() { TimedEvent <IMessageEvent> .Create(Timestamp.Create(EPOCH_SECONDS + 1505855799, 433901068), new MessageEventBuilder(MessageEventType.RECEIVED, 0, 0, 0).SetCompressedMessageSize(7).Build()), TimedEvent <IMessageEvent> .Create(Timestamp.Create(EPOCH_SECONDS + 1505855799, 459486280), new MessageEventBuilder(MessageEventType.SENT, 0, 0, 0).SetCompressedMessageSize(13).Build()) }; ISpanData data = SpanData.Create( SpanContext.Create( TraceId.FromBytes(Arrays.StringToByteArray(traceId)), SpanId.FromBytes(Arrays.StringToByteArray(spanId)), TraceOptions.FromBytes(new byte[] { 1 })), SpanId.FromBytes(Arrays.StringToByteArray(parentId)), true, /* hasRemoteParent */ "Recv.helloworld.Greeter.SayHello", /* name */ Timestamp.Create(EPOCH_SECONDS + 1505855794, 194009601) /* startTimestamp */, Attributes.Create(attributes, 0 /* droppedAttributesCount */), TimedEvents <IAnnotation> .Create(annotations, 0 /* droppedEventsCount */), TimedEvents <IMessageEvent> .Create(networkEvents, 0 /* droppedEventsCount */), LinkList.Create(new List <ILink>(), 0 /* droppedLinksCount */), null, /* childSpanCount */ Status.OK, Timestamp.Create(EPOCH_SECONDS + 1505855799, 465726528) /* endTimestamp */); var handler = new TraceExporterHandler(new TraceExporterOptions() { UseShortTraceIds = false }); var result = handler.GenerateSpan(data, localEndpoint); var zspan = ZipkinSpan.NewBuilder() .TraceId(traceId) .ParentId(parentId) .Id(spanId) .Kind(ZipkinSpanKind.SERVER) .Name(data.Name) .Timestamp(1505855794000000L + (194009601L / 1000)) .Duration( (1505855799000000L + (465726528L / 1000)) - (1505855794000000L + (194009601L / 1000))) .LocalEndpoint(localEndpoint) .AddAnnotation(1505855799000000L + (433901068L / 1000), "RECEIVED") .AddAnnotation(1505855799000000L + (459486280L / 1000), "SENT") .PutTag("census.status_code", "OK") .Build(); Assert.Equal(zspan, result); }
public void SpanContext_ToString() { Assert.Contains(TraceId.FromBytes(firstTraceIdBytes).ToString(), first.ToString()); Assert.Contains(SpanId.FromBytes(firstSpanIdBytes).ToString(), first.ToString()); Assert.Contains(TraceOptions.DEFAULT.ToString(), first.ToString()); Assert.Contains(TraceId.FromBytes(secondTraceIdBytes).ToString(), second.ToString()); Assert.Contains(SpanId.FromBytes(secondSpanIdBytes).ToString(), second.ToString()); Assert.Contains(TraceOptions.Builder().SetIsSampled(true).Build().ToString(), second.ToString()); }
public void IsValid() { Assert.False(SpanContext.INVALID.IsValid); Assert.False( SpanContext.Create( TraceId.FromBytes(firstTraceIdBytes), SpanId.INVALID, TraceOptions.DEFAULT) .IsValid); Assert.False( SpanContext.Create( TraceId.INVALID, SpanId.FromBytes(firstSpanIdBytes), TraceOptions.DEFAULT) .IsValid); Assert.True(first.IsValid); Assert.True(second.IsValid); }
public void IsValid() { Assert.False(SpanContext.Invalid.IsValid); Assert.False( SpanContext.Create( TraceId.FromBytes(firstTraceIdBytes), SpanId.Invalid, TraceOptions.Default, Tracestate.Empty) .IsValid); Assert.False( SpanContext.Create( TraceId.Invalid, SpanId.FromBytes(firstSpanIdBytes), TraceOptions.Default, Tracestate.Empty) .IsValid); Assert.True(first.IsValid); Assert.True(second.IsValid); }
public void FromBinaryValue_UnsupportedFieldIdSecond() { Assert.Equal( SpanContext.Create( TraceId.FromBytes(new byte[] { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 }), SpanId.Invalid, TraceOptions.Default, Tracestate.Empty), binaryFormat.FromByteArray( new byte[] { 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 3, 97, 98, 99, 100, 101, 102, 103, 104, 2, 1, })); }
public SpanContext FromByteArray(byte[] bytes) { if (bytes == null) { throw new ArgumentNullException(nameof(bytes)); } if (bytes.Length == 0 || bytes[0] != VersionId) { throw new SpanContextParseException("Unsupported version."); } var traceId = TraceId.Invalid; var spanId = SpanId.Invalid; var traceOptions = TraceOptions.Default; var pos = 1; try { if (bytes.Length > pos && bytes[pos] == TraceIdFieldId) { traceId = TraceId.FromBytes(bytes, pos + IdSize); pos += IdSize + TraceId.Size; } if (bytes.Length > pos && bytes[pos] == SpanIdFieldId) { spanId = SpanId.FromBytes(bytes, pos + IdSize); pos += IdSize + SpanId.Size; } if (bytes.Length > pos && bytes[pos] == TraceOptionsFieldId) { traceOptions = TraceOptions.FromBytes(bytes, pos + IdSize); } return(SpanContext.Create(traceId, spanId, traceOptions, Tracestate.Empty)); } catch (Exception e) { throw new SpanContextParseException("Invalid input.", e); } }
public override ISpanContext FromByteArray(byte[] bytes) { if (bytes == null) { throw new ArgumentNullException(nameof(bytes)); } if (bytes.Length == 0 || bytes[0] != VERSION_ID) { throw new SpanContextParseException("Unsupported version."); } ITraceId traceId = TraceId.INVALID; ISpanId spanId = SpanId.INVALID; TraceOptions traceOptions = TraceOptions.DEFAULT; int pos = 1; try { if (bytes.Length > pos && bytes[pos] == TRACE_ID_FIELD_ID) { traceId = TraceId.FromBytes(bytes, pos + ID_SIZE); pos += ID_SIZE + TraceId.SIZE; } if (bytes.Length > pos && bytes[pos] == SPAN_ID_FIELD_ID) { spanId = SpanId.FromBytes(bytes, pos + ID_SIZE); pos += ID_SIZE + SpanId.SIZE; } if (bytes.Length > pos && bytes[pos] == TRACE_OPTION_FIELD_ID) { traceOptions = TraceOptions.FromBytes(bytes, pos + ID_SIZE); } return(SpanContext.Create(traceId, spanId, traceOptions)); } catch (Exception e) { throw new SpanContextParseException("Invalid input.", e); } }
private bool TryExtractTraceparent(string traceparent, out TraceId traceId, out SpanId spanId, out TraceOptions traceoptions) { // from https://github.com/w3c/distributed-tracing/blob/master/trace_context/HTTP_HEADER_FORMAT.md // traceparent: 00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01 traceId = TraceId.Invalid; spanId = SpanId.Invalid; traceoptions = TraceOptions.Default; var bestAttempt = false; if (string.IsNullOrWhiteSpace(traceparent)) { return(false); } // if version does not end with delimeter if (traceparent.Length < VersionPrefixIdLength || traceparent[VersionPrefixIdLength - 1] != '-') { return(false); } // or version is not a hex (will throw) var versionArray = Arrays.StringToByteArray(traceparent, 0, VersionLength); if (versionArray[0] == 255) { return(false); } if (versionArray[0] > 0) { // expected version is 00 // for higher versions - best attempt parsing of trace id, span id, etc. bestAttempt = true; } if (traceparent.Length < VersionAndTraceIdLength || traceparent[VersionAndTraceIdLength - 1] != '-') { return(false); } try { traceId = TraceId.FromBytes(Arrays.StringToByteArray(traceparent, VersionPrefixIdLength, TraceIdLength)); } catch (ArgumentOutOfRangeException) { // it's ok to still parse tracestate return(false); } if (traceparent.Length < VersionAndTraceIdAndSpanIdLength || traceparent[VersionAndTraceIdAndSpanIdLength - 1] != '-') { return(false); } try { spanId = SpanId.FromBytes(Arrays.StringToByteArray(traceparent, VersionAndTraceIdLength, SpanIdLength)); } catch (ArgumentOutOfRangeException) { // it's ok to still parse tracestate return(false); } if (traceparent.Length < VersionAndTraceIdAndSpanIdLength + OptionsLength) { return(false); } byte[] optionsArray; try { optionsArray = Arrays.StringToByteArray(traceparent, VersionAndTraceIdAndSpanIdLength, OptionsLength); } catch (ArgumentOutOfRangeException) { // it's ok to still parse tracestate return(false); } if ((optionsArray[0] | 1) == 1) { traceoptions = TraceOptions.Builder().SetIsSampled(true).Build(); } if ((!bestAttempt) && (traceparent.Length != VersionAndTraceIdAndSpanIdLength + OptionsLength)) { return(false); } if (bestAttempt) { if ((traceparent.Length > VersionAndTraceIdAndSpanIdLength + OptionsLength) && (traceparent[VersionAndTraceIdAndSpanIdLength + OptionsLength] != '-')) { return(false); } } return(true); }
public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() { var configMock = Mock.Get <ITraceConfig>(traceConfig); configMock.Setup((c) => c.ActiveTraceParams).Returns(TraceParams.Default); // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long // is not less than probability * Long.MAX_VALUE; var traceId = TraceId.FromBytes( new byte[] { 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }); // If parent is sampled then the remote child must be sampled. var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Create( traceId, SpanId.GenerateRandomId(randomHandler), TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty)) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); Assert.True(childSpan.Context.TraceOptions.IsSampled); childSpan.End(); Assert.Equal(TraceParams.Default, traceConfig.ActiveTraceParams); // If parent is not sampled then the remote child must be not sampled. childSpan = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Create( traceId, SpanId.GenerateRandomId(randomHandler), TraceOptions.Default, Tracestate.Empty)) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); Assert.False(childSpan.Context.TraceOptions.IsSampled); childSpan.End(); }
public void ProbabilitySampler_SampleBasedOnTraceId() { ISampler defaultProbability = ProbabilitySampler.Create(0.0001); // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long // is not less than probability * Long.MAX_VALUE; ITraceId notSampledtraceId = TraceId.FromBytes( new byte[] { 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }); Assert.False( defaultProbability.ShouldSample( null, notSampledtraceId, SpanId.GenerateRandomId(random), SPAN_NAME, new List <ISpan>())); // This traceId will be sampled by the ProbabilitySampler because the first 8 bytes as long // is less than probability * Long.MAX_VALUE; ITraceId sampledtraceId = TraceId.FromBytes( new byte[] { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }); Assert.True( defaultProbability.ShouldSample( null, sampledtraceId, SpanId.GenerateRandomId(random), SPAN_NAME, new List <ISpan>())); }
public void GetTraceId() { Assert.Equal(TraceId.FromBytes(firstTraceIdBytes), first.TraceId); Assert.Equal(TraceId.FromBytes(secondTraceIdBytes), second.TraceId); }
public void TraceId_CompareTo() { Assert.Equal(1, first.CompareTo(second)); Assert.Equal(-1, second.CompareTo(first)); Assert.Equal(0, first.CompareTo(TraceId.FromBytes(firstBytes))); }
public void TraceId_CompareTo() { Assert.Equal(1, First.CompareTo(Second)); Assert.Equal(-1, Second.CompareTo(First)); Assert.Equal(0, First.CompareTo(TraceId.FromBytes(FirstBytes))); }
public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() { var configMock = Mock.Get <ITraceConfig>(traceConfig); configMock.Setup((c) => c.ActiveTraceParams).Returns(TraceParams.DEFAULT); // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long // is not less than probability * Long.MAX_VALUE; ITraceId traceId = TraceId.FromBytes( new byte[] { (byte)0x8F, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 0, 0, 0, 0, 0, 0, 0, 0 }); // If parent is sampled then the remote child must be sampled. ISpan childSpan = SpanBuilder.CreateWithRemoteParent( SPAN_NAME, SpanContext.Create( traceId, SpanId.GenerateRandomId(randomHandler), TraceOptions.Builder().SetIsSampled(true).Build()), spanBuilderOptions) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); Assert.True(childSpan.Context.TraceOptions.IsSampled); childSpan.End(); Assert.Equal(TraceParams.DEFAULT, traceConfig.ActiveTraceParams); // If parent is not sampled then the remote child must be not sampled. childSpan = SpanBuilder.CreateWithRemoteParent( SPAN_NAME, SpanContext.Create( traceId, SpanId.GenerateRandomId(randomHandler), TraceOptions.DEFAULT), spanBuilderOptions) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); Assert.False(childSpan.Context.TraceOptions.IsSampled); childSpan.End(); }
public void GetTraceId() { Assert.Equal(TraceId.FromBytes(FirstTraceIdBytes), First.TraceId); Assert.Equal(TraceId.FromBytes(SecondTraceIdBytes), Second.TraceId); }