private void HandleStart(RabbitMqEvent <RabbitMqHandleParams> evt)
        {
            try
            {
                var prms = evt.Params;
                DistributedTracingData tracingData = null;
                if (prms.Properties != null && prms.Properties.Headers.TryGetValue(Constants.HeaderKey, out object tracingDataBlob) && tracingDataBlob is byte[])
                {
                    tracingData = DistributedTracingData.TryDeserializeFromString(Encoding.UTF8.GetString((byte[])tracingDataBlob));
                }

                if (MatchesIgnoreMessageQueues(prms.RoutingKey))
                {
                    return;
                }

                var transaction = _ApmAgent.Tracer.StartTransaction(prms.RoutingKey, Constants.Type, tracingData);

                if (!_processingQueries.TryAdd(prms.Id, transaction))
                {
                    return;
                }

                transaction.SetLabel(nameof(prms.RoutingKey), prms.RoutingKey);
                transaction.SetLabel(nameof(prms.ConsumerTag), prms.ConsumerTag);
                transaction.SetLabel(nameof(prms.DeliveryTag), $"{prms.DeliveryTag}");
                transaction.SetLabel(nameof(prms.Exchange), prms.Exchange);
                transaction.SetLabel(nameof(prms.Redelivered), $"{prms.ConsumerTag}");
                transaction.SetLabel(nameof(prms.Body), prms.Body != null ? System.Text.Encoding.UTF8.GetString(prms.Body) : string.Empty);
            }
            catch
            {
            }
        }
        /// <inheritdoc />
        public IApmSpan Start(string spanKind, string operationName, string type, IDictionary <string, string> existingContext = null, string resourceName = null)
        {
            if (!global::Elastic.Apm.Agent.IsConfigured)
            {
                return(NullApmSpan.Instance);
            }

            var tracer = global::Elastic.Apm.Agent.Tracer;
            DistributedTracingData?distributedTracingData = null;

            if (existingContext != null && existingContext.TryGetValue("ElasticDTD", out var d))
            {
                distributedTracingData = DistributedTracingData.TryDeserializeFromString(d);
            }

            if (tracer.CurrentTransaction == null)
            {
                return(new ElasticSpan(tracer.StartTransaction(
                                           operationName,
                                           type,
                                           distributedTracingData)));
            }

            return(new ElasticSpan(
                       tracer.CurrentTransaction.StartSpan(operationName, type, resourceName)));
        }
Exemple #3
0
        private static void Main(string[] args)
        {
            if (args.Length == 1)             //in case it's started with an argument we try to parse the argument as a DistributedTracingData
            {
                WriteLineToConsole($"Callee process started - continuing trace with distributed tracing data: {args[0]}");
                var transaction2 = Agent.Tracer.StartTransaction("Transaction2", "TestTransaction",
                                                                 DistributedTracingData.TryDeserializeFromString(args[0]));

                try
                {
                    transaction2.CaptureSpan("TestSpan", "TestSpanType", () => Thread.Sleep(200));
                }
                finally
                {
                    transaction2.End();
                }

                Thread.Sleep(1000);
                WriteLineToConsole("About to exit");
            }
            else
            {
                WriteLineToConsole("Started");
                PassDistributedTracingData();

                //WIP: if the process terminates the agent
                //potentially does not have time to send the transaction to the server.
                Thread.Sleep(1000);

                WriteLineToConsole("About to exit - press any key...");
                Console.ReadKey();
            }
        }
        public override IDisposable Consume(IQueue queue,
                                            Func <byte[], MessageProperties, MessageReceivedInfo, Task> onMessage,
                                            Action <IConsumerConfiguration> configure)
        {
            async Task NewOnMessage(byte[] body, MessageProperties properties, MessageReceivedInfo receivedInfo)
            {
                if (!Agent.IsConfigured)
                {
                    await onMessage(body, properties, receivedInfo).ConfigureAwait(false);

                    return;
                }

                DistributedTracingData tracingData = null;

                if (properties.Headers.ContainsKey("traceparent") &&
                    properties.Headers["traceparent"] is string traceparent)
                {
                    tracingData = DistributedTracingData.TryDeserializeFromString(traceparent);
                }

                var transaction = Agent.Tracer.StartTransaction(receivedInfo.Queue, "event", tracingData);

                try
                {
                    await onMessage(body, properties, receivedInfo).ConfigureAwait(false);
                }
                finally
                {
                    transaction.End();
                }
            }

            return(base.Consume(queue, NewOnMessage, configure));
        }
