public PropagationContext(ulong traceId, ulong parentSpanId, SamplingPriority?samplingPriority, string?origin)
 {
     TraceId          = traceId;
     ParentSpanId     = parentSpanId;
     SamplingPriority = samplingPriority;
     Origin           = origin;
 }
 /// <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;
 }
Beispiel #3
0
        private static PropagationContext?ExtractContext(IServiceRemotingRequestMessageHeader messageHeaders)
        {
            try
            {
                ulong traceId = messageHeaders.TryGetHeaderValueUInt64(HttpHeaderNames.TraceId) ?? 0;

                if (traceId > 0)
                {
                    ulong parentSpanId = messageHeaders.TryGetHeaderValueUInt64(HttpHeaderNames.ParentId) ?? 0;

                    if (parentSpanId > 0)
                    {
                        SamplingPriority?samplingPriority = (SamplingPriority?)messageHeaders.TryGetHeaderValueInt32(HttpHeaderNames.SamplingPriority);
                        string?          origin           = messageHeaders.TryGetHeaderValueString(HttpHeaderNames.Origin);

                        return(new PropagationContext(traceId, parentSpanId, samplingPriority, origin));
                    }
                }

                return(null);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error extracting message headers.");
                return(default);
Beispiel #4
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;
 }
Beispiel #5
0
        public static SpanContext Extract(this IHeaderDictionary headers)
        {
            if (headers == null)
            {
                throw new ArgumentNullException(nameof(headers));
            }

            ulong            traceId          = 0;
            ulong            parentId         = 0;
            SamplingPriority?samplingPriority = null;

            if (headers.TryGetValue(HttpHeaderNames.TraceId, out var traceIdHeaders))
            {
                ulong.TryParse(traceIdHeaders.FirstOrDefault(), NumberStyles.Integer, CultureInfo.InvariantCulture, out traceId);
            }

            if (traceId == 0)
            {
                // a valid traceId is required to use distributed tracing
                return(null);
            }

            if (headers.TryGetValue(HttpHeaderNames.ParentId, out var parentIdHeaders))
            {
                ulong.TryParse(parentIdHeaders.FirstOrDefault(), NumberStyles.Integer, CultureInfo.InvariantCulture, out parentId);
            }

            if (headers.TryGetValue(HttpHeaderNames.SamplingPriority, out var samplingPriorityHeaders) &&
                int.TryParse(samplingPriorityHeaders.FirstOrDefault(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var samplingPriorityValue))
            {
                samplingPriority = (SamplingPriority?)samplingPriorityValue;
            }

            return(new SpanContext(traceId, parentId, samplingPriority));
        }
Beispiel #6
0
        /// <summary>
        /// Event handler called when the Service Remoting client sends a request.
        /// </summary>
        /// <param name="sender">The object that raised the event.</param>
        /// <param name="e">The event arguments.</param>
        private static void ServiceRemotingClientEvents_SendRequest(object?sender, EventArgs?e)
        {
            if (!_initialized)
            {
                return;
            }

            GetMessageHeaders(e, out var eventArgs, out var messageHeaders);

            try
            {
                var tracer = Tracer.Instance;
                var span   = CreateSpan(tracer, context: null, SpanKinds.Client, eventArgs, messageHeaders);

                try
                {
                    // inject propagation context into message headers for distributed tracing
                    if (messageHeaders != null)
                    {
                        SamplingPriority?samplingPriority = span.Context.TraceContext?.SamplingPriority ?? span.Context.SamplingPriority;
                        string?          origin           = span.GetTag(Tags.Origin);
                        var context = new PropagationContext(span.TraceId, span.SpanId, samplingPriority, origin);

                        InjectContext(context, messageHeaders);
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "Error injecting message headers.");
                }

                tracer.ActivateSpan(span);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or activating span.");
            }
        }
Beispiel #7
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(ulong?traceId, ulong spanId, SamplingPriority?samplingPriority, string serviceName = null)
     : this(traceId, serviceName)
 {
     SpanId           = spanId;
     SamplingPriority = samplingPriority;
 }
Beispiel #8
0
        // This small application follows the RabbitMQ tutorial at https://www.rabbitmq.com/tutorials/tutorial-one-dotnet.html
        public static void Main()
        {
            var factory = new ConnectionFactory()
            {
                HostName = "localhost"
            };

            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.QueueDeclare(queue: "hello",
                                         durable: false,
                                         exclusive: false,
                                         autoDelete: false,
                                         arguments: null);

                    var consumer = new EventingBasicConsumer(channel);
                    consumer.Received += (model, ea) =>
                    {
                        // Receive message
                        var body    = ea.Body.ToArray();
                        var message = Encoding.UTF8.GetString(body);

                        // Read the basic property headers and extract the Datadog properties
                        var              headers          = ea.BasicProperties.Headers;
                        ulong?           parentSpanId     = null;
                        ulong?           traceId          = null;
                        SamplingPriority?samplingPriority = null;

                        // Parse parentId header
                        if (headers?[HttpHeaderNames.ParentId] is byte[] parentSpanIdBytes)
                        {
                            parentSpanId = BitConverter.ToUInt64(parentSpanIdBytes, 0);
                        }

                        // Parse traceId header
                        if (headers?[HttpHeaderNames.TraceId] is byte[] traceIdBytes)
                        {
                            traceId = BitConverter.ToUInt64(traceIdBytes, 0);
                        }

                        // Parse samplingPriority header
                        if (headers?[HttpHeaderNames.SamplingPriority] is byte[] samplingPriorityBytes)
                        {
                            var samplingPriorityString = Encoding.UTF8.GetString(samplingPriorityBytes);
                            if (Enum.TryParse <SamplingPriority>(samplingPriorityString, out var result))
                            {
                                samplingPriority = result;
                            }
                        }

                        // Create a new SpanContext to represent the distributed tracing information
                        SpanContext propagatedContext = null;
                        if (parentSpanId.HasValue && traceId.HasValue)
                        {
                            propagatedContext = new SpanContext(traceId, parentSpanId.Value, samplingPriority);
                        }

                        // Start a new Datadog span
                        using (var scope = Tracer.Instance.StartActive("rabbitmq.consume", propagatedContext))
                        {
                            // Log message and properties to screen
                            Console.WriteLine(" [x] Received.");
                            Console.WriteLine("     Message: {0}", message);
                            Console.WriteLine("     Active TraceId: {0}", scope.Span.TraceId);
                            Console.WriteLine("     Active SpanId: {0}", scope.Span.SpanId);
                            Console.WriteLine("     Active SamplingPriority: {0}", scope.Span.GetTag(Tags.SamplingPriority));

                            // Set Datadog tags
                            var span = scope.Span;
                            span.SetTag(Tags.SpanKind, SpanKinds.Consumer);
                            span.SetTag("amqp.exchange", ea.Exchange);
                            span.SetTag("amqp.routing_key", ea.RoutingKey);

                            // Do work inside the Datadog trace
                            Thread.Sleep(1000);
                        }
                    };
                    channel.BasicConsume(queue: "hello",
                                         autoAck: true,
                                         consumer: consumer);

                    Console.WriteLine(" Press [enter] to exit.");
                    Console.ReadLine();
                }
            }
        }