Beispiel #1
0
        internal static Proto.Trace.V1.Span ToProtoSpan(this Trace.Span otelSpan)
        {
            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];

                otelSpan.Context.TraceId.CopyTo(traceIdBytes);
                otelSpan.Context.SpanId.CopyTo(spanIdBytes);

                var parentSpanIdString = ByteString.Empty;
                if (otelSpan.ParentSpanId != default)
                {
                    Span <byte> parentSpanIdBytes = stackalloc byte[8];
                    otelSpan.ParentSpanId.CopyTo(parentSpanIdBytes);
                    parentSpanIdString = ByteString.CopyFrom(parentSpanIdBytes.ToArray());
                }

                return(new Proto.Trace.V1.Span
                {
                    Name = new TruncatableString {
                        Value = otelSpan.Name
                    },

                    // TODO: Utilize new Span.Types.SpanKind below when updated protos are incorporated, also confirm default for SpanKind.Internal
                    Kind = otelSpan.Kind == SpanKind.Client || otelSpan.Kind == SpanKind.Producer ?
                           Proto.Trace.V1.Span.Types.SpanKind.Client :
                           Proto.Trace.V1.Span.Types.SpanKind.Server,

                    TraceId = ByteString.CopyFrom(traceIdBytes.ToArray()),
                    SpanId = ByteString.CopyFrom(spanIdBytes.ToArray()),
                    ParentSpanId = parentSpanIdString,

                    StartTime = otelSpan.StartTimestamp.ToTimestamp(),
                    EndTime = otelSpan.EndTimestamp.ToTimestamp(),
                    Status = !otelSpan.Status.IsValid
                        ? null
                        : new OpenTelemetry.Proto.Trace.V1.Status
                    {
                        Code = (int)otelSpan.Status.CanonicalCode,
                        Message = otelSpan.Status.Description ?? string.Empty,
                    },
                    SameProcessAsParentSpan = otelSpan.ParentSpanId != default,
                    ChildSpanCount = null,
                    Attributes = FromAttributes(otelSpan.Attributes),
                    TimeEvents = FromITimeEvents(otelSpan.Events),
                    Links = new Proto.Trace.V1.Span.Types.Links
                    {
                        Link = { otelSpan.Links.Select(FromILink), },
                    },
                });
            }
Beispiel #2
0
        /// <summary>
        /// Translating <see cref="Trace.Span"/> to Stackdriver's Span
        /// According to <see href="https://cloud.google.com/trace/docs/reference/v2/rpc/google.devtools.cloudtrace.v2"/> specifications.
        /// </summary>
        /// <param name="spanData">Span in OpenTelemetry format.</param>
        /// <param name="projectId">Google Cloud Platform Project Id.</param>
        /// <returns><see cref="ISpan"/>.</returns>
        public static Google.Cloud.Trace.V2.Span ToSpan(this Trace.Span spanData, string projectId)
        {
            var spanId = spanData.Context.SpanId.ToHexString();

            // Base span settings
            var span = new Google.Cloud.Trace.V2.Span
            {
                SpanName    = new SpanName(projectId, spanData.Context.TraceId.ToHexString(), spanId),
                SpanId      = spanId,
                DisplayName = new TruncatableString {
                    Value = spanData.Name
                },
                StartTime      = spanData.StartTimestamp.ToTimestamp(),
                EndTime        = spanData.EndTimestamp.ToTimestamp(),
                ChildSpanCount = null,
            };

            if (spanData.ParentSpanId != null)
            {
                var parentSpanId = spanData.ParentSpanId.ToHexString();
                if (!string.IsNullOrEmpty(parentSpanId))
                {
                    span.ParentSpanId = parentSpanId;
                }
            }

            // Span Links
            if (spanData.Links != null)
            {
                span.Links = new Google.Cloud.Trace.V2.Span.Types.Links
                {
                    Link = { spanData.Links.Select(l => l.ToLink()) },
                };
            }

            // Span Attributes
            if (spanData.Attributes != null)
            {
                span.Attributes = new Google.Cloud.Trace.V2.Span.Types.Attributes
                {
                    AttributeMap =
                    {
                        spanData.Attributes?.ToDictionary(
                            s => FormatLabel(s.Key),
                            s => s.Value?.ToAttributeValue()),
                    },
                };
            }

            return(span);
        }
        internal static Proto.Trace.V1.Span ToProtoSpan(this Trace.Span otelSpan)
        {
            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];

                otelSpan.Context.TraceId.CopyTo(traceIdBytes);
                otelSpan.Context.SpanId.CopyTo(spanIdBytes);

                var parentSpanIdString = ByteString.Empty;
                if (otelSpan.ParentSpanId != default)
                {
                    Span <byte> parentSpanIdBytes = stackalloc byte[8];
                    otelSpan.ParentSpanId.CopyTo(parentSpanIdBytes);
                    parentSpanIdString = ByteString.CopyFrom(parentSpanIdBytes.ToArray());
                }

                return(new Proto.Trace.V1.Span
                {
                    Name = otelSpan.Name,

                    // TODO: Utilize new Span.Types.SpanKind below when updated protos are incorporated, also confirm default for SpanKind.Internal
                    Kind = otelSpan.Kind == SpanKind.Client || otelSpan.Kind == SpanKind.Producer ?
                           Proto.Trace.V1.Span.Types.SpanKind.Client :
                           Proto.Trace.V1.Span.Types.SpanKind.Server,

                    TraceId = ByteString.CopyFrom(traceIdBytes.ToArray()),
                    SpanId = ByteString.CopyFrom(spanIdBytes.ToArray()),
                    ParentSpanId = parentSpanIdString,

                    StartTime = otelSpan.StartTimestamp.ToTimestamp(),
                    EndTime = otelSpan.EndTimestamp.ToTimestamp(),
                    Status = !otelSpan.Status.IsValid
                        ? null
                        : new Opentelemetry.Proto.Trace.V1.Status
                    {
                        Code = (int)otelSpan.Status.CanonicalCode,
                        Message = otelSpan.Status.Description ?? string.Empty,
                    },
                    ChildSpanCount = null,
                    Attributes = FromAttributes(otelSpan.Attributes),
                    TimeEvents = FromITimeEvents(otelSpan.Events),
                    Links = new Proto.Trace.V1.Span.Types.Links
                    {
                        Link = { otelSpan.Links.Select(FromILink), },
                    },
                });
            }
            catch (Exception e)
            {
                // TODO: Is there a way to handle this better?
                // This type of error processing is very aggressive and doesn't follow the
                // error handling practices when smart defaults should be used when possible.
                // See: https://github.com/open-telemetry/OpenTelemetry-dotnet/blob/master/docs/error-handling.md
                ExporterEventSource.Log.FailedToConvertToProtoDefinitionError(e);
            }

            return(null);
        }