elastic / apm-agent-nodejs

https://www.elastic.co/guide/en/apm/agent/nodejs/current/index.html
BSD 2-Clause "Simplified" License
582 stars 225 forks source link

Set the traceparent in the middle of a request #2308

Open exejutable opened 3 years ago

exejutable commented 3 years ago

How i can set the current traceparent, im using SNS and i cant add the traceparent header, i send it in the message. So i want to set it in the middle of the request, is this possible?

pd: im using 3.16.0 version

Thanks

astorm commented 3 years ago

It's not possible to change the traceparent value of a transaction that's already started.

Speaking generally the workflow we've outlines in our docs for using SQS should work with SNS as well. Specifically, you'll access the current traceparent value set on the active transaction, set it as a message attribute (or similar) on your queue message, and then use that traceparent header when you're starting a transaction in your queue processing code.

@exejutable -- does that answer your question, or did I miss the mark?

exejutable commented 2 years ago

This dosn't work with SNS, i lost part of the logs if i create a transaction using another traceparent in the middle of a HTTP request

Maybe adding a traceparent interceptor?


type resolverFunction = (request: Request) => string | undefined;

export interface TraceParentInterceptor {
  url: string,
  resolver: resolverFunction
}

let traceParentInterceptors: TraceParentInterceptor[]= [

  {
    url: '/api/sns/*',
    resolver: (request: Request) => {
      // Obtain the traceparent  and return  for example in sns
      let traceparent;
      if (request.body.message) {
        let message = JSON.parse(request.body.Message);
        traceparent = message.traceparent;
      }
      return traceparent;
    },
  },
];

export const apm = agent.start({

  transactionIgnoreUrls: [
    '/api/alive/',
    '/api/alive',
  ],
  ignoreUrls: [
    '/api/alive/',
    '/api/alive',
  ],

  traceparentInterceptors: traceParentInterceptors
}
trentm commented 2 years ago

@exejutable We are in the process of adding support for Span Links (OpenTelemetry's description of span links is here: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/overview.md#links-between-spans).

Here is the relevant section of our APM Agents spec that talks about how to handle trace-context on received messages: https://github.com/elastic/apm/blob/main/specs/agents/tracing-instrumentation-messaging.md#receiving-trace-context

... Otherwise (a single message being captured as a messaging span, or a batch of messages is processed in a single messaging transaction or span), a span link SHOULD be added for each message with Trace Context. This includes the case where the size of the batch of received messages is one.

So one suggestion (when all of the support for this lands) will be to add a span with a span link using the traceparent in that received message. https://github.com/elastic/apm-agent-nodejs/pull/2692 recently added an API to the APM agent to support this (there isn't a release with it quite yet, probably next week). It would look something like:

apm.startSpan('mySpanName', { links: [ { context: traceparentStringFromMessage } ] })

A coming version of the Kibana APM app will support viewing and clicking through those span links.