public TraceExporterHandler(ZipkinTraceExporterOptions options, HttpClient client) { this.options = options; this.localEndpoint = this.GetLocalZipkinEndpoint(); this.httpClient = client ?? new HttpClient(); this.serviceEndpoint = options.Endpoint?.ToString(); }
public ZipkinSpan( string traceId, string parentId, string id, string kind, string name, long?timestamp, long?duration, ZipkinEndpoint localEndpoint, ZipkinEndpoint remoteEndpoint, in PooledList <ZipkinAnnotation>?annotations,
internal ZipkinSpan GenerateSpan(ISpanData spanData, ZipkinEndpoint localEndpoint) { SpanContext context = spanData.Context; long startTimestamp = this.ToEpochMicroseconds(spanData.StartTimestamp); long endTimestamp = this.ToEpochMicroseconds(spanData.EndTimestamp); ZipkinSpan.Builder spanBuilder = ZipkinSpan.NewBuilder() .TraceId(this.EncodeTraceId(context.TraceId)) .Id(this.EncodeSpanId(context.SpanId)) .Kind(this.ToSpanKind(spanData)) .Name(spanData.Name) .Timestamp(this.ToEpochMicroseconds(spanData.StartTimestamp)) .Duration(endTimestamp - startTimestamp) .LocalEndpoint(localEndpoint); if (spanData.ParentSpanId != null && spanData.ParentSpanId.IsValid) { spanBuilder.ParentId(this.EncodeSpanId(spanData.ParentSpanId)); } foreach (var label in spanData.Attributes.AttributeMap) { spanBuilder.PutTag(label.Key, this.AttributeValueToString(label.Value)); } Status status = spanData.Status; if (status != null) { spanBuilder.PutTag(StatusCode, status.CanonicalCode.ToString()); if (status.Description != null) { spanBuilder.PutTag(StatusDescription, status.Description); } } foreach (var annotation in spanData.Events.Events) { spanBuilder.AddAnnotation(this.ToEpochMicroseconds(annotation.Timestamp), annotation.Event.Name); } return(spanBuilder.Build()); }
private ZipkinEndpoint GetLocalZipkinEndpoint() { var result = new ZipkinEndpoint() { ServiceName = this.options.ServiceName, }; string hostName = this.ResolveHostName(); if (!string.IsNullOrEmpty(hostName)) { result.Ipv4 = this.ResolveHostAddress(hostName, AddressFamily.InterNetwork); result.Ipv6 = this.ResolveHostAddress(hostName, AddressFamily.InterNetworkV6); } return(result); }
internal static ZipkinSpan ToZipkinSpan(this SpanData otelSpan, ZipkinEndpoint defaultLocalEndpoint, bool useShortTraceIds = false) { var context = otelSpan.Context; var startTimestamp = ToEpochMicroseconds(otelSpan.StartTimestamp); var endTimestamp = ToEpochMicroseconds(otelSpan.EndTimestamp); string parentId = null; if (otelSpan.ParentSpanId != default) { parentId = EncodeSpanId(otelSpan.ParentSpanId); } var attributeEnumerationState = new AttributeEnumerationState { Tags = PooledList <KeyValuePair <string, string> > .Create(), }; DictionaryEnumerator <string, object, AttributeEnumerationState> .AllocationFreeForEach(otelSpan.Attributes, ref attributeEnumerationState, ProcessAttributesRef); DictionaryEnumerator <string, object, AttributeEnumerationState> .AllocationFreeForEach(otelSpan.LibraryResource.Attributes, ref attributeEnumerationState, ProcessLibraryResourcesRef); var localEndpoint = defaultLocalEndpoint; var serviceName = attributeEnumerationState.ServiceName; // override default service name if (!string.IsNullOrWhiteSpace(serviceName)) { if (!string.IsNullOrWhiteSpace(attributeEnumerationState.ServiceNamespace)) { serviceName = attributeEnumerationState.ServiceNamespace + "." + serviceName; } if (!LocalEndpointCache.TryGetValue(serviceName, out localEndpoint)) { localEndpoint = defaultLocalEndpoint.Clone(serviceName); LocalEndpointCache.TryAdd(serviceName, localEndpoint); } } ZipkinEndpoint remoteEndpoint = null; if ((otelSpan.Kind == SpanKind.Client || otelSpan.Kind == SpanKind.Producer) && attributeEnumerationState.RemoteEndpointServiceName != null) { remoteEndpoint = RemoteEndpointCache.GetOrAdd(attributeEnumerationState.RemoteEndpointServiceName, ZipkinEndpoint.Create); } var status = otelSpan.Status; if (status.IsValid) { if (!CanonicalCodeCache.TryGetValue(status.CanonicalCode, out string canonicalCode)) { canonicalCode = status.CanonicalCode.ToString(); CanonicalCodeCache.TryAdd(status.CanonicalCode, canonicalCode); } PooledList <KeyValuePair <string, string> > .Add(ref attributeEnumerationState.Tags, new KeyValuePair <string, string>(StatusCode, canonicalCode)); if (status.Description != null) { PooledList <KeyValuePair <string, string> > .Add(ref attributeEnumerationState.Tags, new KeyValuePair <string, string>(StatusDescription, status.Description)); } } var annotations = PooledList <ZipkinAnnotation> .Create(); ListEnumerator <Event, PooledList <ZipkinAnnotation> > .AllocationFreeForEach(otelSpan.Events, ref annotations, ProcessEventsRef); return(new ZipkinSpan( EncodeTraceId(context.TraceId, useShortTraceIds), parentId, EncodeSpanId(context.SpanId), ToSpanKind(otelSpan), otelSpan.Name, ToEpochMicroseconds(otelSpan.StartTimestamp), duration: endTimestamp - startTimestamp, localEndpoint, remoteEndpoint, annotations, attributeEnumerationState.Tags, null, null)); }
internal static ZipkinSpan ToZipkinSpan(this SpanData otelSpan, ZipkinEndpoint defaultLocalEndpoint, bool useShortTraceIds = false) { var context = otelSpan.Context; var startTimestamp = ToEpochMicroseconds(otelSpan.StartTimestamp); var endTimestamp = ToEpochMicroseconds(otelSpan.EndTimestamp); var spanBuilder = ZipkinSpan.NewBuilder() .TraceId(EncodeTraceId(context.TraceId, useShortTraceIds)) .Id(EncodeSpanId(context.SpanId)) .Kind(ToSpanKind(otelSpan)) .Name(otelSpan.Name) .Timestamp(ToEpochMicroseconds(otelSpan.StartTimestamp)) .Duration(endTimestamp - startTimestamp); if (otelSpan.ParentSpanId != default) { spanBuilder.ParentId(EncodeSpanId(otelSpan.ParentSpanId)); } Tuple <string, int> remoteEndpointServiceName = null; foreach (var label in otelSpan.Attributes) { string key = label.Key; string strVal = label.Value.ToString(); if (strVal != null && RemoteEndpointServiceNameKeyResolutionDictionary.TryGetValue(key, out int priority) && (remoteEndpointServiceName == null || priority < remoteEndpointServiceName.Item2)) { remoteEndpointServiceName = new Tuple <string, int>(strVal, priority); } spanBuilder.PutTag(key, strVal); } // See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-resource-semantic-conventions.md string serviceName = string.Empty; string serviceNamespace = string.Empty; foreach (var label in otelSpan.LibraryResource.Attributes) { string key = label.Key; object val = label.Value; string strVal = val as string; if (key == Resource.ServiceNameKey && strVal != null) { serviceName = strVal; } else if (key == Resource.ServiceNamespaceKey && strVal != null) { serviceNamespace = strVal; } else { spanBuilder.PutTag(key, strVal ?? val?.ToString()); } } if (serviceNamespace != string.Empty) { serviceName = serviceNamespace + "." + serviceName; } var endpoint = defaultLocalEndpoint; // override default service name if (serviceName != string.Empty) { endpoint = LocalEndpointCache.GetOrAdd(serviceName, _ => new ZipkinEndpoint() { Ipv4 = defaultLocalEndpoint.Ipv4, Ipv6 = defaultLocalEndpoint.Ipv6, Port = defaultLocalEndpoint.Port, ServiceName = serviceName, }); } spanBuilder.LocalEndpoint(endpoint); if ((otelSpan.Kind == SpanKind.Client || otelSpan.Kind == SpanKind.Producer) && remoteEndpointServiceName != null) { spanBuilder.RemoteEndpoint(RemoteEndpointCache.GetOrAdd(remoteEndpointServiceName.Item1, _ => new ZipkinEndpoint { ServiceName = remoteEndpointServiceName.Item1, })); } var status = otelSpan.Status; if (status.IsValid) { spanBuilder.PutTag(StatusCode, status.CanonicalCode.ToString()); if (status.Description != null) { spanBuilder.PutTag(StatusDescription, status.Description); } } foreach (var annotation in otelSpan.Events) { spanBuilder.AddAnnotation(ToEpochMicroseconds(annotation.Timestamp), annotation.Name); } return(spanBuilder.Build()); }
internal static ZipkinSpan ToZipkinSpan(this Activity activity, ZipkinEndpoint defaultLocalEndpoint, bool useShortTraceIds = false) { var context = activity.Context; var startTimestamp = activity.StartTimeUtc.ToEpochMicroseconds(); string parentId = EncodeSpanId(activity.ParentSpanId); if (string.Equals(parentId, InvalidSpanId, StringComparison.Ordinal)) { parentId = null; } var attributeEnumerationState = new AttributeEnumerationState { Tags = PooledList <KeyValuePair <string, string> > .Create(), }; DictionaryEnumerator <string, string, AttributeEnumerationState> .AllocationFreeForEach(activity.Tags, ref attributeEnumerationState, ProcessTagsRef); var activitySource = activity.Source; if (!string.IsNullOrEmpty(activitySource.Name)) { PooledList <KeyValuePair <string, string> > .Add(ref attributeEnumerationState.Tags, new KeyValuePair <string, string>("library.name", activitySource.Name)); if (!string.IsNullOrEmpty(activitySource.Version)) { PooledList <KeyValuePair <string, string> > .Add(ref attributeEnumerationState.Tags, new KeyValuePair <string, string>("library.version", activitySource.Version)); } } var localEndpoint = defaultLocalEndpoint; var serviceName = attributeEnumerationState.ServiceName; // override default service name if (!string.IsNullOrWhiteSpace(serviceName)) { if (!string.IsNullOrWhiteSpace(attributeEnumerationState.ServiceNamespace)) { serviceName = attributeEnumerationState.ServiceNamespace + "." + serviceName; } if (!LocalEndpointCache.TryGetValue(serviceName, out localEndpoint)) { localEndpoint = defaultLocalEndpoint.Clone(serviceName); LocalEndpointCache.TryAdd(serviceName, localEndpoint); } } ZipkinEndpoint remoteEndpoint = null; if ((activity.Kind == ActivityKind.Client || activity.Kind == ActivityKind.Producer) && attributeEnumerationState.RemoteEndpointServiceName != null) { remoteEndpoint = RemoteEndpointCache.GetOrAdd(attributeEnumerationState.RemoteEndpointServiceName, ZipkinEndpoint.Create); } var annotations = PooledList <ZipkinAnnotation> .Create(); ListEnumerator <ActivityEvent, PooledList <ZipkinAnnotation> > .AllocationFreeForEach(activity.Events, ref annotations, ProcessActivityEventsRef); return(new ZipkinSpan( EncodeTraceId(context.TraceId, useShortTraceIds), parentId, EncodeSpanId(context.SpanId), ToActivityKind(activity), activity.OperationName, activity.StartTimeUtc.ToEpochMicroseconds(), duration: (long)activity.Duration.ToEpochMicroseconds(), localEndpoint, remoteEndpoint, annotations, attributeEnumerationState.Tags, null, null)); }
internal Builder RemoteEndpoint(ZipkinEndpoint val) { this.result.RemoteEndpoint = val; return(this); }
internal Builder LocalEndpoint(ZipkinEndpoint val) { this.result.LocalEndpoint = val; return(this); }