Commit Graph
2984 Commits
Author SHA1 Message Date
Hengfei YangandClaude Opus 4.7 057348b308 feat: add reset file-list-jobs subcommand (#11535)
## 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>
2026-04-29 12:42:42 +00:00
Subhra264 511ca5ad91 fix: in update stream settings api the request add array should also be deduped (#11525)
Ref -
https://github.com/openobserve/openobserve/pull/11496#issuecomment-4326941487,
addresses these reviews that was missed by the earlier pr.
2026-04-29 11:36:52 +00:00
Subhra264 f43f4769b0 fix: list alert and list dashboard should use correct ofga query for list only permitted (#11526) 2026-04-28 17:39:42 +00:00
udev 5665a2059f ci: fix flaky tests (#11504) 2026-04-28 14:44:33 +00:00
Hengfei Yang 7fe6a481d3 feat: add llm_input and llm_output as default full text search fields (#11518)
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)
2026-04-28 12:15:03 +00:00
udev db32fd7db9 fix: sre agent sa creation (#11507)
- **fix casing in sre agent email to avoid FK violation from org_user
table**
- **add more permissions to sre agent SA**
2026-04-28 11:56:49 +00:00
c3e03cc6c4 fix: traces list shows blank rows when filtered by duration (#11514)
## 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>
2026-04-28 11:51:06 +00:00
Subhra264 f05fb3be90 fix: alerts/scheduled pipelines should follow cron when created/updated or enabled (#11489)
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.
2026-04-28 09:07:39 +00:00
Subhra264 bdbb4c6ac3 fix: stream settings update api should dedup fields before adding them to settings (#11496)
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.
2026-04-28 09:07:09 +00:00
Hengfei Yang 3a8bc126d7 fix: llm_usage_tokens_input not found (#11494)
fixed #11490
2026-04-27 16:35:28 +00:00
Huaijin 5327e8e402 fix: force llm field datatype (#11491) 2026-04-27 12:30:36 +00:00
20ed7ee5de fix: add usage reporting to license (#11192)
Add support for license v2 and usage reporting

---------

Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
2026-04-27 09:09:31 +00:00
Hengfei YangandClaude Opus 4.7 0adefa5377 refactor: make detect_llm_stream accept a key-lookup closure (#11480)
## 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>
2026-04-27 04:32:38 +00:00
b7bc228e49 feat(cloud): support contract subscription (#11336)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: udev <undefined@users.noreply.github.com>
2026-04-27 03:49:50 +00:00
Hengfei Yang 1033ade8bc fix: clear UDS when only _timestamp remains after removal (#11478)
## Summary
- When auto-UDS is triggered, the persisted `defined_schema_fields`
includes `_timestamp`. The UI hides `_timestamp` from the UDS selector
so the user can never deselect it.
- A "remove all UDS fields" action from the frontend therefore leaves
`defined_schema_fields = [\"_timestamp\"]` on the backend, which is
still treated as UDS enabled — making it impossible to disable UDS
through the UI even after raising `ZO_SCHEMA_MAX_FIELDS_TO_ENABLE_UDS`.
- Fix: in `update_stream_settings`, after applying the remove diff, if
only `_timestamp` is left, clear `defined_schema_fields` so UDS is
disabled.

Refs: openobserve/o2-enterprise#1570

## Test plan
- [x] On a stream where auto-UDS is enabled, open Schema settings and
switch to the User Defined Schema tab.
- [x] Select all visible UDS fields and delete them, then save.
- [x] Verify the response/stored settings have `defined_schema_fields =
[]` and the stream falls back to all fields (no `_timestamp`-only UDS
lingering).
- [x] Re-add fields to UDS and confirm the normal add path still works.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-27 03:35:03 +00:00
Subhra264 b45464507c fix: use text casting for cache report list db query (#11418)
Currently, the v2 list api for reports with `cache=true` uri params
fails with the following error -
```
Query Error: error returned from database: operator does not exist: json = jsonb
```
2026-04-26 13:46:02 +00:00
cc466132a7 chore: new home page (#11458)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Ashish Kolhe <undefined@users.noreply.github.com>
2026-04-25 19:18:21 +00:00
265bcae736 fix: add cache-control header for static assets (#11461)
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 14:57:59 +00:00
Harsh MahajanandShrinath Rao c535fe4402 fix: adding config to disable custom-llm-model-pricing (#11430)
Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
2026-04-24 11:01:28 +05:30
ktx-kirtan 8bdd333a0f Revert "feat: dashboard validation sync from BE" (#11437)
Reverts openobserve/openobserve#11034
2026-04-24 10:38:50 +05:30
udev cbda294ac1 Revert "fix: dashboards loading" (#11436)
Reverts openobserve/openobserve#11434
2026-04-24 10:36:39 +05:30
Ashish Kolhe fa22e80e22 fix: dashboards loading (#11434) 2026-04-24 09:44:55 +05:30
Huaijin 35c717cc66 chore: remove some unused code (#11419) 2026-04-24 01:35:24 +00:00
Hengfei YangandClaude Opus 4.7 bf3f1fbcd8 revert: "fix: node health api (#8744)" (#11425)
## Summary
- Reverts the three behavioral changes from #8744 in
`src/infra/src/cluster/mod.rs` (the file has since moved from
`src/common/infra/cluster/mod.rs`).
- Keeps the `heatbeat` → `heartbeat` comment typo fix.

## Why

The original `continue` on a missing `NODES_HEALTH_CHECK` entry was
correct self-healing behavior. The replacement in #8744 introduced three
problems:

1. **Cluster-wide failure from one stale entry.** `check_nodes_status`
iterates all online nodes, so `return Err(...)` on a missing uuid aborts
the entire loop. Every node not yet checked in that tick is silently
skipped.
2. **The proactive init on node add is redundant.** The success path in
`check_nodes_status` already runs
`w.entry(node.uuid.clone()).or_insert(0)`, so a node with a missing
entry was never actually unreachable by the health checker.
3. **There's a race window.** `NODES.write` and
`NODES_HEALTH_CHECK.write` in `Event::Put` are two separate lock
acquisitions. A concurrent `check_nodes_status` reading `NODES` can
observe the node present there but not yet in `NODES_HEALTH_CHECK`.
Pre-#8744 that just `continue`d; post-#8744 it aborted the whole tick.

PR-Agent's own reviewer flagged (1) and (3); those concerns weren't
addressed before merge.

## Test plan
- [ ] `cargo check -p infra` passes (confirmed locally)
- [ ] Manual / staging: bring up a multi-node cluster, bounce one node,
confirm health checks for the remaining nodes continue through the tick
where the bounced node becomes briefly inconsistent.
- [ ] Confirm the failure-threshold eviction path (`times >=
failed_times`) still works for a node that stops responding.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:16:25 +00:00
aec4a083d9 fix: stack histogram based on stream fields (#11390)
This PR fixes the issue in #11353 

 ## New Env
```sh
name = "ZO_HISTOGRAM_BREAKDOWN_FIELDS",
help = "Comma-separated ordered list of stream fields used for stacked histogram breakdown. First match wins."
default = "severity,log_level,level,status"
```

## Flow Chart

```
UI histogram request (is_ui_histogram = true)
                │
                ▼
    ┌───────────────────────┐
    │  is_multi_stream_search?│
    └───────────────────────┘
         │ yes          │ no
         ▼              ▼
  breakdown_field    stream_names.first()
      = None              │
         │                ▼
         │       infra::schema::get(org, stream, type)
         │                │
         │         ┌──────┴──────┐
         │       fails          ok
         │         │              │
         │         ▼              ▼
         │   breakdown_field   detect_histogram_breakdown_field(fields)
         │       = None              │
         │                   priority scan (case-insensitive):
         │                     1. severity?  ──yes──▶  breakdown_field = severity
         │                     2. log_level? ──yes──▶  breakdown_field = log_level
         │                     3. level?     ──yes──▶  breakdown_field = level
         │                     4. status?    ──yes──▶  breakdown_field = status
         │                     5. none match ──────▶  breakdown_field = None
         │                          │
         └──────────────────────────┘
                          │
                          ▼
          convert_to_histogram_query(sql, streams, multi, breakdown_field)
                          │
             ┌────────────┴────────────┐
          None                      Some(field)
             │                          │
             ▼                          ▼
   SELECT zo_sql_key,        SELECT zo_sql_key,
          zo_sql_num                "field" AS zo_sql_breakdown,
   FROM stream                      zo_sql_num
   WHERE ...              FROM stream
   GROUP BY zo_sql_key    WHERE ...
   ORDER BY zo_sql_key    GROUP BY zo_sql_key, zo_sql_breakdown
                          ORDER BY zo_sql_key
             │                          │
             └────────────┬─────────────┘
                          │
                          ▼
                    execute search
                          │
                          ▼
         Response {
           hits: [{ zo_sql_key, zo_sql_breakdown?, zo_sql_num }]
           histogram_breakdown_field: Option<String>
         }
                          │
             ┌────────────┴────────────┐
          None                      Some(field)
             │                          │
             ▼                          ▼
   generateHistogramData()    generateHistogramData()
   flat map:                  breakdown map:
   key → count                (key, category) → count
   xData / yData              breakdownSeries per category
             │                          │
             ▼                          ▼
     convertLogData()         convertStackedLogData()
     single-series            multi-series stacked
     ECharts options          ECharts options
                              + per-category color (palette)
                              + scrollable legend
             │                          │
             ▼                          ▼
     flat bar chart          stacked bar chart
      (unchanged)            (one color per category)
```

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: bjp232004 <551527+bjp232004@users.noreply.github.com>
Co-authored-by: Loakesh Indiran <66478092+Loaki07@users.noreply.github.com>
Co-authored-by: Loakesh Indiran <rustyloaki@gmail.com>
2026-04-23 12:06:49 +00:00
Subhra264 232ccf5bf3 fix: map_group_to_role should work even when custom_role is empty (#11408)
- Earlier when map_group_to_role env is enabled, the code flow was
ignoring the map_group_to_role flow when the custom_role was empty
(basically there is no custom role configured in the dex group claim).
This pr fixes this - so no matter whether the custom role is empty or
not, it will go to the map_group_to_role flow (this behaviour was there
earlier, but got broken when the sso claim parser was implemented)
- In the map_group_to_role flow, if the custom role array is empty it
was not adding the sso user to the DEX_DEFAULT_ORG at all even though
the ofga tuple mapping was being done. There is one issue in this pr
though that I just understood, it should add the user to dex_default_org
only when the organizations in the db user create payload is empty
(meaning, if the dex token contains nothing, the user should be added to
dex default org with default dex role). Will fix this shortly.
- When there is new custom org as per the token, it only adds the new
org, but does not remove existing org if there are not present in the
custom group claim returned by the sso claim parser.
2026-04-23 10:40:32 +00:00
78b7b7b622 feat: dashboard validation sync from BE (#11034)
Design at:
https://github.com/openobserve/designs/blob/main/dashboards/dashboard-validation-sync

---------

Co-authored-by: ktx-vaidehi <vaidehi.akhani@kiara.tech>
Co-authored-by: udev <uddhav@openobserve.ai>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Abhay Padamani <undefined@users.noreply.github.com>
2026-04-23 08:13:30 +00:00
Hengfei Yang 8d8352f41a fix: add custom skill support (#11381) 2026-04-23 08:15:45 +08:00
Loakesh Indiran 85fcad0670 fix: disable partitioning for ORDER BY on non-timestamp column (#11389)
When ORDER BY is on a non-timestamp column (e.g. duration), each
partition returns its own local top-N rows. Merging those produces
incorrect global sort order since globally highest values may not appear
in any partition's local top-N.

Add `ZO_DISABLE_PARTITIONS_FOR_NON_TS_ORDER_BY` env var (default false).
When true, non-aggregate non-histogram queries with ORDER BY on a
non-timestamp field return a single full-range partition instead.
2026-04-22 19:07:00 +00:00
vnghiaandHengfei Yang 4ba8f4567f fix: return empty if either left or right is empty for and (#11361)
This is the behavior of prometheus.

Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-04-22 16:32:29 +00:00
HuaijinandHengfei Yang 61c5826199 chore: code cleanup and add trace_id in logs (#11385)
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-04-22 16:20:32 +00:00
Bhargav 16c542d4d1 fix: Auto run query feature (#11376) 2026-04-22 23:01:08 +08:00
Hengfei Yang 77d376efa2 fix: improve real ip logic (#11378) 2026-04-22 22:56:05 +08:00
Sai Nikhil 78b32b88e3 fix: report folder issues (#11362)
1. search across folders is not working
2. when enabling search across or disabling it calling an api which is
not needed
3. while creating report the add folder is not there
4. while edigint the report user is able to change the folder which is
not consistent with alerts
5. when clicking on any folder if it still loading and user is moved
another folder it shoudl display that folder but it is redirecting user
to the previous folder that was clicked
2026-04-22 12:27:04 +00:00
Harsh Mahajan 3d52f4abd2 chore: LLM observability user-pricing (#10781) 2026-04-22 20:40:12 +08:00
Subhra264 353c58e962 fix: service accounts should not be able to rotate token without rbac (#11359) 2026-04-22 10:15:54 +00:00
Loakesh Indiran ced2f858a7 fix: validate multi-stream SQL join query fields against correct stream schema (#11374)
## Bug

Alert queries using SQL that joins two streams (CTE, direct JOIN,
subquery, UNION) fail
validation with a false `SearchFieldNotFound (20004)` error — even
though the same query
runs fine in Logs UI.

**Example error:**
```
Search field not found: body_type. Field not found in stream schema.
```

The query works in `_search` / `_search_stream` but fails when alerts
calls
`_search?validate=true` or `_search_multi?validate=true` before saving.

---

## Root Cause

`validate_query_fields` in `src/handler/http/request/search/utils.rs`
flattened fields
from **all** streams into one set, then validated every field against
the schema of the
**single primary stream** passed in (`stream_name`).

For a query joining `default` + `k8s_events`, `body_type` (which lives
only in
`k8s_events`) was checked against `default`'s schema — where it doesn't
exist — producing
a false negative.

---

## Behaviour Diagram

### Before (broken)

```
SQL joining "default" + "k8s_events"
                │
                ▼
    Sql::new_with_options() — parses SQL, loads both schemas
                │
                ▼
          ColumnVisitor assigns fields per stream:
          ┌──────────────────────────────────────┐
          │ sql.columns                          │
          │  "default"    → {k8s_pod_name, ...}  │
          │  "k8s_events" → {body_type, ...}     │
          └──────────────────────────────────────┘
                │
                ▼  ← BUG
    flatten ALL streams into one set
    {k8s_pod_name, body_type, event_name, ...}
                │
                ▼
    validate every field against "default" schema only
                │
        ┌───────┴────────┐
        │                │
   k8s_pod_name ✅   body_type ❌  ← only in k8s_events
                         │
                         ▼
            SearchFieldNotFound (20004)
```

### After (fixed)

```
SQL joining "default" + "k8s_events"
                │
                ▼
    Sql::new_with_options() — parses SQL, loads both schemas
                │
                ▼
          ColumnVisitor assigns fields per stream:
          ┌──────────────────────────────────────┐
          │ sql.columns                          │
          │  "default"    → {k8s_pod_name, ...}  │
          │  "k8s_events" → {body_type, ...}     │
          └──────────────────────────────────────┘
                │
                ▼
    find entry where stream_name == "default"
    target_fields = {k8s_pod_name, ...}
                │
                ▼
    validate ONLY "default" fields against "default" schema
                │
        ┌───────┴────────┐
        │                │
   k8s_pod_name ✅   body_type → not in target_fields, skipped ✅
                │
                ▼
              Ok(())
```

---

## Affected Query Shapes

All four patterns hit the same bug — any SQL that produces `sql.columns`
with keys for
more than one stream:

```sql
-- CTE + JOIN
WITH x AS (SELECT ... FROM "default") SELECT b.body_type FROM "k8s_events" b JOIN x ...

-- Direct JOIN
SELECT a.col, b.body_type FROM "default" a JOIN "k8s_events" b ON ...

-- Subquery
SELECT col FROM "default" WHERE id IN (SELECT id FROM "k8s_events")

-- UNION
SELECT col FROM "default" UNION SELECT body_type FROM "k8s_events"
```

---

## How `validate_query_fields` is meant to behave

The function validates **one stream at a time**. The handler calls it
once per stream in
the request — full coverage comes from all the calls combined, not from
a single call.

### `_search_multi` (multi-stream, correct path)

```
_search_multi?validate=true  with streams: ["default", "k8s_events"]
        │
        ├── validate_query_fields(org_id, "default",    sql)
        │       → checks default's fields ✅
        │       → body_type skipped (belongs to k8s_events) ✅
        │
        └── validate_query_fields(org_id, "k8s_events", sql)
                → checks k8s_events' fields including body_type ✅
```

Every stream's fields are validated against their own schema. No false
rejections, no gaps.

### `_search` (single-stream endpoint)

```
_search?validate=true  (primary stream: "default")
        │
        └── validate_query_fields(org_id, "default", sql)
                → checks default's fields ✅
                → body_type skipped (belongs to k8s_events) ✅
                → k8s_events fields: not checked ⚠️
```

`k8s_events` fields go unvalidated at pre-check time. This is a
**pre-existing
limitation**, not introduced by this fix. Runtime execution (DataFusion)
still validates
them — if `body_type` doesn't exist in `k8s_events` at query time, the
query fails then
with a clear error. `_search_multi` is the correct API for multi-stream
queries and
provides full pre-validation coverage.

### `_search_stream`

Never calls `validate_query_fields` — goes straight to execution.
Multi-stream joins
work because DataFusion resolves all streams at runtime.

---

## Fix

Look up the `sql.columns` entry that matches `stream_name` and validate
only that
stream's fields against its own schema. Fields from other streams in the
query are
validated separately when the handler calls `validate_query_fields` for
each stream.

```rust
// Before
let used_fields: HashSet<String> = sql.columns.values().flatten().cloned().collect();

// After
let (target_stream, target_fields) = sql
    .stream_names
    .iter()
    .find(|r| r.stream_name() == stream_name)
    .map(|r| {
        let fields = sql.columns.get(r).cloned().unwrap_or_default();
        (stream_name.to_string(), fields)
    })
    .unwrap_or_else(|| {
        // fallback: aliased or unresolved table — original behaviour
        let fields = sql.columns.values().flatten().cloned().collect();
        (stream_name.to_string(), fields)
    });
```

**File:** `src/handler/http/request/search/utils.rs` —
`validate_query_fields()`

---

## Tests

Added `test_cte_multi_stream_regression` module in `utils.rs`:

- `test_cte_join_cross_stream_field_not_rejected` — regression test for
the exact bug:
sets up `default` schema (no `body_type`) + `k8s_events` schema (has
`body_type`),
runs a CTE join query, asserts `validate_query_fields` returns `Ok(())`
for `default`.
  Fails on old code, passes after fix.
2026-04-22 10:03:01 +00:00
4ca1e3005d fix: corelation adaptive sampling (#11346)
Co-authored-by: Neha P <neha@openobserve.ai>
Co-authored-by: Claude <noreply@anthropic.com>
2026-04-21 09:12:29 +00:00
Subhra264 60dd85a329 fix: new rbac resource for incidents (#11344)
Currently incidents rbac is broken. This pr fixes this
2026-04-21 06:44:44 +00:00
Hengfei Yang defc2f4b0a fix: service graph running node (#11341)
fixed https://github.com/openobserve/o2-enterprise/issues/1504
2026-04-21 01:41:32 +00:00
b313248b55 fix: email mismtach cloud (#11340)
This fixes issues
1. on cloud FE would not do case insensitive comparison when checking
user's role
2. in invites flow BE would not do case insensitive comparison for
checking user's invites

---------

Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
Co-authored-by: Yashodhan Joshi <yjdoc2@gmail.com>
2026-04-20 15:31:51 +00:00
Huaijin b027510ac6 fix: some metrics issue (#11335)
- close: https://github.com/openobserve/openobserve/issues/11322
- close: https://github.com/openobserve/openobserve/issues/11321
2026-04-20 12:48:19 +00:00
Hengfei Yang 3bfd7451f0 fix: adjust partition ordering in trace processing (#11334)
Updated the logic for ordering partitions based on the SQL order
expression. If the expression is "zo_sql_timestamp DESC", partitions
remain unchanged. For "zo_sql_timestamp ASC", partitions are reversed.
For other fields, a single partition is returned, ensuring compatibility
with the new ordering requirements.
2026-04-20 12:06:47 +00:00
Subhra264 7a8502f7d9 fix: ofga migration for report folders (#11291) 2026-04-20 17:35:10 +08:00
ByteBakerandAshish Kolhe 907a3c74db fix: simplify _correlate API (#11301)
Co-authored-by: Ashish Kolhe <ashish.j.kolhe@gmail.com>
2026-04-19 10:54:07 +05:30
Huaijin 493dac7433 chore: update datafusion to 53.1.0 (#11310) 2026-04-17 12:03:02 +00:00
Subhra264 f45da519f3 feat: introduce api for report folders (#11261)
Ref https://github.com/openobserve/openobserve/issues/11219

Design at: dashboards/REPORT_FOLDER_VIEW_UI.md
2026-04-17 12:00:09 +00:00
Loakesh Indiran 1de40297e2 fix: propagate partial_err via dedicated flight message (#11292)
Sub-cluster internal node failures (h2 errors) were silently dropped —
partial_err was never transmitted to the super cluster leader, causing
degraded results to be cached as if they were complete.

Adds PreCustomMessage::PartialErrRefEarly + PartialErrRef to carry
partial_err over the flight wire independently of ScanStats (which can
be disabled at deployment level).

Sent twice for reliability: once before first batch (catches
fast-failing
nodes), once after all batches (final accumulated value). Decoder
dedupes
on receive.

Also elevates node gRPC error log from info → error.
2026-04-16 14:24:17 +00:00
Hengfei Yang 69fd00f0c5 fix: implement AES-256-SIV encryption and decryption utilities (#11286) 2026-04-16 19:15:56 +08:00
udevandBhargav 6f8ea1b772 fix: pagination support for values api (#11237)
Co-authored-by: Bhargav <BJP232004@GMAIL.COM>
2026-04-16 13:03:42 +05:30