## What changed
- Passes `matchedSetId` and `chipDimensions` as new computed props from
`IncidentDetailDrawer.vue` to the embedded
`TelemetryCorrelationDashboard`, enabling the "View by" subject tabs in
the incident view
- Adds an `OBadge` showing the selected subject as `label = value` after
the subject toggle tabs in `CorrelationEventHeader.vue`
- Fixes the responsive overflow logic so the first context chip can
overflow when space runs out, and the overflow indicator shows "N
Fields" when all chips are hidden instead of a bare "+N"
- Renders hidden overflow chips as stacked `OBadge` components in
`OTooltip`'s `#content` slot instead of a `\n`-joined string
## Why
Incidents opened without a source trace or log event had no
`matchedSetId` / `chipDimensions` passed to the correlation dashboard,
so the "View by" subject toggle (Pod, Node, etc.) never rendered. The
badge was also missing to visually indicate which subject is active.
#12703
## What changed
Removed the `showErrorOnly` key from `searchObj.meta` state and replaced
it with a `computed` property that derives from
`activeIncludeFilterValues` — specifically checking whether
`span_status` includes `"ERROR"`. The `SearchResult.vue` component now
receives `showErrorOnly` as a prop from `Index.vue` instead of reading
it from the shared composable state. `TracesMetricsDashboard.vue` had
its own writable `showErrorOnly` computed removed since it no longer
needs to sync a top-level state key.
## Why
The user identified that `showErrorOnly` was redundant state — the
information is already encoded in
`activeIncludeFilterValues["span_status"]`. Keeping both in sync was
unnecessary maintenance burden. Deriving it from the existing filter
state is the single source of truth and eliminates the risk of the flag
and the actual query filters diverging.
## What
In the traces **spans-mode** list view, the query was built as:
```sql
SELECT * FROM "<stream>" [WHERE ...] ORDER BY start_time <dir>
```
`start_time` is a regular column, so the engine has to perform a full
re-sort of the result set. This change makes the query order by the
configured timestamp column (`_timestamp`) whenever the active sort
column is the default `start_time`:
```sql
SELECT * FROM "<stream>" [WHERE ...] ORDER BY _timestamp <dir>
```
## Why
- Span data is physically stored sorted by the timestamp column, and the
backend has a dedicated optimizer for timestamp-sorted segments.
- A span's `_timestamp` is monotonically equivalent to its `start_time`,
so the **visible row order is unchanged**.
- This avoids the costly full re-sort that `ORDER BY start_time` forces,
improving query latency for the trace/spans view.
## Scope / Notes
- Change is contained to `web/src/plugins/traces/Index.vue`
(spans-mode query builder in `getQueryData`).
- Only the default `start_time` sort is remapped. Any explicit
non-`start_time` sort column the user picks is passed through
unchanged.
- The `sortBy` UI state still reports `start_time`, so the sort
indicator and reset logic are unaffected.
- Not in scope: the single-trace span fetch in `TraceDetails.vue` still
uses `ORDER BY start_time` (can be addressed separately).
## Testing
- Verified the generated spans SQL now uses the timestamp column for the
default sort and produces the same visible ordering.
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
- alert history title truncate and drawer width increase
- management page content left align and padding
- horizontal scroll in table without resizing columns
- print dashboard header and back button reset print mode
- x-axis name overlapping tick labels and legend
- print dashboard header sticky and scroll fix
---------
Co-authored-by: ktx-vaidehi <vaidehi.akhani@kiara.tech>
This adds a UI and API based trigger for re triggering license check
limits, so we do not have to restart nodes
---------
Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Currently, on the roles edit page, the frontend makes role permission
api for each and every resources. So, for current 41 resources, there
are 41 concurrent api calls, each going through the openfga rbac check
middleware. That means, there are 41 concurrent redundant openfga
checks, and then 41 openfga query to get the role permissions.
This pr adds another api `org_id/roles/role_name/permissions` that
combines all the resource permissions of the given role name and return
the same eliminating the need for making api calls for each rbac
resource.
## What changed
Adds stream-change confirmation dialogs across Traces tabs. When a user
changes the stream in **Service Graph** or **Services Catalog**, the
change is no longer applied silently — instead an `ODialog` prompts the
user to confirm, since changing the stream clears the existing query in
the Traces/Spans tabs.
## Why
Previously, stream selection was only synced one-way: changing the
stream in Traces/Spans propagated to all other tabs. Changing the stream
in Service Graph or Services Catalog did not sync back because those
tabs don't show a query — so doing so could erase an active query in
Traces/Spans without user awareness. This change ensures the user is
explicitly asked before clearing their query.
## Why
The custom spinner-based loading states were inconsistent across traces
views anddid not align with the logs TenstackTable skeleton pattern
already established inthe codebase. The new skeleton provides a unified,
low-friction loading experience — shimmer pills at column-aligned
positions that mirror real cell widths — and removes the need for each
consumer to write its own loading template.
## Data Sources - Linux & Windows Agent Installer Improvements
### What changed
**LinuxConfig.vue** and **WindowsConfig.vue** have been updated to
support environment-specific installation options. Both now show a
two-card selector so users can pick their deployment target before
copying the install command.
---
### Linux
Added an **AWS EC2** option alongside Generic Linux.
- Two clickable selection cards: Generic Linux and AWS EC2
- Switching cards updates the install command automatically
- EC2 card uses the new `linux/ec2/install.sh` script which includes:
- `resourcedetection/ec2` processor to read EC2 instance metadata
- `resource/hostname` processor to set `host.name` from the EC2 Name tag
- Amber prerequisite callout shown when EC2 is selected, explaining that
an IAM role with `ec2:DescribeTags` and `ec2:DescribeInstances` is
required
---
### Windows
Added an **AWS EC2** option alongside Generic Windows.
- Same two-card selection pattern as Linux
- EC2 card uses the new `windows/ec2/install.ps1` script
- Amber IAM prerequisite callout shown when EC2 is selected
- Updated Generic Windows to use the improved `install.ps1` which:
- Bumps OTel version from 0.90.1 to 0.111.0
- Switches download source back to official GitHub releases
- Removes deprecated `memory_ballast` extension
- Fixes processor perf counter instances from hardcoded `[1, 2]` to
`"*"` for all cores
---
### Agent scripts (openobserve/agents repo)
- `linux/ec2/install.sh` - new EC2-specific Linux installer
- `windows/install.ps1` - updated with OTel 0.111.0 and config fixes
- `windows/ec2/install.ps1` - new EC2-specific Windows installer
---
### Test plan
- [ ] Open Data Sources > Recommended > Linux, verify two cards render
correctly in light and dark mode
- [ ] Select EC2 card, verify IAM callout appears and command URL
changes to `linux/ec2/install.sh`
- [ ] Open Data Sources > Recommended > Windows, verify same behaviour
- [ ] Select EC2 Windows card, verify command URL changes to
`windows/ec2/install.ps1`
- [ ] Verify Generic selection on both shows the original install script
URLs
---------
Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
## What changed
Fixed three interrelated issues in the Traces:
(1) duplicated search calls caused by redundant watchers and
programmatic triggers, and (3) `isDatetimeChanged` returning `false`
when switching from absolute to relative mode.
## Why
Separately, loading Traces in any mode triggered 2 redundant search API
calls — watchers on `searchObj.data.query` duplicated explicit trigger
calls at every query writer, mount-time filter restoration also called
`searchData()` despite `loadPageData()` already owning the initial
search, and the DateTime picker's mount replay fired a false positive
"change" that triggered an auto-run.
## Approach
- Added a `markProgrammaticDateChange()` / `userChangedValue` flag to
`DateTime.vue` so the SearchBar can distinguish user-driven date changes
from programmatic ones (redirect, metrics brush, mount replay), using
`nextTick` to reset the flag after the flush.
- Removed the `watch` on `searchObj.data.query` and the debounced
auto-run watchers on query/datetime — every writer of `data.query` in
the codebase already calls a search explicitly, so a watcher doubled
every trigger.
- Removed the `searchData()` call inside the `restoreFilters` block on
mount; the single mount search is owned by `loadPageData()`.
- In `SearchBar.vue`, gated the live-mode auto-run on `userChangedValue
=== true` and `datetimeChanged`, and removed the `searchObj.data.query =
newValue` writes in `applyFilters`/`removeFilter` (filter operations
already trigger search via emit).
- Fixed `isDatetimeChanged` to return `true` when the previous type was
`absolute` and the value is now `relative`, so switching mode always
registers as a change.
## Summary
Fixes duplicate error notifications when NL-to-SQL generation fails due
to 403. The `throw` in `generateAndUpdateQuery` was caught by the catch
block which showed a second generic "Failed to generate SQL query"
notification on top of the correct Unauthorized message. Now returns
early for auth errors, matching the pattern used in alerts.
## Before
User sees two notifications:
1. "Unauthorized Access: You are not authorized..."
2. "Failed to generate SQL query. Please try again."
## After
User sees only:
1. "Unauthorized Access: You are not authorized..."
## Test plan
- [ ] User without AI access sees only one error notification (the
unauthorized message)
- [ ] Non-auth errors still show the generic "Failed to generate SQL
query" message
- [ ] Auth errors don't trigger SearchBar error handling via re-throw
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## 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.
Adds support to show tentative cost in usage page in cloud
---------
Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: Yashodhan Joshi <yjdoc2@gmail.com>
## Summary
When the AI chat endpoint returns HTTP 403, `generateSQL` returned
`null` without setting `streamingResponse`, so `CodeQueryEditor` fell
through to the generic "Failed to generate SQL query" message. Now sets
`UNAUTHORIZED_MESSAGE` so the UI displays the proper error.
## Why
The earlier auth fix (#12558) only handled SSE error events inside the
stream. But when the middleware blocks the request with HTTP 403,
`!response.ok` triggers before the SSE reader starts — leaving
`streamingResponse.value` empty. `isAuthError('')` returns false, so the
code falls to the generic message.
## Test plan
- [ ] User without AI access sees "Unauthorized Access" when using
NL-to-SQL generation
- [ ] Non-auth HTTP errors continue to show generic "Failed to generate
SQL query"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
Fixes - https://github.com/openobserve/o2-enterprise/issues/1892
- Added explicit permission check in `chat` and `chat_stream` handlers
that returns `MetaHttpResponse::forbidden("Unauthorized Access")` (HTTP
403) when the user lacks AI access, ensuring consistent 403 behavior
regardless of OpenFGA state
- Updated all 4 SSE error event handlers in `O2AIChat.vue` to recognize
authorization-related error messages and display the standard
"Unauthorized Access" message
## Why
When a user without AI permissions used the query editor, the auth
middleware could pass the request through (e.g., when OpenFGA was
disabled), and the agent service error would arrive as an SSE event
within a 200 response — bypassing the standard 403 flow. This fix
ensures the backend returns proper HTTP 403 and the frontend displays
the standard unauthorized message consistently.
## Test plan
- [ ] Verify non-root user without AI permission gets HTTP 403 from
`/api/{org}/ai/chat_stream`
- [ ] Verify non-root user without AI permission gets HTTP 403 from
`/api/{org}/ai/chat`
- [ ] Verify root users are unaffected (bypass permission check)
- [ ] Verify the frontend displays "Unauthorized Access: You are not
authorized to perform this operation..." for auth-related SSE errors
- [ ] Verify non-auth SSE errors continue to display normally
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## 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