Exemple #5
0
        public static DistributedTracingData GetTracingData(string traceId, string parentId, bool flagRecorded)
        {
            //NOTE: Not ideal - this really should just be using the constructor but it is marked private
            var serialized = TraceParent.BuildTraceparent(traceId, parentId, flagRecorded);

            return(DistributedTracingData.TryDeserializeFromString(serialized));
        }
        /// <inheritdoc />
        public IApmSpan StartOperation(ApiOperationDescriptor operation, string spanKind, IDictionary <string, string> existingContext = null)
        {
            if (!global::Elastic.Apm.Agent.IsConfigured)
            {
                return(NullApmSpan.Instance);
            }

            var tracer = global::Elastic.Apm.Agent.Tracer;

            if (tracer.CurrentTransaction != null)
            {
                // If a transaction is already underway we want to set it's name for a more accurate picture (i.e. this is
                // a HTTP call but we want to use the operation name not the HTTP route name).
                tracer.CurrentTransaction.Name = operation.Name;

                // We will also start a new span as there may be work before and after in the framework that should
                // be tracked separately from the Blueprint processing work.
                return(new ElasticSpan(
                           tracer.CurrentTransaction.StartSpan(operation.Name, ApiConstants.TypeRequest, "operation", ApiConstants.ActionExec)));
            }

            DistributedTracingData?distributedTracingData = null;

            if (existingContext != null && existingContext.TryGetValue("ElasticDTD", out var d))
            {
                distributedTracingData = DistributedTracingData.TryDeserializeFromString(d);
            }

            return(new ElasticSpan(tracer.StartTransaction(
                                       operation.Name,
                                       spanKind,
                                       distributedTracingData)));
        }
Exemple #7
0
        public void HandleProcessError_should_call_CaptureTransaction_as_expected(Message message,
                                                                                  bool withTransactionName, bool withTrace)
        {
            var transactionName = withTransactionName ? TransactionName : HandleProcessErrorTransaction;
            var traceParent     = withTrace ? DistributedTracingData.TryDeserializeFromString(TraceParent) : null;

            _elasticApmMessageProcessor.HandleProcessError(message, _publisherMock.Object, new Exception(), _processorMock.Object.HandleProcessError);

            _elasticApmTracerMock.Verify(e => e.CaptureTransaction(transactionName, It.IsAny <string>(), It.IsAny <Func <bool> >(), traceParent));
        }
Exemple #8
0
        public void ProcessMessage_should_call_CaptureTransaction_as_expected(Message message, bool withTransactionName,
                                                                              bool withTrace)
        {
            var transactionName = withTransactionName ? TransactionName : ProcessMessageTransacion;
            var traceParent     = withTrace ? DistributedTracingData.TryDeserializeFromString(TraceParent) : null;

            _elasticApmMessageProcessor.ProcessMessage(message, _publisherMock.Object, _processorMock.Object.ProcessMessage);

            _elasticApmTracerMock.Verify(e => e.CaptureTransaction(transactionName, It.IsAny <string>(), It.IsAny <Action>(), traceParent));
        }
