mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 00:08:55 +00:00
Fixes #3764 Supersedes #13195 (stale base, unsigned CLA, and non-rendering — see Units below). The event-parsing and exception-detection approach from that PR is reused, credited via `Co-authored-by`. ## What this adds - **Trace waterfall** — a marker per span event, positioned against the trace window alongside the span bar. Clicking one selects its span. - **Sidebar mini-timeline** — the same events re-plotted against the *span's own* duration, above the Events tab. Answers "where within the span did this fire?", which the waterfall can't show for short spans and the table only shows as absolute timestamps. Clicking a marker expands the matching row. - **Exceptions stand out** — OTel semconv detection (`exception` name or any flattened `exception.*` attribute) renders in the error token; other events in amber. Both are existing registered tokens, so theming is automatic and no new tokens were added. Issue #3764 asks for "dots for events **and** exceptions", so all events are marked with exceptions emphasised, rather than filtering to exceptions only. ## Units — why the previous attempt rendered nothing A span event's `_timestamp` is raw OTLP `time_unix_nano` (**nanoseconds**), stored unconverted: Frontend span timing is **microseconds**. The same field name therefore means different units on a span than on its events. #13195 compared the two directly, so every marker landed ~1000x outside the window and was silently dropped by the range filter — matching the "I couldn't see the UI changes" report on that PR. The `ns → µs` conversion is now confined to one composable and pinned by a regression test using nanosecond fixtures. Corroboration that events are nanoseconds: the sidebar's own events table already divides the same field by `1e6` to render milliseconds. ## Structure `web/src/composables/traces/useSpanEvents.ts` owns event semantics — parse (array or JSON string), convert, classify — while each caller supplies its own window. The two surfaces differ only in that window. Events with no usable timestamp, or outside the window, are skipped rather than pinned to an invented position. ## Verification - `npm run type-check` — clean - ESLint on changed files — 0 errors, 0 warnings - `prettier --check` — conforms - Vitest — **184 passed**: 27 new (`useSpanEvents.spec.ts`), 7 new (`SpanBlock.spec.ts`), 7 new (`TraceDetailsSidebar.spec.ts`), rest pre-existing Pre-existing and untouched: three `no-dupe-keys` errors in `eslint.config.js`, and a `vue/no-dupe-keys` warning for `activeTab` in `TraceDetailsSidebar.vue` (confirmed present on unmodified `main`). ## Reviewer notes - **Not yet validated against a live ingested trace.** That step is what would have caught #13195, and it is the one gap here. - Specifically worth checking: `gen_ai.*` events are constructed with `_timestamp: 0` in the OTel processor's test fixtures. If real SDK data does the same, LLM spans will show no markers (dropped rather than mispositioned, by design). If that turns out to be real, the follow-up is an explicit "N events without timestamps" affordance, not a fabricated position. - Marker clustering for very dense event sets is deliberately deferred until real traces show it is needed. --------- Co-authored-by: coyaSONG <66289470+coyaSONG@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>