-
Notifications
You must be signed in to change notification settings - Fork 30.2k
Use W3C trace context headers to support OTEL trace propagation #56891
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
| const traceStateHeader = req.headers.tracestate | ||
| const traceParent = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? |
||
| typeof traceParentHeader === 'string' ? traceParentHeader : undefined | ||
| const traceState = | ||
| typeof traceStateHeader === 'string' ? traceStateHeader : undefined | ||
|
|
||
| return getTracer().trace( | ||
| BaseServerSpan.handleRequest, | ||
| { | ||
|
|
@@ -711,6 +720,7 @@ export default abstract class Server<ServerOptions extends Options = Options> { | |
| 'http.method': method, | ||
| 'http.target': req.url, | ||
| }, | ||
| reqHeaderTraceContext: { traceParent, traceState }, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
To clarify, do you mean to include the traceparent and tracestate properties in the top level of this TracerSpanOptions object? |
||
| }, | ||
| async (span) => | ||
| this.handleRequestImpl(req, res, parsedUrl).finally(() => { | ||
|
|
||
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
tracecall. For instance, this code could execute:And pass an optional
spanContextto thetrace()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
spanContexttotrace(), there should also be a way to propagate it via OpenTelemetry'scontext.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:
E.g. you could use
AWSXRayPropagatoror 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