refactor(trace): Combine span decoration matching into one registry - #4254
refactor(trace): Combine span decoration matching into one registry#4254udita-0707 wants to merge 10 commits into
Conversation
Signed-off-by: udita-0707 <uditaa17644@gmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4254 +/- ##
=======================================
Coverage 92.02% 92.03%
=======================================
Files 373 373
Lines 12056 12068 +12
Branches 3258 3262 +4
=======================================
+ Hits 11095 11107 +12
Misses 839 839
Partials 122 122 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@yurishkuro @swetalin-10 PTAL |
|
Went through this — checked out the current head, ran it, and it renders correctly. Solid work on the consolidation itself. Still the one open thing though — on the issue you'd asked about |
|
Thank you @swetalin-10 for taking a look. |
Signed-off-by: Udita <153092248+udita-0707@users.noreply.github.com>
Signed-off-by: Udita <153092248+udita-0707@users.noreply.github.com>
Signed-off-by: udita-0707 <uditaa17644@gmail.com>
| * | ||
| * Rules encoded here: | ||
| * - No pill for a pure category signal already covered by an icon (e.g. span.kind). | ||
| * - gen_ai has no namespace icon here: GenAISpanIcon + classifySpan handle that (#4217). |
There was a problem hiding this comment.
what is the motivation for splitting out the GenAI mechanism?
There was a problem hiding this comment.
keeping classifySpan / GenAISpanIcon separate on purpose. Namespace icons are presence-only; GenAI picks a kind fromgen_ai.operation.name and that kind is also used outside the timeline (GenAI tab / isGenAITrace). A generic gen_ai namespace icon here is what caused the double-icon bug in #4217. The model name still belongs in PILL_SOURCES as a value pill.
There was a problem hiding this comment.
Namespace icons are presence-only
key+value check is just a generalization of "key exists" check. I am not convinced by the argument.
A generic gen_ai namespace icon here is what caused the double-icon bug in #4217
Even more reason to have a single mechanism instead of two.
There was a problem hiding this comment.
I see your point. Presence-only vs key+value doesn't really feel like a meaningful distinction.
What I'm thinking is, if we're moving towards a single mechanism in spanDecorations.ts, we could structure it like this:
-
Have a single ordered list of rules, where each rule defines both the match and the outcome (icon and/or pill):
anyKeyPrefix(db.,http., etc.) → namespace icon- key + value (
gen_ai.operation.name→chat,invoke_agent, etc.) → GenAI-specific icon gen_ai.prefix as a fallback → generic GenAI icon- specific keys → pills (
http.status_code,db.system,gen_ai.request.model, etc.)
-
Use a single icon resolver in
SpanBarRow, with GenAI-specific rules taking priority over namespace rules. That way we avoid renderinggetSpanIconComponentandGenAISpanIcontogether. -
classifySpancan continue handling the GenAI tab andisGenAITrace, but instead of maintaining its own mapping, it can read the same operation → kind registry so there's only one source of truth.
here's what I plan:
- In this PR, flatten things to
NAMESPACE_ICONS+PILL_SOURCESand removeDECORATION_FAMILIES/PILL_ONLY_SOURCES. - Then either as an immediate follow-up (or in this PR if you'd prefer), fold the GenAI icon logic into the same matcher and remove the dual-render path entirely.
If you'd prefer, I can also include the GenAI unification in this PR so everything is reviewed together.
@yurishkuro ,would this align with what you had in mind?
Signed-off-by: udita-0707 <uditaa17644@gmail.com>
|
@yurishkuro this is up for review, please have a look |
yurishkuro
left a comment
There was a problem hiding this comment.
Thanks for this, and sorry for the moving target — reviewing it made clear my issue text was too vague, so I have written an actual design into #4223. Two lists in one file was a fair reading of what I originally wrote.
The deltas from what you have: one entry per namespace owning both its icon and its pills (list position replaces the priority field and the separate PILL_SOURCES order), GEN_AI_OPERATION_TO_KIND back to being private in utils/genai/detect.ts, and span-icons.ts plus GenAISpanIcon.tsx collapsing into one presentational component. The reasoning for the middle one is worth a look: classifySpan runs in OtelSpanFacade's constructor at transform time, so that map is classification rather than decoration, and importing it from a component makes every trace transform depend on TraceTimelineViewer — and on three react-icons packages.
Worth keeping as-is: the resolver preferring GenAI kind over namespace icons is exactly right and is now written into the design, GEN_AI_KIND_META is in the right place, and the three getSpanDecorationIcon tests are the ones that earn their keep.
Two things the design does not cover, both from this diff:
- The GenAI icon now renders before the error icon; on
mainit came after. I think that is an improvement, but it needs saying in the description and pinning with a test rather than shipping under "no user-visible behavior change". - Most of
spanDecorations.test.tsrestates the literals above it — priorities unique and ascending, pill labels in a fixed order, no category-only pill. Those pass through any real regression, and several stop meaning anything once the two lists merge. #4223 lists the behavior cases I would rather have.
Nits: title should be refactor(trace): … so it maps to changelog:refactoring; it needs a changelog: label, which I will add once the title settles; and if (bestPriority === 0) break; is unreachable now that priorities start at 1.
🤖 Drafted with Claude Code, reviewed by @yurishkuro
Which problem is this PR solving?
Description of the changes
spanDecorations.tsregistry of decoration families (db/http/messaging/rpc) that owns both namespace→icon matching and value-bearing pill sourcesspan-icons.tsandspanPills.tsxto that registry (lookup/render only; no matching lists of their own)span.kind/ category-only pills)detect.ts/GenAISpanIcon(intentionally separate)spanPillsEnabledas a separate config toggleOut of scope (follow-up):
messaging.systempill (icon exists today; pill TBD)How was this change tested?
spanDecorations.test.ts,span-icons.test.ts,spanPills.test.ts,SpanBarRow.test.jsxpnpm run fmt,pnpm run tsc-lint,pnpm test,pnpm run buildChecklist
AI Usage in this PR (choose one)