Пример #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SpanContext"/> class
 /// from a propagated context. <see cref="Parent"/> will be null
 /// since this is a root context locally.
 /// </summary>
 /// <param name="traceId">The propagated trace id.</param>
 /// <param name="spanId">The propagated span id.</param>
 /// <param name="samplingPriority">The propagated sampling priority.</param>
 /// <param name="serviceName">The service name to propagate to child spans.</param>
 /// <param name="traceState">The W3C tracestate.</param>
 public SpanContext(TraceId?traceId, ulong spanId, SamplingPriority?samplingPriority, string serviceName = null, string traceState = null)
     : this(traceId, serviceName)
 {
     SpanId           = spanId;
     SamplingPriority = samplingPriority;
     TraceState       = traceState;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="SpanContext"/> class
 /// from a propagated context. <see cref="Parent"/> will be null
 /// since this is a root context locally.
 /// </summary>
 /// <param name="traceId">The propagated trace id.</param>
 /// <param name="spanId">The propagated span id.</param>
 /// <param name="samplingPriority">The propagated sampling priority.</param>
 /// <param name="serviceName">The service name to propagate to child spans.</param>
 /// <param name="origin">The propagated origin of the trace.</param>
 internal SpanContext(TraceId?traceId, ulong spanId, SamplingPriority?samplingPriority, string serviceName, string origin)
     : this(traceId, serviceName)
 {
     SpanId           = spanId;
     SamplingPriority = samplingPriority;
     Origin           = origin;
 }
Пример #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SpanContext"/> class
 /// from a propagated context. <see cref="Parent"/> will be null
 /// since this is a root context locally.
 /// </summary>
 /// <param name="traceId">The propagated trace id.</param>
 /// <param name="spanId">The propagated span id.</param>
 /// <param name="samplingPriority">The propagated sampling priority.</param>
 /// <param name="serviceName">The service name to propagate to child spans.</param>
 /// <param name="origin">The propagated origin of the trace.</param>
 /// <param name="rawTraceId">The raw propagated trace id</param>
 /// <param name="rawSpanId">The raw propagated span id</param>
 internal SpanContext(TraceId?traceId, ulong spanId, int?samplingPriority, string serviceName, string origin, string rawTraceId, string rawSpanId)
     : this(traceId, serviceName)
 {
     SpanId           = spanId;
     SamplingPriority = samplingPriority;
     Origin           = origin;
     RawTraceId       = rawTraceId;
     RawSpanId        = rawSpanId;
 }
Пример #4
0
        public SpanContext Extract(IPropagatorMap propagatorMap)
        {
            if (propagatorMap == null)
            {
                throw new ArgumentNullException(nameof(propagatorMap));
            }

            TraceId?traceId = null;
            ulong?  spanId = null, parentId = null;
            bool    sampled = false, debug = false;;

            foreach (var entry in propagatorMap)
            {
                if (string.Equals(entry.Key, TraceIdHeader, StringComparison.OrdinalIgnoreCase))
                {
                    if (TraceId.TryParse(entry.Value, out var _trace))
                    {
                        traceId = _trace;
                    }
                }
                else if (string.Equals(entry.Key, SpanIdHeader, StringComparison.OrdinalIgnoreCase))
                {
                    if (ulong.TryParse(entry.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var _spanId))
                    {
                        spanId = _spanId;
                    }
                }
                else if (string.Equals(entry.Key, ParentIdHeader, StringComparison.OrdinalIgnoreCase))
                {
                    if (ulong.TryParse(entry.Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var _parent))
                    {
                        parentId = _parent;
                    }
                }
                else if (string.Equals(entry.Key, SampledHeader, StringComparison.OrdinalIgnoreCase))
                {
                    sampled = string.Equals(entry.Value, SampledTrue);
                }
                else if (string.Equals(entry.Key, DebugHeader, StringComparison.OrdinalIgnoreCase))
                {
                    debug = string.Equals(entry.Value, SampledTrue);
                }
            }
            if (traceId == null || spanId == null)
            {
                return(null);
            }
            return(new SpanContext(traceId.Value,
                                   spanId.Value,
                                   parentId,
                                   sampled,
                                   debug,
                                   shared: false));
        }
Пример #5
0
        private SpanContext(TraceId?traceId, string serviceName)
        {
            ServiceName = serviceName;
            if (traceId.HasValue)
            {
                TraceId = traceId.Value;
                return;
            }

            TraceId = TraceId.CreateRandom();
            SpanId  = GenerateId();
        }
Пример #6
0
        private SpanContext(TraceId?traceId, string serviceName)
        {
            TraceId     = traceId ?? Tracer.Instance.TracerManager.TraceIdConvention.GenerateNewTraceId();
            ServiceName = serviceName;

            // Because we have a ctor as part of the public api without accepting the origin tag,
            // we need to ensure new SpanContext created by this .ctor has the CI Visibility origin
            // tag if the CI Visibility mode is running to ensure the correct propagation
            // to children spans and distributed trace.
            if (CIVisibility.IsRunning)
            {
                Origin = Ci.Tags.TestTags.CIAppTestOriginName;
            }
        }
Пример #7
0
        protected override SpanContext Extract(ITextMap carrier)
        {
            TraceId?         traceId  = null;
            SpanId?          spanId   = null;
            SpanId           parentId = new SpanId(0); // Conventionally, parent id == 0 means the root span
            SpanContextFlags flags    = SpanContextFlags.None;

            foreach (var entry in carrier)
            {
                if (string.Equals(entry.Key, SampledName, StringComparison.OrdinalIgnoreCase))
                {
                    string value = entry.Value;
                    if (string.Equals(value, "1", StringComparison.Ordinal) || string.Equals(value, "true", StringComparison.OrdinalIgnoreCase))
                    {
                        flags |= SpanContextFlags.Sampled;
                    }
                }
                else if (string.Equals(entry.Key, TraceIdName, StringComparison.OrdinalIgnoreCase))
                {
                    traceId = TraceId.FromString(entry.Value);
                }
                else if (string.Equals(entry.Key, ParentSpanIdName, StringComparison.OrdinalIgnoreCase))
                {
                    parentId = SpanId.FromString(entry.Value);
                }
                else if (string.Equals(entry.Key, SpanIdName, StringComparison.OrdinalIgnoreCase))
                {
                    spanId = SpanId.FromString(entry.Value);
                }
                else if (string.Equals(entry.Key, FlagsName, StringComparison.OrdinalIgnoreCase))
                {
                    if (string.Equals(entry.Value, "1", StringComparison.OrdinalIgnoreCase))
                    {
                        flags |= SpanContextFlags.Debug;
                    }
                }
            }

            if (traceId != null && spanId != null)
            {
                return(new SpanContext(traceId.Value, spanId.Value, parentId, flags));
            }
            return(null);
        }
 private SpanContext(TraceId?traceId, string serviceName)
 {
     TraceId     = traceId ?? Tracer.Instance.TraceIdConvention.GenerateNewTraceId();
     ServiceName = serviceName;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="SpanContext"/> class
 /// from a propagated context. <see cref="Parent"/> will be null
 /// since this is a root context locally.
 /// This constructor is used by W3C propagation.
 /// </summary>
 /// <param name="traceId">The propagated trace id.</param>
 /// <param name="spanId">The propagated span id.</param>
 /// <param name="traceState">The W3C tracestate.</param>
 public SpanContext(TraceId?traceId, ulong spanId, string traceState)
     : this(traceId, serviceName : null)
 {
     SpanId     = spanId;
     TraceState = traceState;
 }
Пример #10
0
        public SpanContext Extract(ITextMap carrier)
        {
            // try to extract the single B3 propagation value instead
            var single = _singleHeaderPropagator.Extract(carrier);

            if (single != null)
            {
                return(single);
            }

            TraceId?   traceId  = null;
            string     spanId   = null;
            string     parentId = null;
            var        debug    = false;
            var        sampled  = false;
            const bool shared   = false;

            foreach (var entry in carrier)
            {
                switch (entry.Key.ToLowerInvariant())
                {
                case B3TraceId:
                    if (!TraceId.TryParse(entry.Value, out var t))
                    {
                        throw new ZipkinFormatException(
                                  $"TraceId in format [{entry.Value}] is incompatible. Please use an X16 encoded 128bit or 64bit id.");
                    }
                    traceId = t;
                    break;

                case B3SpanId:
                    spanId = entry.Value;
                    break;

                case B3ParentId:
                    parentId = entry.Value;
                    break;

                case B3Debug:
                    if (entry.Value.Equals("1"))
                    {
                        debug = true;
                    }
                    break;

                case B3Sampled:
                    if (entry.Value.Equals("1") || entry.Value.ToLowerInvariant().Equals("true")
                        ) // support older tracers https://github.com/petabridge/Petabridge.Tracing.Zipkin/issues/72
                    {
                        sampled = true;
                    }
                    break;
                }
            }

            if (traceId != null && spanId != null) // don't care of ParentId is null or not
            {
                return(new SpanContext(traceId.Value, spanId, parentId, debug, sampled, shared));
            }
            return(null);
        }
Пример #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SpanContext"/> class
 /// from a propagated context. <see cref="Parent"/> will be null
 /// since this is a root context locally.
 /// </summary>
 /// <param name="traceId">The propagated trace id.</param>
 /// <param name="spanId">The propagated span id.</param>
 /// <param name="samplingPriority">The propagated sampling priority.</param>
 /// <param name="serviceName">The service name to propagate to child spans.</param>
 public SpanContext(TraceId?traceId, ulong spanId, SamplingPriority?samplingPriority = null, string serviceName = null)
     : this(traceId, serviceName)
 {
     SpanId           = spanId;
     SamplingPriority = (int?)samplingPriority;
 }
Пример #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SpanContext"/> class
        /// that is the child of the specified parent context.
        /// </summary>
        /// <param name="parent">The parent context.</param>
        /// <param name="traceContext">The trace context.</param>
        /// <param name="serviceName">The service name to propagate to child spans.</param>
        /// <param name="traceId">Override the trace id if there's no parent.</param>
        /// <param name="spanId">The propagated span id.</param>
        /// <param name="rawTraceId">Raw trace id value</param>
        /// <param name="rawSpanId">Raw span id value</param>
        internal SpanContext(ISpanContext parent, TraceContext traceContext, string serviceName, TraceId?traceId = null, ulong?spanId = null, string rawTraceId = null, string rawSpanId = null)
            : this(parent?.TraceId ?? traceId, serviceName)
        {
            SpanId       = spanId ?? SpanIdGenerator.ThreadInstance.CreateNew();
            Parent       = parent;
            TraceContext = traceContext;
            if (parent is SpanContext spanContext)
            {
                Origin     = spanContext.Origin;
                RawTraceId = spanContext.RawTraceId ?? rawTraceId;
            }
            else
            {
                RawTraceId = rawTraceId;
            }

            RawSpanId = rawSpanId;
        }
Пример #13
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationId">The id of the integration creating this scope.</param>
        /// <param name="tags">The tags associated to the scope</param>
        /// <param name="traceId">The trace id - this id will be ignored if there's already an active trace</param>
        /// <param name="spanId">The span id</param>
        /// <param name="startTime">The start time that should be applied to the span</param>
        /// <param name="addToTraceContext">Set to false if the span is meant to be discarded. In that case, the span won't be added to the TraceContext.</param>
        /// <returns>A new pre-populated scope.</returns>
        internal static Span CreateInactiveOutboundHttpSpan(Tracer tracer, string httpMethod, Uri requestUri, IntegrationId integrationId, out HttpTags tags, TraceId?traceId, ulong?spanId, DateTimeOffset?startTime, bool addToTraceContext)
        {
            tags = null;

            if (!tracer.Settings.IsIntegrationEnabled(integrationId) || PlatformHelpers.PlatformStrategy.ShouldSkipClientSpan(tracer.InternalActiveScope) || HttpBypassHelper.UriContainsAnyOf(requestUri, tracer.Settings.HttpClientExcludedUrlSubstrings))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            Span span = null;

            try
            {
                if (GetActiveHttpScope(tracer) != null)
                {
                    // we are already instrumenting this,
                    // don't instrument nested methods that belong to the same stacktrace
                    // e.g. HttpClientHandler.SendAsync() -> SocketsHttpHandler.SendAsync()
                    return(null);
                }

                string resourceUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : true, tryRemoveIds : true) : null;

                string httpUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : false, tryRemoveIds : false) : null;

                tags = new HttpTags();

                // Upstream uses "http.request" for the span name but following legacy version and the
                // OpenTelemetry specification we use the capitalized method as the span name.
                string uppercaseHttpMethod = httpMethod?.ToUpperInvariant();

                string serviceName = tracer.Settings.GetServiceName(tracer, ServiceName);
                span = tracer.StartSpan(uppercaseHttpMethod, tags, serviceName: serviceName, traceId: traceId, spanId: spanId, startTime: startTime, addToTraceContext: addToTraceContext);

                span.Type         = SpanTypes.Http;
                span.ResourceName = $"{httpMethod} {resourceUrl}";
                span.LogicScope   = OperationName;

                tags.HttpMethod          = uppercaseHttpMethod;
                tags.HttpUrl             = httpUrl;
                tags.InstrumentationName = IntegrationRegistry.GetName(integrationId);

                tags.SetAnalyticsSampleRate(integrationId, tracer.Settings, enabledWithGlobalSetting: false);

                if (!addToTraceContext && span.Context.TraceContext.SamplingPriority == null)
                {
                    // If we don't add the span to the trace context, then we need to manually call the sampler
                    span.Context.TraceContext.SetSamplingPriority(tracer.TracerManager.Sampler?.GetSamplingPriority(span));
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating span.");
            }

            // always returns the span, even if it's null because we couldn't create it,
            // or we couldn't populate it completely (some tags is better than no tags)
            return(span);
        }
Пример #14
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationId">The id of the integration creating this scope.</param>
        /// <param name="tags">The tags associated to the scope</param>
        /// <param name="traceId">The trace id - this id will be ignored if there's already an active trace</param>
        /// <param name="spanId">The span id</param>
        /// <param name="startTime">The start time that should be applied to the span</param>
        /// <returns>A new pre-populated scope.</returns>
        internal static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, IntegrationId integrationId, out HttpTags tags, TraceId?traceId = null, ulong?spanId = null, DateTimeOffset?startTime = null)
        {
            var span = CreateInactiveOutboundHttpSpan(tracer, httpMethod, requestUri, integrationId, out tags, traceId, spanId, startTime, addToTraceContext: true);

            if (span != null)
            {
                return(tracer.ActivateSpan(span));
            }

            return(null);
        }