Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I update the traceparent after the operation was started? #973

Closed
johnib opened this issue May 26, 2022 · 2 comments
Closed

How can I update the traceparent after the operation was started? #973

johnib opened this issue May 26, 2022 · 2 comments

Comments

@johnib
Copy link

johnib commented May 26, 2022

I have the following setup:

  • node v16
  • applicationinsights v2.3.3
  • auto collection fully enabled (requests, dependencies, etc.)
  • expressjs v4

My app runs behind a proxy that I cannot configure differently, which alters the header names, including the traceparent header.
If the AI sdk doesn't see this header, it starts with a clean context -- and this is what I want to fix.

Questions:

  • Is there a way to configure the header name containing the traceparent ID ? (guess not, so next question)
  • Is there a method (even a private one) that I can update the context with the traceparent that I will provide? (even a hack would work for me in this case)

Thank you

@hectorhdzg
Copy link
Member

@johnib there is no way to update the header name to use to maintain the correlation in the SDK, you can manually track the requests and create the context using startOperation method, you can also get a reference to the current correlation context using getCurrentContext method and update it, never tried that, definitely hacky but maybe it works in your scenario, disabling automatic tracking and manually handling the request and the context should be better in this case.

@johnib
Copy link
Author

johnib commented Jun 29, 2022

Was a bit tricky, but made it work eventually.
Had to:

  • Extract the traceparent value from the custom header and use it to override the appInsights.getCorrelationContext().operation fields

    • as soon as possible (first middleware set on the express app)
    • at this point, the request telemetry item is already created and initialized with random correlation IDs (hence the second bullet)
    • however it is necessary for all subsequent telemetry items that will be created once the actual flow is executed (dependencies, traces, exceptions, etc.)
  • Add a telemetryProcessor that specifically handles request telemetry items to override the following envelope fields:

envelope.tags['ai.operation.parentId'] = context.correlationContext.operation.traceparent.parentId;
envelope.tags['ai.operation.id'] = context.correlationContext.operation.traceparent.traceId;
envelope.data.baseData.id = context.correlationContext.operation.parentId;

Here is the code, I'm open for improvements.. or a change that would allow me to remove this hack:

/**
 * Call this method as soon as possible after initializing the express app
 *
 * @param {import('express').Express} app
 * @param {String} headerName the header name containing the traceparent value
 */
const configureTraceparentOverride = (app, headerName = 'x-aws-sqsd-attr-traceparent') => {
  const overrideCorrelationContextMiddleware = (req, res, next) => {
    const traceparent = req.header(headerName);
    const { operation } = appInsights.getCorrelationContext();

    if (traceparent) {
      const overwriteTraceparent = new Traceparent(traceparent); // creating a traceparent object from the value coming from a different header
      overwriteTraceparent.spanId = operation.traceparent.spanId; // overriding the spanId to the one generated by the SDK (representing the request.id)
      operation.traceparent = overwriteTraceparent;
      operation.parentId = overwriteTraceparent.getBackCompatRequestId();
      operation.id = operation.traceparent.traceId;
    }

    next();
  };

  const updateTraceparentCorrelationAttributes = (envelope, context) => {
    try {
      const telemetryType = envelope.data.baseType;

      switch (telemetryType) {
        case 'RequestData': {
          envelope.tags['ai.operation.parentId'] = context.correlationContext.operation.traceparent.parentId;
          envelope.tags['ai.operation.id'] = context.correlationContext.operation.traceparent.traceId;
          envelope.data.baseData.id = context.correlationContext.operation.parentId;
        }
      }
    } catch (err) {
      console.error(err);
    }
  };

  app.use(overrideCorrelationContextMiddleware);
  appInsights.defaultClient.addTelemetryProcessor(updateTraceparentCorrelationAttributes);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants