Commit Graph
805 Commits
Author SHA1 Message Date
udev 6761ce2dbf fix: refactor online evals (#12654)
move online evals to enterprise repo
2026-06-15 10:13:55 +00:00
udevandsai nikhil kethe 12fffe4709 fix: online evals rbac list and edit role page (#12623)
- **edit role fixes**
- **fix rbac list apis**

---------

Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
2026-06-12 09:41:07 +00:00
Hengfei Yang 9c82beeeed fix: OTLP/JSON metrics silently dropping histograms and int values (#12615)
Close #12345

## Problem

OTLP histogram metrics sent over HTTP/JSON (e.g. otel-collector with
`encoding: json`) created streams but stored 0 events, with no
`_count`/`_sum`/`_bucket` streams. Int-valued counters/gauges were
silently recorded as 0. The protobuf path was unaffected, which is why
this only surfaced for collectors explicitly configured with JSON
encoding.

## Root cause

`otlp_json` deserializes the body directly into opentelemetry-proto's
serde-derived types, which only partially implement the proto3 JSON
mapping (64-bit integers encoded as strings, enums by name, zero/empty
fields omitted). `Metric.data` is a flattened `Option` oneof, and serde
converts any inner deserialization error of a flattened `Option` into
`None` instead of failing — so the whole metric silently became `data:
None`, while the stream itself had already been created by the schema
setup. Same mechanism on `NumberDataPoint.value` turned string `asInt`
values into 0.

## Changes

- Upgrade opentelemetry stack 0.31 → 0.32, which fixes string-encoded
u64 handling for plain histograms and summaries upstream.
- Add `otlp_json_compat` normalizer for the gaps still present in 0.32
(each verified empirically, with unit tests):
  - string `asInt` values on data points and exemplars
  - `aggregationTemporality` as enum name
  - `Exemplar`'s value oneof is not flattened in 0.32
- missing `serde(default)` on
`ExponentialHistogramDataPoint`/`Buckets`/`ValueAtQuantile`/`Exemplar`,
which rejected omitted zero/empty fields
- Count and log metrics whose data oneof failed to decode
(`partial_success.rejected_data_points`) instead of silently skipping
them, and stop overwriting specific partial-success error messages with
the generic retention message.
- Adapt to OTLP 0.32 API additions (`KeyValue.key_strindex`,
`AnyValue::StringValueStrindex`).
- Upgrade workspace reqwest 0.12 → 0.13, required because
opentelemetry-http 0.32 only implements `HttpClient` for reqwest 0.13
(`rustls` feature replaces `rustls-tls-native-roots` via the platform
verifier; `json`/`query`/`form` are now explicit features). The
`segment` crate is pinned to reqwest 0.12, so `TELEMETRY_CLIENT` moved
into `telemetry.rs` as a plain `reqwest::Client` that posts the Track
message itself, replicating `segment::HttpClient::send`.
- Remove the unused pyroscope profiling integration (optional feature,
dependencies, agent setup, `ZO_PROF_PYROSCOPE_*` config).

## Verification

- 10 unit tests in `otlp_json_compat` covering the full payload matrix
(collector-style string integers, enum names, omitted zero fields,
exemplars with and without trace context, already-normalized payloads,
malformed input).
- End-to-end: posted the issue's collector-style JSON payload to
`/api/default/v1/metrics` — `_bucket` (3 events, correct cumulative
counts with exemplars attached), `_count`, `_sum` populated for
histogram and exponential histogram, summary quantiles stored, `asInt`
counter stored as 42 instead of 0.
- `cargo clippy -- -D warnings` clean; lib test failures are
pre-existing local-environment issues that reproduce identically on
main.
2026-06-12 04:58:19 +00:00
Subhra264 00bd6f984a fix: use default folder for openfga report folder migration (#12568) 2026-06-10 11:48:25 +00:00
0aab1ae261 feat: online evaluations (#12352)
- **feat(online-eval): add PipelineKind::Evaluation and dual realtime
pipeline support**
- **feat(online-eval): add provider, score_config, scorer, and
online_eval_jobs DB entities**
- **feat(online-eval): add config CRUD services and API handlers**
- **feat(online-eval): reconcile jobs into hidden evaluation pipelines**
- **feat(online-eval): add scorer preparation and execution backends**
- **feat(online-eval): write scores and evaluator traces to system
streams**
- **refactor(online-eval): remove legacy eval templates backend**
- **test(online-eval): add API integration coverage for eval resources**

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: sai nikhil kethe <nikhil@openobserve.ai>
2026-06-04 16:03:14 +00:00
1b9c4c93e8 feat: super org (main) (#12380)
adds support for super org

---------

Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: Yashodhan Joshi <yjdoc2@gmail.com>
Co-authored-by: Bhargav <BJP232004@GMAIL.COM>
2026-06-03 14:27:15 +00:00
Hengfei Yang 3e865a3e6a ci: update rust (#12394) 2026-06-02 03:58:01 +00:00
c6179b91c5 fix: env key was not getting extracted from rum event (#12349)
#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>
2026-06-01 07:15:09 +00:00
Subhra264 9a1ed606aa feat: org level ingestion token (#11691)
Design at: observability/org-level-ingestion-token
2026-06-01 06:12:06 +00:00
1afabd35ce feat: bloom filter pruning layer above tantivy (#12121)
## Summary

Design at:
https://github.com/openobserve/designs/blob/main/infrastructure/bloomfilter/DESIGN.md

A bloom-filter pruning layer that sits **between `file_list` and
tantivy** in the search path. It drops candidate files before any `.ttv`
is opened, for **positive equality / IN** lookups on high-cardinality
fields (`trace_id`, `request_id`, …).

It is built **on top of** tantivy: the `.bf` is constructed by iterating
the tantivy term dictionary, so a field must be a tantivy secondary
index (`index_fields`) **and** opted into `bloom_filter_fields`. Only
the intersection is built — a bloom-only field produces nothing. To make
that intersection non-empty by construction, enabling a field for bloom
now folds it into `index_fields` automatically (see Config). Values are
not inspected; the operator chooses which fields are worth it (see
guidance below).

Design notes live in the module-level docs under `src/infra/src/bloom/`
(`mod.rs`, `writer.rs`, `reader.rs`, `sbbf.rs`).

## Design

- **Transposed (block-major) `.bf` layout.** All files in a `.bf` share
`num_blocks = B`, so `block_index = fastmap(hash(value), B)` is
identical across files and the blocks a query needs form **one
contiguous row**. The search side reads **one `M × 32`-byte row per
`.bf`** to answer membership for all `M` files — prune cost is
`O(groups)`, not `O(files)`. (`infra::bloom`, own ~120-LOC SBBF over
gxhash64.)
- **Sub-grouping.** A hour's new files are sorted by record count and
split into chunks of ≤ `ZO_BLOOM_FILTER_MAX_FILES_PER_BF` (default 256),
one `.bf` each. Bounds compactor build memory (`M × B × 32`) and `.bf`
object size; query reads become `ceil(files / 256)` rows.
- **Footer-only reader + batched fetch.** Footer (≈ `M × 12` B) comes
from `BLOOM_FOOTER_CACHE` or one 16 KB suffix GET (with a precise
re-read when a large footer overflows the probe); rows are pulled with
one `cache_storage::get_ranges` call. `cache_storage` was reworked to do
real batched cache reads (memory: 1 lookup + N slices; disk: 1
`File::open` + N `pread`).
- **B sizing.** `num_blocks_for(max_records_in_chunk,
ZO_BLOOM_FILTER_FPP)` (default fpp `0.01`) — record count is a safe NDV
upper bound, so the SBBF never saturates for high-cardinality fields.
- **Versioned, with orphan cleanup.** A file's `bloom_ver` is write-once
— a row is never re-stamped, so dumped rows keep pointing at the `.bf`
they were built into. But `bloom_ver` is **not** append-only at the
bucket level: a merge produces new output files with a fresh `bloom_ver`
and deletes the small inputs, so the old inputs' `.bf` can become
orphaned. After each merge round the compactor retires any `.bf` whose
`bloom_ver` is no longer referenced by a live `file_list` row in the
bucket (enqueued through the existing `file_list_deleted` path).
`bloom_ver` is preserved through every file_list INSERT/SELECT path
(incl. the SQLite read-cache) and the dump parquet.
- **Observability.** Prometheus metrics for prune
(`bloom_prune_keep_ratio`, `bloom_prune_duration_seconds`);
`bloom-inspect` CLI dumps a `.bf` footer (fields, B, row bytes, file
names); footer-cache hit/miss via the shared `BytesCache` tagged
metrics; `Local::get_ranges` now reports `STORAGE_READ_*` (previously
bypassed).

## When it helps (measured, S3, no disk cache)

Same stream `benchtest`, 170 files / 14.64 GB index, single matching
row. The only variable is whether the field's values are
time-correlated:

| Field | Type | tantivy only | bloom + tantivy | Outcome |
|---|---|---|---|---|
| `trace_id` (16-byte random) | random | **2584 ms** (opens all 170
`.ttv`) | 24 ms prune + 65 ms = **89 ms** | **~29× faster** |
| `request_id` (`…-7e74-…`, UUIDv7) | time-ordered | **154 ms** (sparse
index range-prunes) | 42 ms + 154 ms = **196 ms** | ~1.3× **slower** |

The whole 170-file group was answered by **one row read of 5440 bytes**
(`170 × 32`) + a cached footer.

**Guidance — enable only when all three hold (advisory; not enforced):**
1. **High cardinality** field.
2. **Random values** (not time-ordered) — so tantivy can't range-prune
and must scan every file. Time-ordered ids (UUIDv7, snowflake) are
already pruned by tantivy's sparse index in memory → bloom is pure
overhead there.
3. **Many files per hour** — hourly volume ≳ 10 ×
`ZO_COMPACT_MAX_FILE_SIZE` (≳10 `.ttv` files), so there's something to
prune. Bloom turns N file opens into one row read; at 1–2 files/hour
it's net overhead.

The 29× result above had 170 files/hour all answered by one `.bf`. ❌
Low-cardinality / non-indexed / range / `LIKE` / regex / `!=` / OR: no
effect.

## Config

- `ZO_BLOOM_FILTER_ENABLED` (default true) — global gate.
- Per stream: a field must be in **both** `index_fields` and
`bloom_filter_fields`. Adding a field to `bloom_filter_fields` auto-adds
it to `index_fields` (bloom is built on the secondary index), and the
default index fields include the default bloom fields.
- `ZO_BLOOM_FILTER_FPP` (default 0.01) — target false-positive
probability; sizes the SBBF block count (smaller fpp = fewer false
survivors, larger `.bf`). Out-of-range falls back to 0.01.
- `ZO_BLOOM_FILTER_MAX_FILES_PER_BF` (default 256) — files per `.bf`;
trades query reads vs build memory.
- `ZO_BLOOM_FILTER_DEFAULT_FIELDS` (default empty) — fields bloomed for
every stream.
- `ZO_BLOOM_FOOTER_CACHE_MAX_SIZE` (default 1% mem, clamped 32–256 MB).

Removed in this PR: `ZO_BLOOM_FILTER_DISABLED_ON_SEARCH`,
`ZO_BLOOM_FILTER_NDV_RATIO` (B is now sized from record count + fpp, not
an ndv ratio).

## Test plan

- [x] `cargo build`, `cargo clippy -p infra -p openobserve --lib -- -D
warnings`, `cargo fmt --check` clean
- [x] Unit tests: `cargo test -p infra --lib bloom`, `cargo test -p
openobserve --lib bloom`
- [x] E2E on S3 (results above): random field prunes 170→1 and is ~29×
faster; transposed read = 1 request / 5440 B per group
- [x] Reviewer: confirm gating expectations (operator opts fields in; no
auto value detection)
- [x] Test: orphan bloom: 2 * 256MB -> merge to 512MB -> merge to
1024MB, the first .bf should be deleted
- [x] Test: orphan bloom: 6 * 256MB -> merge to 1GB + 512MB -> 512 MB
merge to 1024MB, the first .bf include 2 files(1GB + 512MB), after merge
again, the first still have 2 files but one of them already deleted. we
should keep the first .bf, because still have files in use.

## Notes

- `.bf` format is `VERSION 0x01` (transposed). Not compatible with any
pre-merge experimental `.bf`; rebuild by wiping the `bloom/` dir and
resetting `bloom_ver=0`.
- Hash is gxhash64 (project-wide `config::utils::hash`), not the Parquet
spec's xxhash64 — `.bf` is internal, never read by external tools.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-05-29 07:33:11 +00:00
Subhra264 85a307ba67 fix: anomaly rbac migration (#12142) 2026-05-25 10:29:29 +00:00
Huaijin dde90c14de refactor: unify search partition handle (3) (#12115)
related to 
- https://github.com/openobserve/openobserve/pull/8003
- https://github.com/openobserve/openobserve/issues/7986


# Why We Can Delete `enable_align_histogram`

## What It Was

`enable_align_histogram` was a query parameter introduced in [PR
#8003](https://github.com/openobserve/openobserve/pull/8003) to fix
[Issue #7986](https://github.com/openobserve/openobserve/issues/7986).
The bug was that in the old two-step search flow (`_search_partition` →
`_search`), the two APIs independently generated histogram intervals,
leading to mismatched time buckets and inaccurate chart rendering in
dashboards.

The flag told `_search_partition` to:
1. Align partition boundaries to histogram interval boundaries (e.g.,
round to the start of a minute/hour/day).
2. Return the computed `histogram_interval` in the response so the
frontend could pass it to `_search`.

## Why It Is Now Dead Code

### 1. The frontend no longer calls `_search_partition`

All frontend search now uses `_search_stream` (HTTP/2 streaming), which
internally calls `search_partition()` with `enable_align_histogram =
false`. The old `_search_partition` endpoint is no longer consumed by
the UI. The only frontend caller (`getValuesPartition` in
`IndexList.vue`) is defined but never invoked.

### 2. `search_stream` handles alignment inherently

In the streaming search flow, partitions themselves define the search
time ranges. Each partition search runs on the exact aligned time
boundaries returned by the partition step. There is no separate
histogram query that needs an externally provided interval — alignment
is "baked into" the partition boundaries.

### 3. Histogram queries are already covered by `is_complex_query`

For histogram queries (which have `GROUP BY`), `is_complex_query`
returns `true`. Combined with `has_ts_column = true`, this triggers
`calculate_partition_settings()` to align `min_step` to the histogram
interval — the same alignment behavior that `enable_align_histogram`
previously provided, but without the extra flag.

### 4. All backend callers pass `false`

Of the 5 callers of `search_partition()`:
| Caller | Value |
|--------|-------|
| gRPC handler | hardcoded `false` |
| streaming execution | hardcoded `false` |
| traces handler | hardcoded `false` |
| HTTP `_search_partition` | from query param (frontend always passed
`true`, but frontend no longer calls this) |
| HTTP `_search_partition_multi` | from query param (frontend always
passed `true`, but frontend no longer calls this) |

No active code path ever sets `enable_align_histogram = true`.

## What Was Removed

- `get_enable_align_histogram_from_request()` — the HTTP query param
parser
- The `enable_align_histogram` parameter from:
  - `search_partition()` function signature
  - `search_partition_multi()` function signature
  - `calculate_partition_settings()` function signature
- The alignment logic in `search_partition()`:
  - `add_mini_partition` (always `false` without the flag)
- `PartitionGenerator` align parameter (now driven by `is_histogram`
alone)
  - `resp.histogram_interval` override block
- The `|| enable_align_histogram` branch in
`calculate_partition_settings`
- The query parameter from both HTTP handler `utoipa` specs
- The `false` argument from all 5 call sites
2026-05-22 11:08:51 +00:00
Subhra264 6ec195ac81 fix: revamp rbac (#11610)
Revamps the complex rbac logic to make it simpler.
Also, 
- Adds RBAC for anomaly apis
- Fixes https://github.com/openobserve/openobserve/issues/11710
2026-05-20 15:03:23 +00:00
Subhra264 74538574f0 fix: don't allow creating saved views with same name in same org (#11736) 2026-05-15 05:43:02 +00:00
Loakesh Indiran 85128776cb fix: migration-issues-fixes (#11827)
ref: https://github.com/openobserve/openobserve/pull/10588
2026-05-14 15:45:31 +00:00
ea5e0e1102 feat: org level storage configuration (#11614)
This adds supports for configuring storage at org level instead of
installation level in ent and cloud setup.

design at:
https://github.com/openobserve/designs/blob/main/infrastructure/custom-s3-bucket-support/design.md

---------

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>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 09:33:02 +00:00
Ashish Kolhe 3161d13785 fix: refactor ssrf (#11734) 2026-05-14 08:32:40 +00:00
Harsh Mahajan 56856f3955 fix: ent build (#11613)
caused by https://github.com/openobserve/openobserve/pull/11588
2026-05-05 21:50:44 +00:00
Loakesh IndiranandHengfei Yang 379087b550 chore: add sync unit tests (#11588)
## Summary

- Add `#[cfg(test)] mod tests` blocks to ~525 files across all workspace
crates
- Covers: openobserve, infra, config, ingester, wal, flight,
tantivy_utils, cli
- All tests are synchronous (`#[test]` only) — struct defaults, serde
roundtrips, enum variants, pure utility functions
- No async tests, no logic changes — purely additive

---------

Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-05-04 10:38:41 +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
Huaijin 35c717cc66 chore: remove some unused code (#11419) 2026-04-24 01:35:24 +00:00
Hengfei Yang 77d376efa2 fix: improve real ip logic (#11378) 2026-04-22 22:56:05 +08:00
Harsh Mahajan 3d52f4abd2 chore: LLM observability user-pricing (#10781) 2026-04-22 20:40:12 +08: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
Subhra264 7a8502f7d9 fix: ofga migration for report folders (#11291) 2026-04-20 17:35:10 +08: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
Hengfei Yang b266560838 feat: support custom AI tools (#11270) 2026-04-15 20:11:35 +08:00
Ashish Kolhe 55e9e92cc4 fix: update ofga version (#11272) 2026-04-15 12:04:33 +05:30
85d261b5d0 fix: vulnerability scan fixes (#11249)
| # | Severity | Category | File |
| :--- | :--- | :--- | :--- |
| 1 | **High** | SSRF bypass (IPv6) | `ssrf_guard.rs` |
| 2 | **High** | SSRF bypass (retry) | `enrichment_table/mod.rs` |
| 3 | **High** | SSRF defense-in-depth | `alert.rs` |
| 4 | **Critical** | CORS + credentials | `router/mod.rs` |
| 5 | **Critical** | SQL Injection | `postgres.rs`, `sqlite.rs` |
| 6 | **High** | Privilege escalation (token) | `users.rs` |
| 7 | **Medium** | Panic/DoS | `users.rs` |
| 8 | **Low** | Integer overflow | `alerts/mod.rs` |
| 9 | **Medium** | XSS | `alertSummaryGenerator.ts`, `colorizeQuery.ts`
|
| 10 | **Medium** | Credential exposure in logs | `validator.rs`,
`organization.rs`, `users.rs` |

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
Co-authored-by: Prabhat Sharma <hi.prabhat@gmail.com>
2026-04-14 07:22:11 +00:00
Ashish Kolheandgithub-actions[bot] 2ee44808c0 fix: fga for eval templates (#11238)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-13 06:35:27 +00:00
ByteBaker 58a0297b96 fix: SRE SA auth for MCP (#11228)
- fix incidents not correlating for alert ID
- SRE SA no more visible in other screens than main SA list
- SreAgent role cannot be assigned to any other user now
- regular user now working for MCP
2026-04-10 14:41:25 +00:00
Subhra264 938347df85 fix: db email instead of token email, should be used for UserEmail and openfga check (#11226)
When validating access token, we should use the email returned from db
query to do `check_permissions` rbac function call. Reason is, in
openfga db, we store the same user email as stored in the openobserve
db. Hence, all the permission is supposed to be evaluated against the
same email stored in the db.

The email decoded from token can have any case (upper/lower) as per
user's sso config, so it is important to follow the case stored in the
db created when the user logged in for the first time.
2026-04-10 06:38:37 +00:00
Sai prasanna sastry 5ba6968d7f fix: extract resolve_write_method helper and add auth permission tests (#11009) 2026-04-07 20:39:07 +08:00
ByteBakerandHengfei Yang b948361769 chore: update copyright year to 2026 (#11166)
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-04-07 09:57:53 +08:00
1d3618ad94 chore: system-managed SRE Agent service account provisioning (#11130)
## Summary

Implement automatic provisioning and lifecycle management of
per-organization system service accounts for the AI-powered SRE Agent.
These accounts serve as the identity for RCA (Root Cause Analysis) agent
API interactions and are created automatically for each organization.

## Key Features

### Service Account Provisioning
- Database migration creates SRE Agent accounts for all existing
organizations
- Deterministic email format:
`o2-sre-agent.org-<ORG_ID>@openobserve.internal`
- System accounts are automatically created on organization creation
- Idempotent operations ensure safe re-runs and self-healing

### System Account Protection
- API endpoints prevent modification/deletion of system service accounts
(403 Forbidden)
- User responses include `is_system` flag to identify system accounts
- Protection enforced at HTTP handler layer

### RCA Agent Client Refactoring
- Singleton pattern: global client initialized once at startup
- Per-request user credential forwarding for better audit trails and
scoping
- Lazy initialization: returns None if agent service not configured
- Updated all query methods to accept and forward auth credentials

### Incident Correlation Enhancement
- Query `ServiceIdentityConfig` to get configured semantic dimension
groups
- Extract only `distinguish_by` fields from matched identity sets
- Use parallel correlation execution (Service Discovery + semantic
extraction)
- Improved accuracy by using configured groups instead of fallback label
extraction

### Improved Token Redaction
- Consistent 12-character format: first 4 visible characters + 8
asterisks
- Better security for token display in UI
- Updated tests for new redaction format

## Technical Details

### Database Changes
- New migration:
`m20260331_000001_create_sys_rca_agent_service_accounts`
- Creates accounts with organization and RUM tokens
- Safe pagination (100 orgs at a time) with idempotency checks
- System accounts use role type 6 (SreAgent, distinct from
ServiceAccount)

### Authorization
- System accounts added to OpenFGA with standard org membership tuples
- SRE-specific read-only role for permission control
- Self-healing: runtime ensures OpenFGA state is consistent with
database state

### API Changes
- GET /users: Returns `is_system` and `description` fields
- PUT/DELETE /users: Reject modification/deletion of system accounts

## Test Coverage
- Token redaction tests updated for new format
- System service account protection verified
- User list pagination tested with system accounts

## Feature Flag
This is an enterprise feature gated behind `#[cfg(feature =
"enterprise")]`. System accounts are always created, but RCA integration
only works if the agent service is configured.

## Deployment
- Zero-downtime: migration is additive
- Opt-in for OSS deployments
- Automatic provisioning on upgrade and org creation

---------

Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-04-06 14:30:20 +00:00
漂流 fbf7283ffc chore: use std instead of once_cell (#11081) 2026-04-06 16:27:16 +08:00
416a6cce32 feat: work group v2 — slot-based admission (#10990)
## Summary

Design at:
https://github.com/openobserve/designs/blob/main/infrastructure/work-group/work_group_v2_impl.md

This PR adds slot-based distributed admission control for search queries
and fixes file dispatch consistency when a subset of querier nodes is
selected per query.

To enable this feature we need to set:

```
O2_WORK_GROUP_MAX_NODES_PER_QUERY > 0
O2_WORK_GROUP_NODE_SELECTION_STRATEGY = org | stream
```

### Slot-based admission

- Add `TryAcquire / StartQuery / ReleaseQuery` gRPC RPCs — Follow nodes
reserve slots before execution starts and self-release via
`FlightEncoderStream::drop`
- Wire slot admission in both Arrow Flight search and PromQL paths,
co-located with the existing org/user concurrency queue check
- Delegate DataFusion `target_partitions` / `memory_size` to enterprise
`get_resource_limit()`, which applies per-query slot fraction with
optional dynamic expansion
- TTL sweep interval derived from `slot_reserved_ttl_ms / 4` (min 100
ms) instead of a hardcoded 500 ms
- Move `QUERY_PENDING_NUMS` / `QUERY_RUNNING_NUMS` metric updates to
after slot admission completes (a blocked request is no longer counted
as "running")

### Consistent-hash file dispatch fix (`max_nodes_per_query > 0`)

- Add `get_node_from_consistent_hash_within(key, role, group, allowed)`
to `infra::cluster`: walks the global ring clockwise from `hash(key)`
but skips nodes outside `allowed`. Preserves all consistent-hash
properties (even distribution via vnodes, minimal remapping on
membership change) while confining dispatch to the selected subset
- `partition_file_by_hash` now passes only the selected querier nodes as
the `allowed` set, so every file maps to one of the N selected nodes —
no more fallback-to-index-0 imbalance when `strategy=org/stream`
- File-list broadcast (enterprise) pre-computes per-item target nodes
using the same filtered ring walk via `broadcast_item_targets()` in
`o2-enterprise`, so broadcast and dispatch always agree on which node
owns each file

### Proto fix

- Reserve field 10 in `QueryStatus` (was `WorkGroup` enum / varint wire
type) and move `work_group` string to field 13 — prevents wire-type
mismatch during rolling upgrades

### Other fixes from code review

- `get_first_stream_key()` now returns `"{stream_type}/"` sentinel
instead of `""` for multi-stream / cross-index queries, so
`select_nodes` always receives a non-empty deterministic key
- PromQL node selection uses `"metrics/"` stream key (consistent with
the sentinel format) instead of bare `"metrics"`
- Move `_orig_trace_id` binding inside `#[cfg(feature = "enterprise")]`
block in `FlightEncoderStream::drop`

## Key config (all default to safe/off values)

| Env var | Default | Description |
|---|---|---|
| `O2_WORK_GROUP_MAX_NODES_PER_QUERY` | `0` | Nodes per query; 0 = all
nodes (disables slot admission) |
| `O2_WORK_GROUP_NODE_SELECTION_STRATEGY` | `all` | `all` / `org` /
`stream` |
| `O2_WORK_GROUP_SHORT_SLOT_RATIO` | `0.8` | Max fraction of node slots
for short queries |
| `O2_WORK_GROUP_DYNAMIC_RESOURCE` | `true` | Expand DataFusion
allocation on idle nodes |

## Test plan

- [x] Default (`max_nodes_per_query=0`): behavior identical to before,
zero overhead
- [x] `strategy=org`, `max_nodes_per_query=3`, 10-node cluster: each org
consistently uses the same 3 nodes; files distributed evenly across
those 3 nodes (no node-0 pile-up)
- [x] Broadcast routes each file to the same node that
`partition_file_by_hash` selects at query time → cache hits on
re-queries
- [x] Slot admission: 3rd request waits when budget=2 and 2 queries
running; slots released on completion
- [x] PromQL queries respect slot budget
- [x] Rolling upgrade: old node sends `QueryStatus` without field 10
conflict

## Related

Requires companion PR in `o2-enterprise`:
https://github.com/openobserve/o2-enterprise/pull/1378

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-05 05:31:37 +00:00
ByteBaker d25fbf97c1 fix: do not show service account token post creation (#11110)
So far, service account token could be viewed and copied even after an
SA was created. This was bad design and posed risk of impersonation.

The changes prevent this from happening by returning only the redacted
token in the API response. Full token with create API itself, and
removing GET API to get the service account details (which returned raw
token).

The same affects token rotation as well.
2026-04-01 19:29:42 +00:00
477ec39db2 feat: add support for sourcemaps for RUM (#10259)
This ads support for sourcemaps in RUM

Design at :
https://github.com/openobserve/designs/blob/main/application-monitoring/rum/sourcemap-be.md

---------

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>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-24 21:18:06 +05:30
Subhra264 11e16f47eb fix: don't do unnecessary lowercasing of user emails (#10938) (#10985) 2026-03-23 10:04:53 +01:00
ByteBaker 4a6c9efdb1 chore: enable UI toggle for self-org usage reporting 2026-03-23 13:17:46 +05:30
Ashish Kolhe ec0dc67d5a fix: for prometheus metadata api (#10934) 2026-03-17 15:25:35 +05:30
Hengfei Yang 9e7336897e fix: extract auth for ratelimit (#10887) 2026-03-13 15:21:31 +08:00
Hengfei Yang 518761b6ca fix: add random jitter to keep-alive mechanism and delay after node registration (#10883) 2026-03-13 11:50:53 +08:00
Sai Nikhil d2861433fa fix: search inspector UI (#10749) 2026-03-13 09:57:29 +08:00
udev a1ba8b1b71 feat: Ai metering for cloud (#10824) 2026-03-13 00:57:31 +05:30
Hengfei Yang 76c4f5c423 fix: trace stream api (#10880) 2026-03-12 22:38:43 +08:00
Subhra264andHengfei Yang 3d9369910d fix: rbac for alerts trigger api (#10834)
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-03-11 10:34:05 +08:00
Loakesh Indiran b82271f70b feat: add anomaly detection (#10538) 2026-03-11 10:25:46 +08:00
Subhra264 e5293ba348 fix: scheduled pipeline test run query should use ui search type and rbac fixes for alert history and generate_sql apis (#10800) 2026-03-09 20:22:23 +08:00