-
Notifications
You must be signed in to change notification settings - Fork 27k
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
Use W3C trace context headers to support OTEL trace propagation #56891
Use W3C trace context headers to support OTEL trace propagation #56891
Conversation
@@ -711,6 +720,7 @@ export default abstract class Server<ServerOptions extends Options = Options> { | |||
'http.method': method, | |||
'http.target': req.url, | |||
}, | |||
reqHeaderTraceContext: { traceParent, traceState }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need the intermediary context object. Also let's use the traceparent
as is, without the camelcase, to follow the OTEL convention
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need the intermediary context object
To clarify, do you mean to include the traceparent and tracestate properties in the top level of this TracerSpanOptions object?
to test it out yourself, you can run |
As someone who maintains an internal patch for this support (hadn't had time to create an upstream PR yet): Can we get some tests as well to avoid breaking this in the future? |
Definitely agree @valkum, I am trying to figure out how to test this but haven't been able to find how this kind of tracer logic is tested within Next.js so would appreciate any pointer |
I think here would be the right place: https://github.com/vercel/next.js/blob/canary/test/e2e/opentelemetry/opentelemetry.test.ts |
@@ -702,6 +702,15 @@ export default abstract class Server<ServerOptions extends Options = Options> { | |||
): Promise<void> { | |||
await this.prepare() | |||
const method = req.method.toUpperCase() | |||
|
|||
// Extract the w3c trace context headers and pass them to tracer | |||
const traceParentHeader = req.headers.traceparent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO, it'd be better to either move the propagation extraction code from below to here or to pass headers to the trace
call. For instance, this code could execute:
spanContext = propagation.extract(context.active(), req.headers)
And pass an optional spanContext
to the trace()
method. This way the SDK can configure whatever propagation strategy it likes outside of Next and it'd work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't want to pass spanContext
to trace()
, there should also be a way to propagate it via OpenTelemetry's context.with()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the alternative, which, IMHO, should cover the target cases better: #57084
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK thanks, I was planning to work on your feedback today but I'm happy to let you take it from here with your PR
Can you help me understand how your PR is an improvement / expand on what you mean by This way the SDK can configure whatever propagation strategy it likes outside of Next and it'd work
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a otel setup (in an application, not in Next), you could do something like this:
traceProvider.register({
propagator: new XPropagator(),
})
E.g. you could use AWSXRayPropagator
or make your own.
This propagator could work off headers or some special environment context. Next.js wouldn't need to know any of that - it'd just call a generic propagator.extract()
and (eventually)propagator.inject()
and delegate this part fully to the configuration of the application or a deployment environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And FWIW, your PR is super close, it just limits which propagators can be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thanks for explaining and for opening your PR. I'll close this one out in favor of yours
// Extract the w3c trace context headers and pass them to tracer | ||
const traceParentHeader = req.headers.traceparent | ||
const traceStateHeader = req.headers.tracestate | ||
const traceParent = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we extract the propagation, should we also inject it in the downstream fetch calls? Or would that be too subjective?
Closing in favor of #57084 which does the same |
…7084) Implement OTEL propagation according to the OpenTelemetry API per https://opentelemetry.io/docs/specs/otel/context/api-propagators/. Any configured propagator should work with this API, including `W3CTraceContextPropagator` (https://www.w3.org/TR/trace-context/). Alternative to the #56891. /cc @sfirrin
Adding propagation to OTEL tracing
Implements OTEL propagation https://opentelemetry.io/docs/instrumentation/js/propagation/ for API route handler traces by extracting the W3C trace context headers https://www.w3.org/TR/trace-context/ from the request and using them to create the context for the active span.
I spent some time trying to figure out how best to test this but I wasn't sure. Would appreciate a pointer to existing tests for the tracer or any advice on testing this.
I followed the doc here https://github.com/vercel/next.js/blob/canary/contributing/core/developing-using-local-app.md and was able to confirm the header values are being used to create the context through logging, but have not been able to do a more thorough test end-to-end to confirm that the generated API route spans are parented correctly. I wanted to deploy a testing app to Vercel that uses my local Next.js build so I could double check that the headers are being used in the generated traces, but I ran into some problems getting the app to build correctly with my local version of Next.js. I asked in Discord here https://discord.com/channels/752553802359505017/1007476603422527558/threads/1162417878507737228 and someone has been helping out but I still haven't yet been able to deploy it. If the reviewer has any advice on the
Error: No Next.js version could be detected in your project. Make sure
"next"is installed in "dependencies" or "devDependencies"
error I'm getting there it would be appreciated (more context in Discord).*I was not able to find a checklist in the PR template for this that is a great match for this since it's not exactly a bug or a feature. Please let me know if anything should be added or expanded here