Exemple #9
0
        private DistributedTracingData getDistributedTracingData(ServerCallContext context)
        {
            Metadata.Entry         metadataEntry          = context.RequestHeaders.FirstOrDefault(m => String.Equals(m.Key.ToLower(), "elastic-apm-traceparent", StringComparison.Ordinal));
            DistributedTracingData distributedTracingData = null;

            if (metadataEntry != null && !metadataEntry.Equals(default(Metadata.Entry)) && metadataEntry.Value != null)
            {
                distributedTracingData = DistributedTracingData.TryDeserializeFromString(metadataEntry.Value);
            }
            return(distributedTracingData);
        }
        static void Main(string[] args)
        {
            if (args.Length == 1)             //in case it's started with an argument we try to parse the argument as a DistributedTracingData
            {
                Console.WriteLine($"Process started - continuing trace with distributed tracing data: {args[0]}");

                var distributedTracingData = DistributedTracingData.TryDeserializeFromString(args[0]);
                var transaction2           = Agent.Tracer.StartTransaction("Transaction2", "TestTransaction", distributedTracingData);

                try
                {
                    transaction2.CaptureSpan("TestSpan", "TestSpanType", () => Thread.Sleep(200));
                }
                finally
                {
                    transaction2.End();
                }

                Thread.Sleep(2000);

                Console.WriteLine("About to exit - press any key...");
                Console.ReadKey();
            }
            else
            {
                Console.WriteLine("Started");

                Console.WriteLine("Capturing a transaction");
                var transaction = Agent.Tracer.StartTransaction("Transaction1", "TestTransaction");

                try
                {
                    var outgoingDistributedTracingData = Agent.Tracer.CurrentTransaction?.OutgoingDistributedTracingData?.SerializeToString();

                    Console.WriteLine($"The value of the distributed tracing data: {outgoingDistributedTracingData}");
                    Console.WriteLine($"Waiting 20 sec to continue the trace");

                    Thread.Sleep(20000);
                }
                finally
                {
                    transaction.End();
                }

                //WIP: if the process terminates the agent
                //potentially does not have time to send the transaction to the server.


                Console.WriteLine("About to exit - press any key...");
                Console.ReadKey();
            }
        }
Exemple #11
0
        public async Task <CommandResult> Handle(TCommand command, RequestContext context)
        {
            var  commandName      = command.GetType().FullName;
            bool shouldCreateSpan = traceSettings?.ShouldCreateSpan(commandName) ?? false;

            CommandResult commandResult = null;

            if (!shouldCreateSpan)
            {
                commandResult = await decoratedRequestHandler.Handle(command, context);
            }

            if (!context.Headers.ContainsKey(DistributedTracingHeader.DistributedTracingDataKey))
            {
                string outgoingDistributedTracingData =
                    (tracer.CurrentSpan?.OutgoingDistributedTracingData
                     ?? tracer.CurrentTransaction?.OutgoingDistributedTracingData)?.SerializeToString();

                context.Headers.Add(DistributedTracingHeader.DistributedTracingDataKey, outgoingDistributedTracingData);
            }

            if (tracer.CurrentTransaction == null)
            {
                await tracer.CaptureTransaction(commandName.ToTransactionName(), commandName.ToTransactionType(), async(transaction) =>
                {
                    // transaction.Labels["TK"] = "kadirzade";
                    await tracer.CurrentTransaction.CaptureSpan(commandName.ToSpanName(), commandName.ToSpanType(), async(span) =>
                    {
                        commandResult = await decoratedRequestHandler.Handle(command, context);
                    });
                }, DistributedTracingData.TryDeserializeFromString(context.Headers[DistributedTracingHeader.DistributedTracingDataKey]));
            }
            else
            {
                await tracer.CurrentTransaction.CaptureSpan(commandName.ToSpanName(), commandName.ToSpanType(), async (span) =>
                {
                    commandResult         = await decoratedRequestHandler.Handle(command, context);
                    span.Labels["result"] = commandResult.FormatResult();
                });
            }

            return(commandResult);
        }
        public async Task <QueryResult <TResponse> > Handle(TQuery query, RequestContext context)
        {
            var  queryName        = query.GetType().FullName;
            bool shouldCreateSpan = traceSettings?.ShouldCreateSpan(queryName) ?? false;
            QueryResult <TResponse> queryResult = null;

            if (!shouldCreateSpan)
            {
                queryResult = await decoratedRequestHandler.Handle(query, context);
            }

            if (!context.Headers.ContainsKey(DistributedTracingHeader.DistributedTracingDataKey))
            {
                string outgoingDistributedTracingData =
                    (tracer.CurrentSpan?.OutgoingDistributedTracingData
                     ?? tracer.CurrentTransaction?.OutgoingDistributedTracingData)?.SerializeToString();

                context.Headers.Add(DistributedTracingHeader.DistributedTracingDataKey, outgoingDistributedTracingData);
            }

            if (tracer.CurrentTransaction == null)
            {
                await tracer.CaptureTransaction(queryName.ToTransactionName(), queryName.ToTransactionType(), async() =>
                {
                    await tracer.CurrentTransaction.CaptureSpan(queryName.ToSpanName(), queryName.ToSpanType(), async(span) =>
                    {
                        queryResult = await decoratedRequestHandler.Handle(query, context);
                    });
                }, DistributedTracingData.TryDeserializeFromString(context.Headers[DistributedTracingHeader.DistributedTracingDataKey]));
            }
            else
            {
                await tracer.CurrentTransaction.CaptureSpan(queryName.ToSpanName(), queryName.ToSpanType(), async (span) =>
                {
                    queryResult           = await decoratedRequestHandler.Handle(query, context);
                    span.Labels["result"] = queryResult.FormatResult();
                    span.Type             = "";
                });
            }

            return(queryResult);
        }
        private void FillSpanLinks(PropertyFetcherCollection cachedProperties, IExecutionSegment segment, KeyValuePair <string, object> kv)
        {
            var messages = cachedProperties.Fetch(kv.Value, "Messages") as IEnumerable <object>;

            var spanLinks = new List <SpanLink>();

            if (messages != null)
            {
                foreach (var message in messages)
                {
                    if (message.GetType().GetProperty("UserProperties")?.GetValue(message) is Dictionary <string, object> properties)
                    {
                        foreach (var property in properties)
                        {
                            if (property.Key.Equals("Diagnostic-Id", StringComparison.InvariantCultureIgnoreCase))
                            {
                                var parsedTraceParent = DistributedTracingData.TryDeserializeFromString(property.Value.ToString());
                                if (parsedTraceParent != null)
                                {
                                    spanLinks.Add(new SpanLink(parsedTraceParent.ParentId, parsedTraceParent.TraceId));
                                }
                            }
                        }
                    }
                }
            }

            switch (segment)
            {
            case Model.Transaction t: t.InsertSpanLinkInternal(spanLinks);
                break;

            case Model.Span s: s.InsertSpanLinkInternal(spanLinks);
                break;
            }
        }
