Design at: docs/online-evaluation-scheduler-queue-review.zh-CN.md
OSS-side half of the phase-2 eval scheduler rework (paired o2-enterprise
PR linked in comments). The enterprise PR depends on the metrics and the
executor contract below, so **this PR must merge first**.
## Scheduler metrics
- `eval_scheduler_pending_targets` (gauge, org/stream) — in-flight
pending targets tracked across scheduler passes
- `eval_scheduler_pending_memory_bytes` (gauge, state=used|limit) —
accounted pending memory vs the configured budget
- `eval_scheduler_forced_ready_total` (counter, org/stream) — targets
force-evaluated early by budget enforcement
- `eval_scheduler_watermark_lag_seconds` (gauge, org/stream) — scan
cursor vs committed (persisted) watermark
Registration only; all emission sites live in the enterprise scheduler.
## Detection-search executor: window-split support
The scheduler's search executor no longer errors on an oversized scan
window. It reports `over_limit` against the shared 100k-row cap
(`EVAL_DETECTION_MAX_ROWS`) so the scheduler can split the window in
half and re-query, and fetches a capped result set only when the
scheduler explicitly allows truncation at the minimum window width. This
removes the previous failure mode where a high-throughput window could
never be fetched and retried forever.
## Completion-window defaults, floor, and hard caps
Eval jobs that don't set their own trace/session completion windows now
take deployment-wide defaults, declared in the enterprise
`LlmEvaluationConfig` (`O2_EVAL_TRACE_IDLE_TIMEOUT_SECS`=30,
`O2_EVAL_TRACE_MAX_AGE_SECS`=1800,
`O2_EVAL_SESSION_IDLE_TIMEOUT_SECS`=1800,
`O2_EVAL_SESSION_MAX_AGE_SECS`=14400 — the design-spec baselines) and
injected into infra at startup via `init_completion_window_defaults`
(same registration pattern as the search executor). Sessions span user
think-time between traces, hence the much wider session idle window.
- **Floor**: the old 45s idle-window minimum is dropped to 1s. Readiness
fires only once the observed ingest-time silence reaches the window, so
sub-poll-interval windows are correct — their firing is merely quantized
to the next scan pass.
- **Hard caps** (`validate_trace_completion_window` /
`validate_session_completion_window`, applied identically to
job-supplied values and env defaults): trace idle ≤ 30m / max age ≤ 2h,
session idle ≤ 4h / max age ≤ 24h. Max age bounds pending-target memory
residency, committed-watermark lag, and restart rescan, so it is a guard
rail, not an operator preference. The enterprise config parser calls the
same validators and **fails startup** on out-of-range env values (0
still means built-in default).
- **Frontend** mirrors all of it: per-scope defaults and limits in
`completionWindow.ts`, zod schema validation, input `max` attributes,
and validation messages across all 15 locales.
## Legacy eval-buffer cleanup (OSS side)
Removes the pipeline-update eviction call into the legacy
trace-buffering LLM evaluation node (`LlmEvaluationNode::remove_buffer`)
— a no-op on an always-empty registry since span evaluation moved to the
eval-task queue. The paired enterprise PR deletes the legacy module
itself.
## Module split
`infra::table::online_eval_jobs` splits into submodules —
`completion_window.rs` (defaults, guard rails, trace/session configs)
and `span_selector.rs` — with re-exports keeping every external path
unchanged.
Makes **environment** and **version** first-class identity dimensions
for GenAI agents, and adds an A/B **version-compare** experience to LLM
Insights.
### What's in it
- **Schema / identity (OSS, ungated):** migration adds `env` +
`agent_version` to `gen_ai_agents`; entity/table ops and agent-mapping
config carry them through; env/version surfaced across all AI screens
via a shared Env→Agent→Version cascade.
- **Version compare (LLM Insights):** pick two versions of an agent,
align their windows (**Since each rollout** / **Same wall-clock** /
**Manual**), and read latency / cost / error-rate deltas with confidence
intervals plus a tri-state failure-class diff (introduced / fixed /
shared).
- **Handlers + service wiring:** `#[cfg(feature = "enterprise")]` call
sites for the compare/agent-signals endpoints (enterprise impl + OSS 403
stub); the sketch-merge compute lives in the companion enterprise PR.
~120 files; primarily `web/src` (AI Observability + traces) and
`src/infra`/`src/core`/`src/config` for the schema and thin service
layer.
Applies the **Calm Signal** colour language and summary stat strips
across the monitoring + AI-evaluation pages.
- Colourful summary stat strips (`OStatStrip`) with selectable filter
tiles + left row rails / exception washes on **Alerts, Incidents, Eval
Jobs, Scorers, Score Configs**.
- Tile tones match their `OTag` chip colours; critical-first (left)
ordering; re-click a tile to clear the filter.
- AI Observability: consistent section headers, detail drawer, and
per-session signals.
- Migrate `ScorerTypeDialog` to the standard `ODialog`; token-compliance
+ vertical separators on the eval form pages.
- Table perf: lazy tooltips, delegated row shortcuts, virtualization.
Fixes the Agent Graph end-to-end — UI (openobserve/web) + service-graph
backend (openobserve/core). Root causes were found and validated against
live trace data.
---
## 1. UI: wrong graph until refresh + no independent graph-type selector
The Agent Graph page embeds Traces' `ServiceGraph`, which read its
viz/layout type from the shared `searchObj.meta` singleton and
auto-loads on mount.
- **Wrong graph on return (from Agent Behavior):** the effective stream
fell back to the literal `default` trace stream before `loadAgents()`
resolved, so ServiceGraph rendered that whole stream's service topology
instead of the agent graph. Fixed: no `default` fallback in agent mode;
render is gated behind `graphReady` (a resolved agent stream), with a
spinner / "no agents" empty state otherwise; stale agent/stream
selections reconciled on reload.
- **No graph-type selector / inherited the Traces tab's type:** added
`vizType`/`layoutType` prop overrides on `ServiceGraph` (computeds
prefer props, else the shared store — Traces behavior unchanged), and
gave the Agent Graph page its own Tree/Graph + layout selector with its
own state and `agentGraph_*` localStorage keys.
- **Stream picker** now lists only the distinct `source_stream`s of
discovered agents (not agentless streams), annotated with per-stream
agent counts, with an option tooltip and wider control.
New `AgentGraphPage.spec.ts` (5 tests): gating, empty state, viz/layout
independence, stream-picker scoping. `vue-tsc` app + vitest typecheck
clean.
## 2. Backend: agent→model/tool edges mis-attributed to the service
Model/tool spans (`chat`, `execute_tool`) don't carry
`gen_ai.agent.name` — it lives on an ancestor `invoke_agent` span
(confirmed as the norm across the OTel GenAI spec, Google ADK, OpenAI
Agents SDK, OpenInference, CrewAI, LangGraph). The edge builder climbs
≤4 parent hops to find it, else falls back to `service_name`. When an
intermediate span is missing (the spec permits omitting `invoke_agent`;
inconsistent sampling / async context loss produce orphan LLM spans),
the climb fails and the span mis-attributes to the service — a spurious
`service → model` / `service → tool` edge.
Fix: add a per-trace agent CTE (`MAX(gen_ai_agent_name) GROUP BY
trace_id`) as a fallback level in the COALESCE, between the ancestor
climb and the `service_name` fallback, for both edge queries. This
matches the industry-recommended fallback (group by trace when the chain
breaks).
### Validation (live introspect data, 2 streams, 7-day window)
| stream | before | after |
|---|---|---|
| `sre_agent_traces_production` | `service → model` (47+3 reqs) |
eliminated → o2_ai_agent (247) / sre_rca_agent (29) |
| `sre_agent_traces_production_us2` | `service → model` (20 reqs) |
eliminated → o2_ai_agent (279) |
- No cross-agent contamination in the multi-agent stream (traces are
single-agent). No tool-edge regression.
- Non-agent traces: CTE returns nothing → NULL join → falls to
`service_name` exactly as before (no behavior change).
- Perf: single-column `GROUP BY trace_id` aggregate, ~+25% wallclock on
the batch edge query; runs in the hourly job, not a hot path.
Unit tests cover the COALESCE position and CTE builder.
## Not included / follow-up
- **env/version in the agent dropdown** requires backend extractor + DB
migration + API changes. Tracked separately.
## Note
Full enterprise `cargo build` isn't runnable in the dev environment (the
`o2_enterprise` crate is a resolution stub); the SQL-builder logic is
verified via standalone rustc and the runtime behavior via the live
dry-run above. CI runs the real enterprise build.
Companion to the o2-enterprise change. On a live instance the Agent
Behavior/Graph views were empty because the rollup never re-processed
the agent trace streams, and the stream pickers offered non-LLM streams.
service_graph/processor.rs — discovery gap: the rollup discovered
streams from a usage-windowed query, falling back to the schema cache
only when usage was ENTIRELY empty. So any stream that dropped out of
the current window's usage (producer paused, bursty ingest) was silently
skipped forever on a busy instance — exactly how the agent streams went
dark. Replace the all-or-nothing fallback with a union: usage-active
streams ∪ every schema-cache trace stream (deduped). Idle windows are
cheap no-ops, so this doesn't widen the worst case.
agent_signals/processor.rs — always-on + stream-level LLM gate: drop the
removed O2_AGENT_SIGNALS_ENABLED check, and add an early return that
skips streams whose schema has no gen_ai_operation_name (mirrors the
service-graph has_gen_ai gate) so non-LLM streams cost nothing. Thread
has_agent_id into the SQL builders for the schema-gated agent-id
predicate.
AgentGraphPage/AgentBehaviorPage.vue — filter the stream picker to LLM
streams (settings.is_llm_stream !== false), matching LLM Insights /
Sessions. A plain service trace stream has no agents or signals to show
here.
- **add session and travel level evals fix quality page to show scoped
scores improve quality page to allow drill down of scores improve the
quality page UI to make it more indicative of health of agents.**
- **Fix Quality dashboard runs, show agent ids**
- **nats at least once delivery semantics + quality runs page changes**
- **feat(evaluations): improve online evaluation workflows**
---------
Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
## Summary
- add shared lifetime AI credit limits and persisted per-organization
usage tracking
- expose used and total AI credits in organization management with an
editable limit dialog
- keep router quota caches synchronized and delegate billing and
contract exhaustion policy to enterprise
- clean up the redundant quota table only in non-cloud builds while
preserving cloud credit data
## Companion PR
- https://github.com/openobserve/o2-enterprise/pull/2208
## Testing
- cargo check --features cloud
- cargo test -p openobserve-core --features cloud trial_quota::tests
--lib
- cargo test -p infra --features cloud
m20260717_000001_drop_trial_quota_usage_for_non_cloud::tests --lib
- cargo test -p infra
m20260717_000001_drop_trial_quota_usage_for_non_cloud::tests --lib
- cargo fmt checks for changed Rust packages
- npm run type-check
- 200 focused frontend unit tests covering organization management,
billing usage, organization services, and required numeric input
- live organization-management verification with per-org 0 used / 1,000
total values
chore: update package.json scripts for improved type-checking
fix: adjust frontmatter regex to handle BOM characters
refactor: streamline error handling in dashboard data conversion
style: clean up comments and formatting in various files
## What
Adds **Agent Behavior signals** — a PB-safe rollup that surfaces two
behavioural questions the platform couldn't answer before: *is an agent
stuck in a loop?* and *why is it failing?* Plus a batch of Agent Graph /
AI Observability UX and correctness fixes found while building it.
Companion changes land in **o2-enterprise**
(`feat/agent-signals-enterprise-split`): the SQL builders, mappers,
config-driven failure taxonomy, the service-graph agent-classification
fix, and the RBAC route entry.
## Backend (agent-signals)
- Bounded-key rollup co-located in the service-graph job
(alert-manager-only, reuses its watermark + self-ingest). Groups only on
agent/tool/class — never trace_id — so it stays PB-safe.
- Config-driven **failure taxonomy** (rules as data, evolvable without
code) + config-driven error-detail columns; ancestor-agent resolution so
error spans attribute to the owning agent.
- Read API `GET /{org}/traces/agent_signals` (dual `#[cfg]`, reads the
derived `_agent_signals` stream) + RBAC route entry (enterprise
`route_permissions`) mapping it to `traces` read.
- OSS/enterprise split respected: pure SQL/mapping in enterprise, thin
gated I/O in OSS.
- Fix: `traces/latest` only narrows to a UUIDv7 trace_id's embedded time
when that time is inside the caller's window (fixes "trace not found"
for time-shifted/re-ingested traces).
## Frontend (AI Observability)
- New **Agent Behavior** page under Monitor: looping-agents +
failure-taxonomy tables, each row opening an actionable detail drawer
(real grouped error messages / worst-repeat traces), click-through to
Trace Details in a new tab.
- Agent-node **Behavior tab** on the Agent Graph node drawer (reuses the
same signals).
- Nav rename: LLM Insights → **Insights**, LLM Sessions → **Sessions**.
- **Agent** is the default scope across the AI pages, with the
Agent|Stream toggle placed consistently (left scope bar); explicit
URL/localStorage choices still win.
- Removed the duplicate in-table refresh on Sessions.
## Agent Graph fixes
- **Agent classification**: agents that also call tools now correctly
classify as `service_type: "agent"` (they glow), fixing a latent
precedence bug where the tool/model client-role overrode the agent role
and `is_real_service` forced agents to plain services. Rust
`classify_entity` brought in line with the (already-correct) TS twin.
- **Drag-to-pan restored**: the shared ChartRenderer armed
`dataZoomSelect` cursor unconditionally, hijacking drag away from roam
pan. Disabled for this graph (no dataZoom).
- **Nodes scale on zoom** (`nodeScaleRatio: 1`) so zooming enlarges
nodes/labels, not just spacing.
## Testing
- Enterprise unit tests: agent-signals SQL/mappers/config,
classification precedence, RBAC route resolution — all pass.
- FE: type-check + lint clean.
- Verified end-to-end on real re-ingested introspection data: taxonomy
unclassified rate ~100% → ~1–3%, agents resolved, both agents
classify/glow, trace-open works.
## Notes
- `Cargo.toml`/`Cargo.lock` and unrelated Slack-bot files were
intentionally excluded from the commits (local build-config drift).
---------
Co-authored-by: ktx-vaidehi <vaidehi.akhani@kiara.tech>
Co-authored-by: ktx-vaidehi <134508096+ktx-vaidehi@users.noreply.github.com>
# Design System Unification — one visual language, enforced end-to-end
Establishes **one source of truth for every visual decision**, wires the
whole app to it, and **locks it in with CI** so it can't drift back.
### Foundations
- **Design-token system ("one knob per decision").** Every colour, text
size, spacing, corner radius, and shadow is a named token defined in
exactly one place — change the token, every screen updates. Collapsed
hundreds of near-duplicate definitions and removed "fake" duplicates
that pretended to be different but weren't.
- **Shared component library (O2).** Buttons, tables, dialogs, drawers,
form fields, badges, etc. already know the correct colours, spacing, and
dark-mode behaviour; new screens compose them instead of hand-styling.
Added new primitives on this branch (`OContent`, `KpiCard`) and
standardized existing ones.
- **One page structure everywhere** (`PageLayout` / `AppPageHeader` /
`AppPage` / `OContent`) — titles, breadcrumbs, spacing, and content
edges line up identically across every screen.
- **One table implementation** — all tabular data uses the same table
(sorting, density, sticky headers, empty states).
- **Styling consolidated onto Tailwind; old systems removed** —
hand-written CSS driven to the practical minimum, the legacy **Quasar**
framework fully removed, surviving stylesheets required to justify
themselves.
- **Two-tier corner radius** — a tight **4px** for controls and a soft
**12px** for surfaces (dialogs, cards, the app shell), plus a
full-circle option — replacing five radius names that all secretly meant
the same thing.
### Detailed improvements across screens
**Page structure & alignment** — unified page shell rolled across ~40+
screens (IAM, Settings, Alerts, Dashboards, Functions, Pipelines, RUM,
Metrics, Synthetics, Billing, editors, lists); one header height; one
page-edge grid driving headers, tables, rails, and tabs; unified
side-rail widths; inset rail selection/hover pills; every tab strip on
the grid line; tightened title/subtitle spacing.
**Tables (cross-screen)** — action columns consistently centered (incl.
Organizations); unified row-number column with no "#" truncation;
non-standard tables restyled to match; loading skeletons made
geometrically identical to the loaded table; symmetric edge inset; IAM
first-column grid alignment fixed.
**Traces** — flame graph + span-detail correlation panel fixes;
correlated logs/metrics placeholder fit; sticky headers; removed a
double scrollbar + a 1px sliver; aligned table fonts/badges; polished
the service detail drawer; stream-selector + correlation alignment;
aligned loading spinners; floating overlay arrows for the
disabled-services strip.
**Logs** — field-list controls aligned (focus ring no longer clipped);
detail-drawer spacing + metrics-tab overflow fixed; Run Query toolbar
tidied; listing sizing + stray border fixed.
**Metrics** — search added to the "Type" facet rail and aligned with the
other rails; proper empty states for the explorer and facet rail.
**Dashboards** — removed inconsistent card shadows; tightened
borders/resizers/field-list spacing; aligned View Dashboard chrome to
the grid; chart colours via the token helper.
**Home** — redesigned the Usage tab; added reusable KPI stat cards so
summary strips stop drifting.
**Dark mode** — new theme-switch animation; fixed a 1px content shift on
toggle and a white flash on load; fixed AI-chat text and assorted
light/dark mismatches; completed the token-driven dark migration.
**Empty states, controls & small polish** — restored 3 broken
empty-state animations; adopted the standard empty state; added the
sliding indicator to the toggle control; fixed the Quality-page inset +
drawer badge; refreshed Search History / Schedulers; fixed the
alert-history drawer scrollbar + timeline hover; removed a stray
menu-bar border.
### Dead code & cruft removal
- **Deleted the entire legacy `utilities.css`** global stylesheet (well
over a thousand lines) — evacuated in waves, roughly half of it dead
once traced.
- **Removed Quasar entirely**, including dead `.q-*` styles and ~25
phantom `--q-*` variables that were silently breaking bits of the UI.
- Stripped hundreds of **dead CSS classes and tokens that compiled to
nothing** — e.g. 46 uses of a colour class with no backing token, a
no-op shadow class on 51 elements, dead layout/utility classes, a
leftover `card-container` block, a dead table-actions token, and a
mis-registered gradient that rendered nothing.
- Cut **unused keyframe animations (19 → 3)** and removed **unused
components** + a stray build artifact.
- Net effect: a much smaller, leaner styling surface — less to maintain,
fewer dead ends to copy.
## Safety & verification
Large but low-risk: this is overwhelmingly a **styling and structure**
change, not product behaviour or data. Guarded by the
design-token/consistency/type checks above plus the existing test suite,
and reviewed screen-by-screen.
---------
Co-authored-by: Kirtan Thakkar <kirtan@kiara.tech>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: ktx-mihir <mihir.patel@kiara.tech>
## What
Adds an **Agent Graph** to AI Observability that renders AI agents,
tools, and models as first-class nodes in the service graph — unified
with the real downstream services an agent talks to. It answers "what
does my agent actually interact with?" (tools, models, services,
datastores) instead of showing GenAI spans in isolation.
## Why
LLM Insights shows plenty of per-call data but no picture of the flow —
where a request starts, where the agent sits, and everything it fans out
to. This surfaces the full agent topology, works across every framework
OpenObserve documents, and correctly attributes tools/models to the
owning agent even when the instrumentation nests them several spans
deep.
## Backend (`src/core`)
- **Agent/tool/model edge families in the service-graph processor**
(`traces/service_graph/processor.rs`): derives `service → agent`, `agent
→ model`, `agent → tool` edges from the canonical `gen_ai_*` columns,
keyed on column presence (open operation-name vocabulary), schema-gated
so streams missing a column don't error.
- **Multi-level agent inheritance.** The owning agent name usually lives
on an *ancestor* span (real Google ADK nests `generate_content(agent) →
chat → execute_tool`), not on the tool/LLM span. The `from` climbs the
parent chain up to `AGENT_INHERIT_DEPTH` (4) levels —
`COALESCE(child.agent, p1…pN, service_name)` + chained ancestor `LEFT
JOIN`s — taking the nearest ancestor with an agent name. Extracted
`build_agent_or_service` / `build_ancestor_joins` as pure, unit-tested
helpers. (Recursive CTE was tried first but panics in the search engine;
a bounded chained join is supported and shallow-tree-cheap.)
- **Extractor coverage** for the framework conventions OpenObserve
documents (gen_ai semconv, OpenInference, traceloop, CrewAI, Google ADK,
LangChain, Langfuse): `is_llm_trace` gate now admits
OpenInference/framework agent+tool spans; `extract_tool_name` reads
`tool.name` / `langchain.tool.name` / `crewai.task.tools` / Langfuse
metadata; new attribute constants. All normalize into the canonical
`gen_ai.*` columns at ingest, so the query layer reads one column set
regardless of vendor.
## Frontend (`web/src`)
- **Standalone Agent Graph page** under AI Observability
(`AgentGraphPage.vue`) with Stream/Agent selectors and a DateTime
picker, matching the LLM Insights UX; route + rail item + i18n.
- **Graph rendering** (`convertTraceData.ts`, `ServiceGraph.vue`):
agent/tool/model node kinds, vendor brand logos on model nodes (reusing
the AI-integrations catalog logos), an animated "radar-ping" halo baked
into the agent symbol SVG so it stays centered and pans/zooms with the
node, and a layered-layout depth fix so `service < agent < model/tool`
renders correctly. Agent highlighting is gated to the Agent Graph page
(the Service Graph tab is unchanged).
- **Side-panel caller consistency** (`ServiceGraphNodeSidePanel.vue`):
the Operations table now resolves a tool/model node's caller with the
*same* ancestor-agent climb the graph edge uses, so the panel and graph
agree (previously the panel showed the host app as the caller).
Refactored the identity-field builder to emit aliased columns directly
(no fragile regex post-processing).
- **Design tokens** (`theme.ts`): added `cssToken(name, fallback)` to
resolve `--color-*` tokens at runtime for chart/SVG contexts (where
`var(--x)` can't be used), and routed the agent-accent + exact-match
health colors through it instead of hardcoded hex.
## Consistency
Service classification is mirrored TS ⇄ Rust; the shared
`classification_cases.json` vector (both copies kept identical) drives
unit tests in both languages.
## Testing
- Rust: multi-level inheritance + edge-attribution unit tests; `cargo
build` clean.
- Frontend: new specs for the graph conversion, layout,
model-vendor-logo, side-panel caller climb, and `cssToken`; full traces
suite green.
- Verified end-to-end on real production traces (SRE agent) and on
synthetic fixtures for CrewAI / OpenAI-Agents / Google ADK /
genai-semconv / LangChain — every framework attributes agent →
model/tool correctly.
## Notes
- Topology is read from the pre-aggregated `_o2_service_graph` stream
(the hourly incremental job), so it scales to large trace volumes — no
per-load raw-trace scan.
- The enterprise `classify_entity` / `build_topology` changes live in
the o2-enterprise repo and are required for the enterprise build.
## Summary
A pass of UI-consistency and empty-state fixes across the AI
Observability, Logs, and Settings surfaces. Brings several one-off /
hand-rolled UI patterns in line with the app's shared components
(`OEmptyState`, `OTable` selection, badge groups).
## Changes
| Area | Change | Files |
|---|---|---|
| LLM Model Pricing | Replaced the small faded `$` icon empty state with
the standard `OEmptyState` illustration; added `no-model-pricing` preset
and made it filter-aware (no-results + Clear filters vs. first-run card)
| `ModelPricingList.vue`, `presets.ts`, `en.json`, `hi.json` |
| Scorers list | Moved the "no LLM providers" empty state into the
table's `#empty` slot so the search bar + column header stay visible
(was hiding the whole table) | `ScorerList.vue` |
| Correlation → Traces | "No Traces Found" now uses `OEmptyState` with
the `trace` illustration instead of a small icon + text (both embedded
and drawer paths) | `TelemetryCorrelationDashboard.vue` |
| Logs "No events found" | Added `h-full` so the empty state centers
vertically in the results panel instead of sitting near the top |
`Index.vue` |
| Eval Jobs | Added multi-select checkboxes + bulk **Delete** action
with confirm dialog; selection pruned after reload | `EvalJobList.vue`,
`OnlineEvals.vue`, `en.json`, `hi.json` |
| Score Config → "Not declared" chip | Cramped custom `xs` badge →
default `sm`/`pill` sizing, matching sibling `Categorical` / `Active`
chips | `badgeGroups.ts` |
| Search History → More Details | Added spacing between the tab strip
and the JSON editor | `SearchHistory.vue` |
---------
Co-authored-by: ktx-vaidehi <134508096+ktx-vaidehi@users.noreply.github.com>
## What
Adds an **"Enable usage reporting" call-to-action** to the Cloud Billing
→ Usage tab for organizations that have self-usage reporting turned off,
a **"waiting for usage data" illustrated state** for orgs that have it
on but haven't reported any usage yet, and flips the per-org default for
the setting to **OFF** so the CTA is the entry point.
Previously, when `usage_stream_enabled` was off the Usage tab showed
only the billing-cycle cards and nothing where the daily chart would be.
And when it was on but the org's `usage` stream didn't exist yet, the
panel showed a raw `Search stream not found: usage` error. Now:
- **Reporting OFF** → an illustrated empty state (`OEmptyState`,
`wave-bars`) invites the user to enable reporting. Clicking **Enable**
opens a `ConfirmDialog` explaining the per-org, reversible effect before
the merge-and-POST enable flow runs.
- **Reporting ON, no data yet** → the raw "stream not found" error is
suppressed (on this panel only) and replaced with an illustrated
**"Waiting for usage data"** state. When usage lands, the search
succeeds, the error clears, and the daily chart shows through
automatically.
- **Reporting ON, has data** → unchanged: the daily line chart
(Ingestion + Search + Pipelines) renders.
## Behavior change (please review)
`default_usage_stream_enabled()` now returns **`false` in every build**
(previously cloud builds defaulted to ON when
`ZO_USAGE_REPORT_TO_OWN_ORG` was set). `ZO_USAGE_REPORT_TO_OWN_ORG`
remains the deploy-wide master switch but no longer flips the per-org
default. This is the intentional pairing with the CTA — an "enable"
prompt only makes sense when reporting is off by default. Explicit
stored values (opt-in or opt-out) still win in every build.
## How the waiting state is scoped
The "stream not found" suppression is set via `error_config` **only on
the usage panel's schema** (`usageDailyPanelSchema.ts`) —
`custom_error_handeling: true` with no `custom_error_message` silences
PanelSchemaRenderer's own error blocks. `usage.vue` catches the panel's
`@error`, detects the stream-not-found case specifically (unrelated
query errors still surface), and overlays the graphic. No other chart is
affected.
## Testing
- `web`: 417/417 billing specs pass, incl. new coverage for the enable
CTA, merged-settings POST, the schema silencing the renderer, and the
waiting overlay showing only for stream-not-found (not other errors).
- `cargo check -p openobserve` (non-release): clean.
## Note
These commits were cherry-picked onto a fresh branch from `main` — the
original branch (`chore/usage-ui-cloud-changes`) had already merged its
base work via #13112 and carried divergent, pre-squash history that
would have produced a conflicting diff.
## What
Adds a **daily usage view** to Cloud Billing → Usage for orgs with usage
reporting enabled, layered on top of the existing billing-cycle cards.
Cloud-only.
### Frontend (cloud billing components)
- **Merged into the existing Usage tab** (no separate tab): the billable
usage cards are always shown; when self-usage reporting is on, a
dashboards **date-range picker** (in the toolbar next to the GB/MB
toggle) drives **both** the cards and a daily chart.
- **Daily line chart** — a single query via `PanelSchemaRenderer` over
the org's own `usage` stream, broken down by event into **Ingestion /
Search / Pipeline / Remote Pipeline** lines (connect-nulls on).
- **Six billable usage tiles** on one row with **automatic unit
scaling** (GB→TB→PB / MB→GB→…) so large numbers stay readable; AI
Credits shown as a count.
- Cards re-fetch over the calendar range (derived `<N>days`, hardened
against bad values).
### Backend (all cloud-gated)
- `usage_stream_enabled` **defaults to `ZO_USAGE_REPORT_TO_OWN_ORG`** in
cloud builds, so orgs report to their own `usage` stream by default; a
per-org opt-out persists an explicit `false`. OSS / self-hosted default
stays `false`.
- **Reserved self-reporting streams** (`usage`, `stats`, `triggers`,
`errors`, `data_retention_usage`) are blocked from user **create /
ingest / delete** — cloud-only; the internal self-reporting writer
(`IngestionRequest::Usage`) is exempt.
- `get_org_usage`: a **missing `usage` / `data_retention_usage` stream
is tolerated** (treated as zero) instead of failing the whole request
with a 400.
## Notes
- No enterprise-repo or DB-migration changes; backend logic stays in OSS
behind `#[cfg(feature = "cloud")]`, per the OSS/Enterprise layer map.
- `Cargo.toml` / `Cargo.lock` are intentionally **not** included (local
`downloadO2.sh` dev-setup).
## Testing
- `cargo check` (OSS) and `cargo check --features cloud` — pass; `cargo
fmt` clean.
- Frontend: **411 billing unit tests** pass; `vue-tsc` typecheck clean;
production build succeeds.
1. The name is missing on score config list table
datetime error when user is clicking on arrow in quality page / any one
of the score config overview
replace hardcoded badges to obadge in all list page
when user goes to llm sessions it is taking user to traces submenu
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>