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()); }
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()); }