Exemple #14
0
        public override Task <bool> ReceiveAsync <T>(T message, QueueMessageContext messageContext,
                                                     ReceiveAsyncDelegate <T>?callback = null)
        {
            var tracer = GetTracer();

            if (tracer != null)
            {
                var transaction = tracer.CurrentTransaction;
                if (transaction == null)
                {
                    return(tracer.CaptureTransaction($"Process {message.GetType().FullName}",
                                                     ApiConstants.TypeRequest, () => base.ReceiveAsync(message, messageContext, callback), DistributedTracingData.TryDeserializeFromString(messageContext.RequestId)));
                }

                return(transaction.CaptureSpan($"Process {message.GetType().FullName}", ApiConstants.TypeExternal,
                                               () => base.ReceiveAsync(message, messageContext, callback), "Queue"));
            }

            return(base.ReceiveAsync(message, messageContext, callback));
        }
        public bool HandleProcessError(IMessage message, IPublisher publisher, Exception error, Func <IMessage, IPublisher, Exception, bool> handleProcessError)
        {
            var method = new StackFrame().GetMethod();
            var name   = GetName(message, method, handleProcessError.GetMethodInfo().Name);

            if (!message.Headers.ContainsKey(ApmConstants.TraceParent))
            {
                return(_elasticApmtracer.CaptureTransaction(name, TransactionType, () => handleProcessError(message, publisher, error)));
            }
            var traceParent = message.Headers[ApmConstants.TraceParent].ToString();

            return(_elasticApmtracer.CaptureTransaction(name, TransactionType, () => handleProcessError(message, publisher, error), DistributedTracingData.TryDeserializeFromString(traceParent)));
        }
