private static void SetLinks(Span.Types.Links spanLinks, IDictionary <string, string> telemetryProperties) { if (spanLinks?.Link == null) { return; } // for now, we just put links to telemetry properties // link0_spanId = ... // link0_traceId = ... // link0_type = child | parent | other // link0_<attributeKey> = <attributeValue> // this is not convenient for querying data // We'll consider adding Links to operation telemetry schema int num = 0; foreach (var link in spanLinks.Link) { string prefix = $"{LinkPropertyName}{num++}_"; telemetryProperties[prefix + LinkSpanIdPropertyName] = BytesStringToHexString(link.SpanId); telemetryProperties[prefix + LinkTraceIdPropertyName] = BytesStringToHexString(link.TraceId); telemetryProperties[prefix + LinkTypePropertyName] = link.Type.ToString(); if (link.Attributes?.AttributeMap != null) { foreach (var attribute in link.Attributes.AttributeMap) { SetCustomProperty(telemetryProperties, attribute, prefix); } } } }
internal static Span ToProtoSpan(this SpanData spanData) { try { // protobuf doesn't understand Span<T> yet: https://github.com/protocolbuffers/protobuf/issues/3431 Span <byte> traceIdBytes = stackalloc byte[16]; Span <byte> spanIdBytes = stackalloc byte[8]; spanData.Context.TraceId.CopyTo(traceIdBytes); spanData.Context.SpanId.CopyTo(spanIdBytes); var parentSpanIdString = ByteString.Empty; if (spanData.ParentSpanId != default) { Span <byte> parentSpanIdBytes = stackalloc byte[8]; spanData.ParentSpanId.CopyTo(parentSpanIdBytes); parentSpanIdString = ByteString.CopyFrom(parentSpanIdBytes.ToArray()); } return(new Span { Name = new TruncatableString { Value = spanData.Name }, // TODO: Utilize new Span.Types.SpanKind below when updated protos are incorporated, also confirm default for SpanKind.Internal Kind = spanData.Kind == SpanKind.Client || spanData.Kind == SpanKind.Producer ? Span.Types.SpanKind.Client : Span.Types.SpanKind.Server, TraceId = ByteString.CopyFrom(traceIdBytes.ToArray()), SpanId = ByteString.CopyFrom(spanIdBytes.ToArray()), ParentSpanId = parentSpanIdString, StartTime = spanData.StartTimestamp.ToTimestamp(), EndTime = spanData.EndTimestamp.ToTimestamp(), Status = spanData.Status == null ? null : new OpenTelemetry.Proto.Trace.V1.Status { Code = (int)spanData.Status.CanonicalCode, Message = spanData.Status.Description ?? string.Empty, }, SameProcessAsParentSpan = spanData.ParentSpanId != default, ChildSpanCount = spanData.ChildSpanCount.HasValue ? (uint)spanData.ChildSpanCount.Value : 0, Attributes = FromAttributes(spanData.Attributes), TimeEvents = FromITimeEvents(spanData.Events), Links = new Span.Types.Links { DroppedLinksCount = spanData.Links.DroppedLinksCount, Link = { spanData.Links.Links.Select(FromILink), }, }, }); }