feat(tanstackstart-react): Show readable server function names in traces#21190
Conversation
f01c86c to
e110c50
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8d0efef. Configure here.
8d0efef to
e5733b0
Compare
| 'sentry.origin': 'auto.function.tanstackstart.server', | ||
| 'tanstackstart.function.hash.sha256': expect.any(String), | ||
| }), | ||
| 'sentry.source': 'route', |
There was a problem hiding this comment.
Using this because from what I can see in my experiments the name here never has parameters so we don't need relay-side route parametrization
Use `serverFnMeta` from the function middleware context to replace hash-based server function span names with human-readable ones. Fixes #21185 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
e84a02f to
aa1ed88
Compare
| expect(transactionEvent?.spans).toEqual([ | ||
| expect.objectContaining({ | ||
| description: expect.stringContaining('GET /_serverFn/'), | ||
| description: 'GET /_serverFn/testLog', | ||
| op: 'function.tanstackstart', | ||
| origin: 'auto.function.tanstackstart.server', | ||
| data: expect.objectContaining({ | ||
| data: { | ||
| 'sentry.op': 'function.tanstackstart', | ||
| 'sentry.origin': 'auto.function.tanstackstart.server', | ||
| 'tanstackstart.function.hash.sha256': expect.any(String), | ||
| }), | ||
| 'sentry.source': 'route', | ||
| 'tanstackstart.function.id': expect.any(String), | ||
| 'tanstackstart.function.filename': 'src/routes/test-serverFn.tsx', | ||
| }, | ||
| }), | ||
| ]); | ||
| }); |
There was a problem hiding this comment.
Keep in mind that .objectContaining might ignore fields that matter as it does not to an equality check (is successful when one item is missing). You can either do toEqual or toBe on each individual item you want to check.
Same for all other checks in this PR.
There was a problem hiding this comment.
yes that's why I removed the .objectContaining, so this should now do an exact match
| server: createSentryFunctionMiddlewareHandler('auto.middleware.tanstackstart.server_function') as ( | ||
| ...args: any[] // eslint-disable-line @typescript-eslint/no-explicit-any | ||
| ) => any, // eslint-disable-line @typescript-eslint/no-explicit-any |
There was a problem hiding this comment.
Q: Why is the createSentryMiddlewareHandler removed from here?
There was a problem hiding this comment.
createSentryMiddlewareHandler only does a try catch essentially, so this is replaced with the new handler that also includes the logic to update the span with the metadata. createSentryMiddlewareHandler is still used for the global middleware that captures exceptions from API routes

Uses
serverFnMetafrom the TanStack Start function middleware context to replace hash-based server function span names with human-readable ones (e.g.GET /_serverFn/greetinstead ofGET /_serverFn/a10e70b3...). Also attaches function metadata (id,filename) as span attributes. The span still gets started inwrapFetchWithSentrybut then updated with the available metadata in the global function middleware. I only update the custom server function span itself and don't update the http span, so that one will now show up with a description ofGET /serverFn/*(see trace below). We can certainly think about also updating the http span, but I wasn't sure how to name this if there is for instance multiple nested server function calls. Happy to hear any thoughts on this.The
tanstackstart.function.hash.sha256span attribute has been renamed totanstackstart.function.id(should be more accurate name given that that is the name the framework itself uses for the metadata).Example trace from local testing:


Fixes #21185