public static JaegerLog ToJaegerLog(this Event timedEvent)
        {
            var tags = new PooledListState <JaegerTag>
            {
                Created = true,
                List    = PooledList <JaegerTag> .Create(),
            };

            DictionaryEnumerator <string, object, PooledListState <JaegerTag> > .AllocationFreeForEach(
                timedEvent.Attributes,
                ref tags,
                ProcessTagRef);

            // Matches what OpenTracing and OpenTelemetry defines as the event name.
            // https://github.com/opentracing/specification/blob/master/semantic_conventions.md#log-fields-table
            // https://github.com/open-telemetry/opentelemetry-specification/pull/397/files
            PooledList <JaegerTag> .Add(ref tags.List, new JaegerTag("message", JaegerTagType.STRING, vStr : timedEvent.Name));

            return(new JaegerLog(timedEvent.Timestamp.ToEpochMicroseconds(), tags.List));
        }
        public static JaegerSpan ToJaegerSpan(this Activity activity)
        {
            var jaegerTags = new TagState
            {
                Tags = PooledList <JaegerTag> .Create(),
            };

            DictionaryEnumerator <string, string, TagState> .AllocationFreeForEach(
                activity.Tags,
                ref jaegerTags,
                ProcessActivityTagRef);

            string peerServiceName = null;

            if ((activity.Kind == ActivityKind.Client || activity.Kind == ActivityKind.Producer) && jaegerTags.PeerService != null)
            {
                // Send peer.service for remote calls.
                peerServiceName = jaegerTags.PeerService;

                // If priority = 0 that means peer.service was already included in tags.
                if (jaegerTags.PeerServicePriority > 0)
                {
                    PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag(SpanAttributeConstants.PeerServiceKey, JaegerTagType.STRING, vStr : peerServiceName));
                }
            }

            // The Span.Kind must translate into a tag.
            // See https://opentracing.io/specification/conventions/
            if (activity.Kind != ActivityKind.Internal)
            {
                string spanKind = null;

                if (activity.Kind == ActivityKind.Server)
                {
                    spanKind = "server";
                }
                else if (activity.Kind == ActivityKind.Client)
                {
                    spanKind = "client";
                }
                else if (activity.Kind == ActivityKind.Consumer)
                {
                    spanKind = "consumer";
                }
                else if (activity.Kind == ActivityKind.Producer)
                {
                    spanKind = "producer";
                }

                if (spanKind != null)
                {
                    PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag("span.kind", JaegerTagType.STRING, vStr : spanKind));
                }
            }

            var activitySource = activity.Source;

            if (!string.IsNullOrEmpty(activitySource.Name))
            {
                PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag("library.name", JaegerTagType.STRING, vStr : activitySource.Name));

                if (!string.IsNullOrEmpty(activitySource.Version))
                {
                    PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag("library.version", JaegerTagType.STRING, vStr : activitySource.Version));
                }
            }

            var traceId      = Int128.Empty;
            var spanId       = Int128.Empty;
            var parentSpanId = Int128.Empty;

            if (activity.IdFormat == ActivityIdFormat.W3C)
            {
                // TODO: The check above should be enforced by the usage of the exporter. Perhaps enforce at higher-level.
                traceId      = new Int128(activity.TraceId);
                spanId       = new Int128(activity.SpanId);
                parentSpanId = new Int128(activity.ParentSpanId);
            }

            return(new JaegerSpan(
                       peerServiceName: peerServiceName,
                       traceIdLow: traceId.Low,
                       traceIdHigh: traceId.High,
                       spanId: spanId.Low,
                       parentSpanId: parentSpanId.Low,
                       operationName: activity.DisplayName,
                       flags: (activity.Context.TraceFlags & ActivityTraceFlags.Recorded) > 0 ? 0x1 : 0,
                       startTime: ToEpochMicroseconds(activity.StartTimeUtc),
                       duration: (long)activity.Duration.TotalMilliseconds * 1000,
                       references: activity.Links.ToJaegerSpanRefs(),
                       tags: jaegerTags.Tags,
                       logs: activity.Events.ToJaegerLogs()));
        }
        public static JaegerSpan ToJaegerSpan(this SpanData span)
        {
            var jaegerTags = new TagState
            {
                Tags = PooledList <JaegerTag> .Create(),
            };

            DictionaryEnumerator <string, object, TagState> .AllocationFreeForEach(
                span.Attributes,
                ref jaegerTags,
                ProcessAttributeRef);

            // Send peer.service for remote calls. If priority = 0 that means peer.service was already included.
            if ((span.Kind == SpanKind.Client || span.Kind == SpanKind.Producer) &&
                jaegerTags.PeerService != null &&
                jaegerTags.PeerServicePriority > 0)
            {
                PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag("peer.service", JaegerTagType.STRING, vStr : jaegerTags.PeerService));
            }

            // The Span.Kind must translate into a tag.
            // See https://opentracing.io/specification/conventions/
            if (span.Kind.HasValue)
            {
                string spanKind = null;

                if (span.Kind.Value == SpanKind.Server)
                {
                    spanKind = "server";
                }
                else if (span.Kind.Value == SpanKind.Client)
                {
                    spanKind = "client";
                }
                else if (span.Kind.Value == SpanKind.Consumer)
                {
                    spanKind = "consumer";
                }
                else if (span.Kind.Value == SpanKind.Producer)
                {
                    spanKind = "producer";
                }

                if (spanKind != null)
                {
                    PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag("span.kind", JaegerTagType.STRING, vStr : spanKind));
                }
            }

            DictionaryEnumerator <string, object, TagState> .AllocationFreeForEach(
                span.LibraryResource?.Attributes ?? Array.Empty <KeyValuePair <string, object> >(),
                ref jaegerTags,
                ProcessLibraryAttributeRef);

            var status = span.Status;

            if (status.IsValid)
            {
                if (!CanonicalCodeDictionary.TryGetValue(status.CanonicalCode, out string statusCode))
                {
                    statusCode = status.CanonicalCode.ToString();
                    CanonicalCodeDictionary.Add(status.CanonicalCode, statusCode);
                }

                PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag(StatusCode, JaegerTagType.STRING, vStr : statusCode));

                if (status.Description != null)
                {
                    PooledList <JaegerTag> .Add(ref jaegerTags.Tags, new JaegerTag(StatusDescription, JaegerTagType.STRING, vStr : status.Description));
                }
            }

            var traceId      = Int128.Empty;
            var spanId       = Int128.Empty;
            var parentSpanId = Int128.Empty;

            if (span.Context.IsValid)
            {
                traceId      = new Int128(span.Context.TraceId);
                spanId       = new Int128(span.Context.SpanId);
                parentSpanId = new Int128(span.ParentSpanId);
            }

            return(new JaegerSpan(
                       peerServiceName: jaegerTags.PeerService,
                       traceIdLow: traceId.Low,
                       traceIdHigh: traceId.High,
                       spanId: spanId.Low,
                       parentSpanId: parentSpanId.Low,
                       operationName: span.Name,
                       flags: (span.Context.TraceOptions & ActivityTraceFlags.Recorded) > 0 ? 0x1 : 0,
                       startTime: ToEpochMicroseconds(span.StartTimestamp),
                       duration: ToEpochMicroseconds(span.EndTimestamp) - ToEpochMicroseconds(span.StartTimestamp),
                       references: span.Links.ToJaegerSpanRefs(),
                       tags: jaegerTags.Tags,
                       logs: span.Events.ToJaegerLogs()));
        }