## Summary
- Add optional `is_llm_stream` field to `UpdateStreamSettings` so the
stream settings update API can toggle the flag.
- Apply the value in `update_stream_settings` alongside the other
boolean toggles.
## Why
`StreamSettings` already exposes `is_llm_stream`, but the update API had
no way to change it. This brings the update payload in line with the
underlying setting so callers can flip the flag without going through a
different code path.
## Test plan
- [x] `cargo check` passes (verified locally)
- [x] PATCH stream settings with `{"is_llm_stream": true}` updates the
stored value
- [x] Omitting `is_llm_stream` leaves the existing value unchanged
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
**Problem:**
Backend sent cumulative `took` per partition (monotonically increasing:
69, 130, 192...ms). Frontend summed all values → O(n²) inflation (e.g.
23s displayed vs 1.4s actual).
**Fix:**
- Backend: timer now created independently per partition → each
partition reports only its own processing time
**Result:** `took = search + histogram` sums correctly. Verified against
SSE data for both no-cache and cache flows
## Summary
Design at: #11532
Closes
[#11532](https://github.com/openobserve/openobserve/issues/11532).
Adds a new reset component so operators can re-run compaction over a
stream's
historical file_list:
```
./openobserve reset -c file-list-jobs [-t <microseconds>]
```
The command performs three things:
1. **Safety check** — calls `infra::cluster::list_nodes()` and aborts
with an
error if any dedicated compactor node is online (the operator must stop
them first). If a `single_node` (Role::All) node is online, prints a
warning that it must be restarted after the reset so its in-memory
compact state is cleared.
2. **Reset compact offsets** — `db::compact::files::reset_offset(time)`
lists
every `/compact/files/` key in meta and rewrites its value to `time`
(defaulting to `0`), then clears the in-process offset cache.
3. **Re-queue jobs** — calls `infra_file_list::set_job_pending(&[])`,
which
now treats an empty ids slice as "reset all rows", flipping every
`file_list_jobs` row back to `Pending` and clearing `node`,
`started_at`, `updated_at`.
`set_job_pending` previously returned `Result<()>`; it now returns
`Result<u64>` so callers (and the new CLI output) can report rows
affected.
The existing call site in `service/compact/mod.rs` is unaffected because
it
ignores the Ok value.
## Test plan
- [x] `./openobserve reset -c file-list-jobs` against a stack with no
compactor running — verify offsets are 0 and all jobs are Pending
- [x] `./openobserve reset -c file-list-jobs -t 1700000000000000` —
verify
offsets are written as the supplied microsecond timestamp
- [x] Run while a compactor is online — verify the command errors with
the
offending node name
- [x] Run on a single_node deployment — verify the warning is shown and
operation still completes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Design at: #11518
## Summary
- Add `llm_input` and `llm_output` to the default SQL full text search
field list so LLM-related streams get FTS out of the box without needing
to set `feature_fulltext_extra_fields`.
## Test plan
- [x] Verify a stream with `llm_input` / `llm_output` columns is
searchable via `match_all` without extra config.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
- Replace `SELECT *` Q2 with grouped aggregations so per-trace
enrichment is bounded by N rows instead of total span count.
- Q2a aggregates per `trace_id`: span count, error count, min/max times,
max duration, root span labels (with first-by-timestamp fallback), and
`approx_distinct(service_name)` to gate Q2b.
- Q2b runs only for multi-service traces, returning per-`(trace_id,
service_name)` count and max duration.
## Root cause
When a user filters Traces by Duration, Q2 ran `SELECT * FROM stream
WHERE trace_id IN (...)` and aggregated spans in Rust. For traces with
tens of thousands of spans, the search-service row cap was hit before
every `trace_id` got at least one span back. The un-enriched entries
were still sent to the FE with `spans=[0,0]`, `duration=0`,
`first_event=null` — the blank rows in the screenshot on the issue.
The new Q2a returns one row per `trace_id` (≤ N rows total), so it
cannot trip the row cap. Single-service traces are fully populated from
Q2a alone; only multi-service traces require Q2b. Response shape
(`TraceResponseItem`) is unchanged — `first_event` is now built as a
synthetic `{service_name, operation_name}` object so the FE in
`web/src/composables/useTraces.ts` keeps working unchanged.
Applied to both `get_latest_traces` and `process_latest_traces_stream`.
Closes#11505
## Test plan
- [ ] Open Traces, pick a stream with traces that have many spans (≥10K
spans/trace).
- [ ] Filter by Duration `<= Max value`. Confirm no blank rows; every
row has a service icon, service name, non-zero duration, and a span
count.
- [ ] Single-service stream: confirm the services list under each trace
is correct.
- [ ] Multi-service trace (e.g., a trace that crosses several services):
confirm the per-service breakdown still appears (Q2b path).
- [ ] Sort by duration ASC and DESC.
- [ ] Sort by start_time ASC and DESC.
- [ ] LLM stream: confirm LLM token / cost columns still populate.
- [ ] Pagination: page 1, page 2, page N — every page has fully
populated rows.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Hengfei Yang <undefined@users.noreply.github.com>
Build frontend and Rust binary in parallel using /tmp/dist trick
Remove VITE_COVERAGE/COVERAGE env vars and coverage instrumentation
Remove generate_coverage_report job and all nyc upload/report steps
Rename artifact debug-binary → release-ci-binary, add frontend-dist
artifact
Update playwright_summary needs to drop generate_coverage_report
---------
Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
Currently alerts/reports/scheduled pipelines get triggered immediately
when updated or enabled or created. Instead, it should follow the cron
expression (if given) instead of triggering immediately.
Currently, through api, you can keep adding same schema field to UDS, or
full text search settings etc. because the backend simply extends
existing settings with the given payload, instead of checking if the
field already exists in the same config (e.g. uds). This pr fixes this.
## Summary
- Adds `github.event.pull_request.base.ref == 'main'` guard to the "Add
milestone to PR" step
- PRs opened against non-main branches (feature, release, etc.) will no
longer receive auto-assigned milestones
- Issue milestone logic is unchanged (issues don't have a target branch)
## Test plan
- [ ] PR opened against `main` → milestone is assigned (existing
behavior preserved)
- [ ] PR opened against a non-`main` branch (e.g., `feature/xyz`) →
milestone step is skipped
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Change `detect_llm_stream` to accept `impl Fn(&str) -> bool` instead
of `&HashMap<String, json::Value>`, so the same helper works for both
`HashMap` (span attributes path) and `json::Map` (JSON ingest path)
without cloning or wrapping.
- Update the two callers in `src/service/traces/mod.rs` to pass `|k|
map.contains_key(k)`.
- Add unit tests covering empty input, no-match, and each LLM attribute
family (GenAi, O2, Langfuse) for both `HashMap` and `json::Map`.
## Test plan
- [x] `cargo check -p openobserve`
- [x] `cargo test -p openobserve --lib
service::traces::tests::test_detect_llm_stream` (7 passed)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>