feat(local): surface trace IDs, attribute table, and fix AI filter#1133
Conversation
Improve `sentry local serve` output so events are easier to correlate
and scan, and make `-f ai` catch GenAI activity on child spans.
- Surface a short `[trace:…]` token on error, transaction, and log tail
lines, and add `trace_id` to JSON output (logs read it from the
`sentry.trace.trace_id` attribute). Lets agents group related events.
- Add `--attributes`/`-a` to render an indented, aligned attribute table
grouped into user-custom vs SDK-default sections, sorted by key. JSON
output exposes the same split under `attributes.{user,sdk}`.
- Fix `-f ai` missing Vercel-AI-style transactions: `gen_ai.*` attributes
live on child spans of the HTTP handler, not the trace root, so the
filter now scans child span attributes too.
- Render user log attributes alphabetically so repeated lines align.
Fixes #1132
|
Codecov Results 📊✅ Patch coverage is 92.08%. Project has 5053 uncovered lines. Files with missing lines (2)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 81.35% 81.40% +0.05%
==========================================
Files 392 392 —
Lines 27070 27160 +90
Branches 17566 17617 +51
==========================================
+ Hits 22019 22107 +88
- Misses 5051 5053 +2
- Partials 1832 1832 —Generated by Codecov Action |
|
Marked ready — CI is green: Build, Unit Tests, E2E, Lint & Typecheck, CodeQL, semgrep, and secret scan all passed. Self-review turned up nothing to fix. @MathurAditya724 requested for review since you filed #1132. |
|
Not enabling auto-merge — this exceeds the small-change gate (716 lines / 6 files changed, plus new public API surface: the |
MathurAditya724
left a comment
There was a problem hiding this comment.
I reviewed this against #1132. This is a good direction and CI is green, but I don't think it's ready to merge yet because the -f ai fix is still incomplete.
Blocking finding:
src/lib/formatters/local.ts:844-855detects AI activity on child spans only by callinginferSemanticOp(spanAttrs).inferSemanticOponly returnsgen_aiforgen_ai.operation.name,gen_ai.tool.name, orgen_ai.agent.name(src/lib/formatters/semantic-display.ts:121-129). Other GenAI attributes that this same formatter already treats as GenAI display inputs, such asgen_ai.request.model,gen_ai.response.model,gen_ai.provider.name,gen_ai.data_source.id, andgen_ai.usage.*, can still be missed by-f aiwhen they live only on child spans. Since the linked issue describes missinggen_ai.*child-span data, the filter should detect GenAI/MCP by semantic key prefix or aligninferSemanticOpwith the GenAI display formatter.
Non-blocking risks:
src/lib/formatters/local.ts:330-350omits several semantic/instrumentation namespaces already recognized elsewhere, includinggraphql.,aws.s3.,cloudevents.,feature_flag.,process., anderror.. Those will be shown as user attributes, which weakens the claimed SDK-default vs user-custom split.src/lib/formatters/local.ts:391-406flattens all child span attributes into one map, so duplicate keys across child spans silently overwrite earlier values. That may hide multiple AI calls/models/token counts in one transaction.
I would add a regression test where -f ai matches a transaction whose child span has only gen_ai.request.model or gen_ai.usage.input_tokens and no gen_ai.operation.name/tool/agent key.
The -f ai filter relied on inferSemanticOp, which only flags gen_ai for gen_ai.operation.name/tool/agent keys. Spans carrying only gen_ai.request.model or gen_ai.usage.* (e.g. Vercel AI generations) were missed. Detect the full gen_ai.*/mcp.* namespace by key prefix instead. Also widen SDK_ATTRIBUTE_PREFIXES to cover graphql., aws.s3., cloudevents., feature_flag., process., and error. namespaces so the attribute-table SDK/user split matches the semantic display formatter.
|
Pushed Blocking finding (fixed): Non-blocking #1 (fixed): widened Non-blocking #2 (won't fix here): the child-span attribute flattening in |
formatLogJson sanitized log attribute values but passed keys through raw, so C1 controls or BiDi overrides in envelope-supplied attribute key names survived JSON.stringify and could drive terminal injection. Apply stripBidi() to the key, matching buildJsonAttributes.
MathurAditya724
left a comment
There was a problem hiding this comment.
Re-reviewed the latest head (916d2007) against my previous findings.
The blocking -f ai issue is fixed: transactionHasAiActivity now uses prefix-based hasAiAttributes detection for gen_ai.*/mcp.*, so child spans with only gen_ai.request.model or gen_ai.usage.input_tokens are included. The added regression tests cover those cases. The SDK/user attribute grouping concern was also addressed by widening SDK_ATTRIBUTE_PREFIXES.
The remaining child-span attribute flattening behavior is a reasonable non-blocking tradeoff for this PR. CI is green. No remaining blocking findings from me.
Improves
sentry local serveoutput so events are easier to correlate and scan, and fixes-f aimissing GenAI activity that lives on child spans.[trace:…]token, and JSON output includestrace_id(logs read it from thesentry.trace.trace_idattribute) — lets humans and agents group related events.--attributes/-aflag renders an indented, aligned table grouped into user-custom vs SDK-default sections, sorted by key. JSON exposes the same split underattributes.{user,sdk}.-f aipreviously only checked trace-root attributes, so Vercel-AI-style transactions (POST /api/ai/chat) wheregen_ai.*lives on child spans were missed. The filter now scans child span attributes too.Testing
bun run lint,tsc --noEmit, and the formatter/local test suites (920 formatter tests + local command tests) all pass. Added tests for the AI child-span filter, trace ID extraction/rendering across human + JSON output, log attribute ordering, andcollectSpanAttributes.Closes #1132