## What changed
Fixed three issues in the Trace Graph:
- **Multi-root traces no longer crash** — traces where root spans
belonged to distinct services, the same service, or had cyclic service
relationships now render correctly instead of showing an empty graph.
- **Overlapping node labels are truncated** — long service names in
chart nodes are capped at 24 characters with an ellipsis, preventing
overlap with the next tree level.
- **Tooltip now shows the service name** — the pattern node tooltip
header was missing the service name, making it impossible to seethe full
name of a truncated node on hover.
Also added `truncateText` utility to `zincutils.ts` and comprehensive
test fixtures covering all multi-root scenarios.
## What changed
Added a stream-selected guard before setting `searchObj.loading = true`
in the auto-query trigger in `SearchBar.vue`, and added an explicit
`searchObj.loading = false` reset in `Index.vue`'s `runQueryFn` when no
stream is selected.
## Why
When no stream is selected, auto-query is enabled, and the user switches
the date-time mode (relative → absolute → relative), `searchObj.loading`
was set to `true` by SearchBar but never reset to `false`. The
`runQueryFn` in Index.vue would early-return due to an empty
`selectedStream`, but did not clear the loading state, leaving the UI
stuck in an infinite loading spinner.
## Approach
- **SearchBar.vue** (line 2719): Added
`searchObj.data.stream.selectedStream.length > 0` to the condition that
triggers an auto-query on date-time change, preventing
`searchObj.loading = true` when there is no stream to query.
- **Index.vue** (lines 978–981): Inside `runQueryFn`, when
`selectedStream.length` is 0, explicitly set `searchObj.loading = false`
and `searchObj.runQuery = false` before returning, as a defense-in-depth
reset.
## What changed
Enriches the ServiceGraph Node Detail Panel for **inferred services**
(uninstrumented dependencies discovered from span attributes —
databases, message queues, RPC backends, external APIs). Instead of
showing only a single operation for these services, the panel now
displays type-specific dynamic tabs (Hosts, Databases, Queries,
Destinations, URLs, RPC Services) using field fallback chains with
COALESCE expressions, filtered against the actual stream schema.
## Why
Inferred services (detected via `infer_service_name`) previously showed
only one operation in the panel because they're derived from
CLIENT/PRODUCER spans. There was no way to see the different servers,
databases, or URLs they connect to. This PR adds structured context by
inspecting peer attributes (`server_address`, `net_peer_name`,
`db_namespace`, `messaging_destination_name`, etc.) and grouping data
into meaningful tabs per service type.
## Approach
- **INFERRED_SERVICE_TABS registry** — maps each `service_type`
(database/queue/rpc/external) to its relevant tabs with fallback field
chains (e.g., `["server_address", "net_peer_name", "net_peer_ip",
"network_peer_address"]`)
- **SQL helper functions** — `buildCoalesceExpr` and `buildNullCheck`
generate COALESCE expressions for GROUP BY/SELECT and OR clauses for
WHERE filters
- **Schema-aware field filtering** — `resolveStreamSchema` fetches the
trace stream schema; each tab's fallback fields are filtered against it,
dropping tabs with zero surviving fields
- **Caller-aware operations** — Operations table gains a "Caller" column
for inferred services, showing which upstream service invokes each
operation
- **Filter construction** — Row clicks on inferred service tabs generate
`(field1 = 'val' OR field2 = 'val')` filters instead of single-field
equality
- **Metrics tab hidden** for inferred services — no meaningful metric
correlation for uninstrumented backends
- Non-breaking — existing single-field `resourceFilter` paths left
unchanged; `handleServicesCatalogViewTraces` normalizes legacy string
payloads
## What changed
- Extracted parser-limitation guards into `isParserLimitation()` and
refactored `useSearchQuery.ts` to **not block the search** when the PEG
parser flags a false-positive error — the squiggle still shows but the
query proceeds to the backend
- Added a 4th parser-limitation guard for `found="("` inside window
function clauses (covers `SUM(COUNT(*)) OVER (...)`, `NTILE(N) OVER
(PARTITION BY COALESCE(...)...)`)
- Unified all four `fetchRumEventsForTrace` queries to a consistent
±60,000,000 µs buffer around the trace window
- Added `allowedTracingUrls` config + `propagatorTypes` to the RUM SDK
config snippet in `FrontendRumConfig.vue`
- Added an "Explain" query dropdown menu item in the logs SearchBar
- Fixed various traces/RUM UI padding and border issues
(PlayerEventsSidebar, TraceDetails, TracesMetricsDashboard,
SessionViewer)
- Updated i18n keys across all 12 language files
## Why
Two valid SQL queries produced false-positive validation errors
(`SUM(COUNT(*)) OVER (...)`, `NTILE(...) OVER (PARTITION BY
COALESCE(...)...)`), and even after suppressing those, the query was
still **blocked from executing** by `useSearchQuery.ts`. The PEG parser
has known gaps that the DataFusion backend handles correctly — there was
no reason to block valid queries. The RUM event queries also had
inconsistent time buffers across different calls (some used ±10s, others
±60s), causing missed RUM events in trace correlation.
## Approach
- Extracted the 4 parser-limitation guards from `validateSql()` into a
pure sync `isParserLimitation()` function exported from
`sqlDiagnostics.ts`, then reused it in `useSearchQuery.ts` to let query
execution continue when only parser limitations are detected
- Replaced inline constants with a shared `RUM_TIME_BUFFER_US =
60_000_000` in `useRumSpanBuilder.ts` so all four
`fetchRumEventsForTrace` queries use the same ±60s window
- Added `{ timeout: 30000 }` to the aggregate mutation test that was
timing out on ~5,500 broken queries
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## What changed
- Added a wrap/unwrap button (toggle) in the CorrelatedLogsTable header
toolbar, matching the pattern from `logs/SearchResult.vue` (`wrap-text`
icon, `OTooltip` with `search.messageWrapContent` i18n key)
- Replaced the hard-coded 800px column `maxSize` with a dynamic cap
computed from the table container's actual width, tracked via
`ResizeObserver`
- Last-column fill: if total column widths are less than the container
and the last column is a `longTextFields` type, the remaining space is
added to it
- Organizations actions icon not visible
- User section checkbox deselect not working
- Traces session dropdown fix
- Tooltip for stream field item
- New dashboard save button loading
#12351
Fixed RUM middleware in `middleware_data.rs` to extract
`ootags`/`o2tags` from the request body when the field is not present in
URL query parameters. Previously, the middleware only inspected query
parameters for these fields, but the RUM SDK sends them in the request
body.
## Why
User logs confirmed the issue: `ootags raw=None, o2tags raw=None`
appeared consistently in the middleware logs even when the RUM SDK
included tags like `env`, `service`, `version`, and `sdk_version`. Geo
keys (which come from a different extraction path) were unaffected,
narrowing the root cause to query-param-only parsing of
`ootags`/`o2tags`. The RUM SDK sends these tags in the POST body, not as
query string parameters.
## Approach
Added body-parsing logic to read and decode the request body when
`ootags`/`o2tags` are absent from query parameters. The body is parsed
once using `url::form_urlencoded` and merged into the existing key-value
map before the `filter_tags` step runs, ensuring the same downstream
pipeline works unchanged.
---------
Co-authored-by: Neha P <neha@openobserve.ai>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
Co-authored-by: Neha P <144308844+neha00290@users.noreply.github.com>
- SDR Save Settings trigger point discrepency
- Edit the existing alert - Ai icon is overlapping
- On stream field Scroller is not working
- With other languages, the Side Navigation UI is broken
- Search box dont having any border (List search view )
- text area color not looks proper
- Pipeline history - pagination is not working properly
- iam page default pagination value change
- Org display on top right should have a bigger width - more real estate
can be used there
- Date - picker does not show selection when selection 27th may to 20th
may
- Date - picker also does not handle selection if use selects 27th may
first and 20th may later, it should select the correct date no matter
what user selects the date in.
- when searching across folders in dashboard, it shows no data instead
of skeleton loading
- https://github.com/openobserve/o2-enterprise/issues/1824
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
#11936
## What changed
Fixed `TraceDetails.vue` so that `traceServiceMap` captures services
from **all** root span nodes in a trace, not just the first one.
Previously, traces with two or more root spans (e.g., from misconfigured
instrumentation) would show service data only for the first root.
## Why
When a trace has multiple root spans, the service-map waterfall widget
and trace-graph display were incomplete — only the first root's services
appeared. Users investigating instrumentation issues or multi-root
traces (which the existing UI already supports rendering) were missing
service data for the second and subsequent roots.
#11841
## What changed
Added `queryParams.stream = effectiveStreamName.value` to the share URL
generation in `TraceDetails.vue` so the stream name is included when
generating a share/short URL.
## Why
When sharing a URL from the Trace Details view, the stream name
parameter was missing from the generated URL. This caused the shared
link to open without the correct stream context, making it unable to
display the trace properly on navigation.
## Approach
The stream name is already resolved by the `effectiveStreamName`
computed property — which handles both embedded mode (via
`props.streamNameProp`) and standalone mode (via
`router.currentRoute.value.query.stream`). The fix simply passes this
value into the `queryParams` object before the URL is serialized.
#11816
## What changed
Added an optional `skipSearch` parameter to `SearchBar.vue`'s
`applyFilters` method. When `true`, the method applies filters to state
without emitting a `searchdata` event. In `Index.vue`,
`onMetricsFiltersUpdated` now passes `skipSearch=true` when live mode is
ON, letting the datetime trigger (`triggerAbsoluteQueryDebounced`)
handle the search call. When live mode is OFF, `skipSearch=false` so the
search still fires (since the datetime trigger won't run).
## Why
When auto-search is enabled and a user drags on RED charts to select a
time range, both `applyFilters` and `triggerAbsoluteQueryDebounced` were
called simultaneously — each triggering a separate `searchdata` API
call. Per the user, "searchdata should only be called from
triggerAbsoluteQueryDebounced." The fix ensures only one search call
happens by having `applyFilters` skip its own search when live mode is
on.
#11615
## What changed
Extracted duplicate resize/mousedown/mousemove/mouseup logic from
`TraceDetails.vue` (horizontal resizer) and `FlameGraphView.vue`
(vertical resizer) into a shared `useResizer` composable. The flame
graph now embeds a `TraceDetailsSidebar` in a resizable bottom panel
directly, rather than only emitting `span-selected` events to a parent.
## Why
Both `TraceDetails.vue` and `FlameGraphView.vue` independently
implemented the same resize pattern (`mousedown` → `mousemove` delta
calculation → `mouseup` cleanup), creating duplicated logic that was
brittle and hard to maintain. Additionally, the flame graph view needed
to host the trace details sidebar inline to support the full span-detail
workflow without requiring a parent component to manage the panel.
## Approach
- Created `web/src/composables/useResizer.ts` accepting `direction`,
`initialValue`, `minValue`/`maxValue`, `unit`, `containerRef` (for
percentage mode), `throttleMs`, `invert`, and `onResize` callback —
returns `value`, `isResizing`, and `onMouseDown`.
- Replaced the manual event-binding code in `TraceDetails.vue` (both
left-panel and DAG resizers) with calls to `useResizer`.
- Replaced the duplicated resize code in `FlameGraphView.vue` with
`useResizer`; added a bottom panel section containing
`TraceDetailsSidebar`.
- Added `sidebarVisible` state and `selectedSpan` computed from a new
`spanMap` prop to `FlameGraphView.vue`.
- The `invert` option was added during the session because vertical
resizing worked in the opposite direction — moving the mouse up
increased the element height instead of decreasing it.
- Updated tests to cover sidebar visibility, `selectedSpanId` store
sync, and the new props.
#11740
## Why
Users viewing correlated logs from traces saw results from only one
stream (the "primary" stream). Multi-stream setups where different
streams use different field names for the same semantic concept (e.g.,
`k8s_namespace_name` vs `service_k8s_namespace_name`) would silently
drop streams whose schemas didn't match the filter field exactly. This
PR makes correlation queries multi-stream-aware across both traces and
logs.
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## What changed
Replaced single-stream correlation log queries with multi-stream
support. The composable now builds independent SQL queries for each
correlated log stream and sends them as an array to
`_search_multi_stream`, merging and sorting results by `_timestamp` on
completion. Also temporarily disabled hover span selection in the trace
tree due to UX issues, and made the timestamp column configurable via
`store.state.zoConfig.timestamp_column`.
## Why
The previous implementation only queried the primary stream (first log
stream), missing correlated logs from other streams. Multi-stream
support is needed to show all correlated logs across streams. Hover span
selection was producing `null` span IDs on unhover, causing UX glitches
— disabled pending a proper fix.