Exemple #16
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseAllElasticApm(_configuration);

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    var output = new StringBuilder();
                    output.Append("<ul>");
                    output.Append("<li><a href=\"/trans1/1\">Distributed Transaction 1</a></li>");
                    output.Append("<li><a href=\"/trans2\">Distributed Transaction 2</a></li>");
                    output.Append("</ul>");

                    context.Response.ContentType = "text/html";
                    await context.Response.WriteAsync(output.ToString());
                });

                endpoints.MapGet("/trans1/1", async context =>
                {
                    var trans = Agent.Tracer.StartTransaction("Dist Trans 1", ApiConstants.TypeRequest);
                    await trans.CaptureSpan("step 1 processing", ApiConstants.ActionExec, async() => await Task.Delay(30));
                    trans.End();

                    var trace = trans.OutgoingDistributedTracingData.SerializeToString();

                    await context.Response.WriteAsync($"<a href=\"/trans1/2?s={trace}\">Continue</a>");
                });

                endpoints.MapGet("/trans1/2", async context =>
                {
                    var deser = DistributedTracingData.TryDeserializeFromString(context.Request.Query["s"]);

                    var trans = Agent.Tracer.StartTransaction("Dist Trans 1", ApiConstants.TypeRequest,
                                                              deser);
                    await trans.CaptureSpan("step 2 processing", ApiConstants.ActionExec, async() => await Task.Delay(15));
                    trans.End();

                    var trace = trans.OutgoingDistributedTracingData.SerializeToString();

                    await context.Response.WriteAsync($"<a href=\"/trans1/3?s={trace}\">Continue</a>");
                });

                endpoints.MapGet("/trans1/3", async context =>
                {
                    var deser = DistributedTracingData.TryDeserializeFromString(context.Request.Query["s"]);

                    var trans = Agent.Tracer.StartTransaction("Dist Trans 1", ApiConstants.TypeRequest,
                                                              deser);
                    await trans.CaptureSpan("step 3 processing", ApiConstants.ActionExec, async() => await Task.Delay(40));
                    trans.End();

                    await context.Response.WriteAsync($"<a href=\"/trans1/1\">Restart</a> / <a href=\"/\">Exit</a>");
                });

                endpoints.MapGet("/trans2", async context =>
                {
                    // transaction 1
                    var trans1 = Agent.Tracer.StartTransaction("Dist Trans 2", ApiConstants.TypeRequest);
                    await trans1.CaptureSpan("step 1 processing", ApiConstants.ActionExec, async() => await Task.Delay(30));
                    trans1.End();

                    // transaction 2
                    var trans2 = Agent.Tracer.StartTransaction("Dist Trans 2", ApiConstants.TypeRequest,
                                                               DistributedTracingData.TryDeserializeFromString(trans1.OutgoingDistributedTracingData.SerializeToString()));
                    await trans2.CaptureSpan("step 2 processing", ApiConstants.ActionExec, async() => await Task.Delay(30));
                    trans2.End();

                    // transaction 3
                    var trans3 = Agent.Tracer.StartTransaction("Dist Trans 2", ApiConstants.TypeRequest,
                                                               DistributedTracingData.TryDeserializeFromString(trans2.OutgoingDistributedTracingData.SerializeToString()));
                    await trans3.CaptureSpan("step 3 processing", ApiConstants.ActionExec, async() => await Task.Delay(30));
                    trans3.End();

                    await context.Response.WriteAsync($"<a href=\"/trans2\">Restart</a> / <a href=\"/\">Exit</a>");
                });
            });
        }
 private static DistributedTracingData BuildDistributedTracingData(string traceId, string parentId, string traceFlags) =>
 DistributedTracingData.TryDeserializeFromString(
     "00-" +                     // version
     (traceId == null ? "" : $"{traceId}") +
     (parentId == null ? "" : $"-{parentId}") +
     (traceFlags == null ? "" : $"-{traceFlags}"));
        public void ProcessMessage(IMessage message, IPublisher publisher, Action <IMessage, IPublisher> processMessage)
        {
            var method = new StackFrame().GetMethod();
            var name   = GetName(message, method, processMessage.GetMethodInfo().Name);
            var traceAsyncTransaction = GetTraceAsyncTransaction(message);

            if (message.Headers.ContainsKey(ApmConstants.TraceParent) && traceAsyncTransaction)
            {
                var traceParent = message.Headers[ApmConstants.TraceParent].ToString();
                _elasticApmtracer.CaptureTransaction(name, TransactionType, () => processMessage(message, publisher), DistributedTracingData.TryDeserializeFromString(traceParent));
            }
            else
            {
                _elasticApmtracer.CaptureTransaction(name, TransactionType, () => processMessage(message, publisher));
            }
        }