Example #1
0
 public TraceExporterHandler(ZipkinTraceExporterOptions options, HttpClient client)
 {
     this.options         = options;
     this.localEndpoint   = this.GetLocalZipkinEndpoint();
     this.httpClient      = client ?? new HttpClient();
     this.serviceEndpoint = options.Endpoint?.ToString();
 }
Example #2
0
 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));
        }
Example #6
0
        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));
        }
Example #8
0
 internal Builder RemoteEndpoint(ZipkinEndpoint val)
 {
     this.result.RemoteEndpoint = val;
     return(this);
 }
Example #9
0
 internal Builder LocalEndpoint(ZipkinEndpoint val)
 {
     this.result.LocalEndpoint = val;
     return(this);
 }