-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(tanstackstart-react): Add wrappers for manual instrumentation of servers-side middlewares #18680
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
base: develop
Are you sure you want to change the base?
Conversation
node-overhead report 🧳Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.
|
| } catch (e) { | ||
| span.end(); | ||
| throw e; | ||
| } |
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.
Span status not set when middleware throws error
Medium Severity
When a middleware throws an error, span.end() is called before re-throwing. Since startSpanManual's error handler only sets SPAN_STATUS_ERROR when span.isRecording() returns true, and isRecording() returns false for ended spans, the error status is never set. This causes middleware error spans to appear successful (with undefined status) instead of properly indicating failure. The span status needs to be set to error before calling span.end() in the catch block.
This PR adds a middleware wrapper to the
tanstackstartSDK that allows users to add tracing to their application middleware. Eventually we will want to patch this automatically, but that is a bit tricky since it requires build-time magic. This API provides a manual alternative for now and can later still act as a fallback for cases where auto-instrumentation doesn't work.How it works
The wrapper patches the middleware
options.serverfunction that gets executed whenever a middleware is run. Each middleware invocation creates a span with:At first I had the issue that if multiple middlewares were used they would be nested (i.e. first middleware is parent of second etc.). This is because the middlewares call
next()to move down the middleware chain, so trivially starting a span for the middleware execution would actually create a span that would last for the current middleware and any middlewares that come after in the middleware chain. I fixed that by also proxyingnext(), where I end the middleware span and then also reattach the middleware spans to the parent request span instead of the previous middleware span.Usage
Tests
Added E2E tests for:
Screenshots from sample app
Using two global request middlewares:
Closes #18666