Commit Graph
390 Commits
Author SHA1 Message Date
Huaijin 3b44da3eee refactor: extract shared common crate (#13252)
## Summary

- introduce a `common` workspace crate for shared metadata,
infrastructure helpers, and utilities
- keep service-backed code in `openobserve-core` while preserving the
existing `common` compatibility namespace
- flatten `src/core/src/service/` into the standard `src/core/src/`
module layout without using `#[path]`
- retain `service::*` as compatibility re-exports from `service.rs`
- move cipher request/response types from core into the search crate
while preserving `openobserve_core::cipher`
- remove unused Cargo dependencies from workspace crates

Enterprise companion:
https://github.com/openobserve/o2-enterprise/pull/2202

## Validation

- `cargo check --workspace --all-targets`
- `cargo clippy -p common -p openobserve-core -p search --lib -- -D
warnings`
- common crate unit tests: 271 passed, 4 ignored
- enterprise overlay: `cargo check -p openobserve-core --features cloud`
- migrated cipher tests: 8 passed
- `cargo deny check licenses`
- `cargo fmt --all -- --check`
- `git diff --check`
2026-07-17 13:58:24 +00:00
4031f76426 feat: synthetic monitoring (#12849)
Design at : https://github.com/openobserve/designs/tree/main/synthetics

ref: https://github.com/openobserve/o2-enterprise/issues/2095

---------

Co-authored-by: omkark06 <omkar@zinclabs.io>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Claude <claude@users.noreply.github.com>
2026-07-17 08:58:47 +00:00
Huaijin 66ca3d2439 refactor: extract PromQL evaluator into dedicated crate (#13239)
## Summary

- add a dedicated promql workspace crate for parsing and evaluation
- keep cluster routing, cache, WAL, file-list, and request orchestration
in openobserve-core
- preserve existing service::promql call sites through a compatibility
facade; the facade re-exports an explicit item list (not a glob), and
the promql search orchestration in core depends on the promql crate
directly
- inject enterprise query cancellation through TableProvider instead of
coupling the evaluator to core search state
- replace the core regex-UDF dependency with DataFusion regexp_like
expressions

## Companion PR

- openobserve/o2-enterprise#2198 updates the enterprise workspace
override for the new promql crate

## Validation

- cargo fmt --all -- --check
- cargo check --workspace
- cargo clippy -p promql --all-targets -- -D warnings
- cargo clippy -p openobserve-core
- cargo test -p promql: 363 passed
- verified the promql dependency tree has no openobserve-core or search
dependency
- cargo check -p o2_enterprise --lib in the paired private workspace

## Notes

The evaluator moves atomically in this PR. The existing
service::promql::search subtree remains in core because it owns
OpenObserve-specific orchestration rather than PromQL evaluation.

The two web/ file changes only update source-path references in comments
that pointed at the moved Rust files (src/service/promql/... ->
src/promql/src/...).
2026-07-17 02:46:02 +00:00
Huaijin f36c9bd5f1 refactor: move search engine into search crate (#13238)
## Summary

This is PR 2 of the atomic search-crate split, following #13234.

- move the complete query-engine SCC into `src/search`: DataFusion, SQL,
index, Tantivy, bloom pruning, inspector, and engine utilities
- move 130 Rust files / 43,935 lines as a single atomic change
- keep search orchestration, result-cache policy,
cluster/gRPC/streaming, partitioning, usage, and audit responsibilities
in `openobserve-core`
- preserve existing `openobserve_core::service::search::*` paths through
ordinary facade re-exports
- move direct engine dependencies and feature ownership into the
`search` manifest
- remove core dependencies used only by the moved engine

No query behavior change is intended. Source changes inside the moved
engine are limited to crate-relative import paths and formatting.

## Dependency boundary

```text
openobserve / API / jobs
          |
          v
openobserve-core (orchestration)
          |
          v
search (query engine)
          |
          v
config / infra / proto / flight / openobserve-vrl
```

- `search` does not depend on `openobserve-core`
- `openobserve-vrl` remains independent of both `search` and
`openobserve-core`
- the old core DataFusion, SQL, and Tantivy implementation directories
no longer exist

## Validation

- `cargo check --workspace`
- `cargo check -p openobserve --features mimalloc`
- `cargo clippy -- -D warnings`
- `cargo clippy -p search -p openobserve-core --lib -- -D warnings`
- `cargo fmt --all -- --check`
- Cargo metadata dependency-boundary checks
- `cargo test -p openobserve-vrl --lib` — 7 passed
- `cargo test -p search --lib` — 876 passed; 12 existing histogram
static-configuration tests fail in this local environment
- `cargo test -p openobserve-core --lib` — 2407 passed, 6 existing
global-state/filesystem/DB-isolation tests failed, 18 ignored
- filtered reruns excluding those existing environment-sensitive tests
passed

## Not run

- private Enterprise / Vectorscan / Vortex overlay builds
- local/distributed runtime smoke tests
- cold/incremental build and query runtime performance benchmarks

No performance improvement is claimed by this PR until those benchmarks
are completed.
2026-07-17 01:15:20 +00:00
Huaijin 059058519e refactor: make search engine sources crate-independent (#13234)
## Summary

- add `src/vrl` as a leaf package named `openobserve-vrl` with Rust path
`openobserve_vrl`
- move `QUERY_FUNCTIONS`, enrichment-table ownership, GeoIP/MaxMind
table registration, VRL compiler configuration, and shared runtime
helpers into `openobserve-vrl`
- let ingestion, jobs, core, and search use the shared VRL integration
without depending on one another
- keep DataFusion UDF registration direct through `Sql.org_id`; no
`QueryExecutionContext`, `PreparedQueryTransform`, or
`prepare_query_transforms`
- move the cipher registry, query parameters, and file-cache helpers to
`search`
- move the generic file downloader implementation to `infra`
- add feature forwarding for the `search` crate
- keep compatibility re-exports for existing API, ingestion, gRPC, jobs,
and Enterprise call sites

Enterprise companion:
https://github.com/openobserve/o2-enterprise/pull/2196
2026-07-16 13:50:35 +00:00
Huaijin d6166aac49 perf: speed up embedded web asset compilation (#13233)
## Summary

- upgrade rust-embed-for-web from 11.3 to 11.4.1
- disable unused compile-time gzip and Brotli generation for embedded UI
assets
- keep browser response compression through the global tower-http
CompressionLayer

Related enterprise PR:
https://github.com/openobserve/o2-enterprise/pull/2192

## Benchmark

Clean release-profiling build with mimalloc:

- before: 21m 13s
- after: 15m 45s
- improvement: 5m 28s, or 25.8%

Focused web crate compilation improved from 546.66s to 98.55s.

## Testing

- cargo metadata --locked --no-deps --format-version 1
- cargo clean
- cargo build --features mimalloc --profile release-profiling
2026-07-16 10:44:10 +00:00
Huaijin 5dc22a0ee8 refactor: establish search crate boundary (#13217)
## Summary

- add the minimal `openobserve-search` workspace crate and move shared
search/cache types into it
- move the concrete enrichment table type and cache ownership to the
search crate while retaining normal compatibility re-exports
- move trace schema constants to `config` so the SQL engine no longer
reaches into the traces service
- expose concrete enrichment read functions from `infra` and make
DataFusion call them directly
- construct the stateless VRL runtime directly in the transform UDF
- keep search execution and orchestration in `openobserve-core` for the
later physical moves
- do not introduce `SearchRuntime`, provider traits, callbacks,
`#[path]`, or a search-to-core dependency

This combines the original crate-boundary step with the dependency
cleanup needed before SQL/DataFusion files can move safely.

## Validation

- `cargo test -p openobserve-search --lib` (11 passed)
- `cargo test -p openobserve-core service::enrichment::tests --lib` (19
passed)
- `cargo check -p openobserve --features mimalloc`
- enterprise + mimalloc check using the o2-enterprise overlay
- cloud + mimalloc check using the o2-enterprise overlay
- `cargo fmt --all -- --check`
- strict all-target clippy for `openobserve-search` and
`openobserve-core`
- strict library clippy for `infra`
- dependency check confirms `openobserve-search` does not depend on
`openobserve-core`

`infra --all-targets` currently reports three pre-existing inconsistent
digit-grouping warnings in
`src/infra/src/table/entity/alert_dedup_state.rs`; they are unrelated to
this change and are not included here.
2026-07-16 06:50:01 +00:00
Huaijin 3559d483ae refactor: move web UI asset embedding into a dedicated leaf crate (#13211)
## Problem

Every rebuild of `openobserve-api` re-runs the `RustEmbed` macro
expansion, which embeds `web/dist` (53MB, 1035 files) and compresses
every file with gzip + brotli(q11) — single-threaded, non-incremental,
and it peaks at 8GB RSS. `-Ztime-passes` attributes ~540s of the 769s
api compile to `expand_crate`. Net effect: touching one file in
`openobserve-core` costs a **16m45s** rebuild on an M-series laptop, and
neither incremental compilation nor codegen-unit tuning can help,
because macro expansion happens before both.

## Fix

Move the `#[derive(RustEmbed)]` into a new `src/web` leaf crate with no
workspace dependencies. The embed + compression now only recompiles when
`web/dist` changes; edits anywhere in the backend no longer pay for it.

**Measured (same machine, default profile settings, `--profile
release-profiling`):**

| | before | after |
|---|---|---|
| `openobserve-api` compile | 769s | 231s |
| touch `src/core` → binary | 16m45s | **6m44s** |

## Also in this PR

- **`src/web/build.rs`**: the derive has no file tracking, so a rebuilt
`web/dist` silently shipped stale embedded assets until something else
dirtied the api crate. `rerun-if-changed` on the embed folder fixes
that. The folder is parsed from the `#[folder]` attribute rather than
hardcoded, so it stays correct when the e2e workflows rewrite it. A
missing `index.html` now prints a build warning instead of silently
embedding nothing (the #13197 failure mode).
- **Playwright workflows**: the embed-folder `sed` now targets
`src/web/src/lib.rs` and is guarded with `grep -q`, so a future path
drift fails at the sed step instead of silently shipping an empty UI and
failing at the login page (see openobserve/o2-enterprise#2175 for that
incident).
- **`deny.toml`**: allow the new crate's AGPL-3.0 license (CI runs
`cargo deny check licenses`, which requires a per-crate exception).

## Validation

- `cargo deny check licenses` passes
- Smoke-tested the binary: `/healthz` ok, `/web/` serves `index.html`,
JS assets return 200 from the embedded bundle
- Enterprise overlay resolves: `cargo metadata` passes with the
companion `Cargo.toml.openobserve` change

## Companion

openobserve/o2-enterprise#2184 carries the overlay + e2e workflow sync
on the **same branch name** (`perf/web-embed-crate`); the two should
merge together.
2026-07-16 01:33:42 +00:00
Huaijin bcea47f644 refactor: extract management API crate (#13202)
## Summary

- add the `openobserve-api-management` crate under `src/api_management`
- physically move management handlers, models, and authentication
helpers out of `openobserve-api`
- preserve the existing API module paths through re-exports
- move shared stream permission checking into `openobserve-core` to
avoid a management-to-query dependency
- allow the new crate's `AGPL-3.0` license in `deny.toml` (fixes the
cargo-deny `check` job)
- keep router, OpenAPI generation, and rate-limit path mapping in
`openobserve-api`

## Dependency boundary

`openobserve-api-management` depends on `openobserve-api-common` and
`openobserve-core`; it does not depend on `openobserve-api-query`.

## Note on `split-debuginfo`

Removing `split-debuginfo = "packed"` from `[profile.release-profiling]`
is intentional (not a formatting artifact): profiling builds now keep
DWARF debuginfo embedded in the binary, so profiling artifacts can be
symbolized at runtime without shipping a separate debuginfo file. The
o2-enterprise overlay `Cargo.toml.openobserve` is kept in sync.

## Companion PR

- openobserve/o2-enterprise#2175

## Validation

- OSS check with `mimalloc`
- OSS strict clippy with all targets
- enterprise check and strict clippy
- cloud check and strict clippy
- `cargo test -p openobserve-api-management --lib`: 300 passed
- `cargo deny check licenses`
- `cargo fmt --all`
- `git diff --check`

Build-time benchmarking is intentionally deferred for this stage.
2026-07-15 07:10:41 +00:00
Huaijin cd8610cafa refactor: extract shared and query API crates (#13199)
## Summary

- add `openobserve-api-common` for HTTP extractors and request DTOs
shared across API domain crates
- add `openobserve-api-query` and physically move the search, PromQL,
and traces handlers (about 16.4K lines)
- preserve the existing `handler::http::request::{search,promql,traces}`
paths through re-exports so routing, Swagger generation, and rate-limit
metadata remain compatible
- forward enterprise, cloud, vectorscan, and vortex features through the
new crate boundary
- avoid `#[path]` source inclusion

## Enterprise overlay

Requires openobserve/o2-enterprise#2174, which registers the two new
workspace crates in `Cargo.toml.openobserve`.

## Validation

- `cargo check -p openobserve --features mimalloc`
- enterprise check with `--no-default-features --features
enterprise,mimalloc`
- cloud check with `--no-default-features --features cloud,mimalloc`
- OSS and cloud/enterprise all-targets Clippy with `-D warnings`
- `openobserve-api-common`: 9 tests passed
- `openobserve-api-query`: 136 independent tests passed single-threaded;
the unchanged DB-dependent saved-view test was excluded because
standalone crate tests do not initialize the infra database
- `cargo fmt --all -- --check`

Build-time benchmarking is intentionally deferred until the crate-split
series is ready for a controlled `release-profiling` comparison.
2026-07-15 04:22:55 +00:00
Hengfei Yang 17dbff89b3 feat: skip file download cache for data older than configurable max age (#13201)
Design at: #13200

## What changed

Adds a max-age admission policy for the file download cache:

- New configs `ZO_DISK_CACHE_MAX_AGE_DAYS` and
`ZO_MEMORY_CACHE_MAX_AGE_DAYS` (default `0` = disabled, current behavior
unchanged).
- `queue_download()` now skips files whose `max_ts` is older than the
configured max age — they never enter the download queue; queries read
them directly from object storage (the existing cache-miss fallback).
- The `cache_latest_files` gRPC event handler applies the same filter
when collecting files, covering the batch `download_from_node` path that
writes to the cache via `file_data::set` without going through the queue
(e.g. merged files produced by compaction of old partitions).
- The check is exposed as `file_downloader::exceeds_cache_max_age(ts,
cache_type)`; `ts <= 0` (unknown timestamp) is never skipped.

## Why

`time_lru` has an eviction policy but no admission policy. With a cache
sized for the recent hot window (e.g. 3 days), a query on old data (e.g.
30 days ago):

1. Triggers gc **before** insert: the first old-file insert evicts
`max(release_size, data_size * 100)` — by default ~10% of the cache —
from the oldest hours of the *hot* window.
2. Once inserted, the old files themselves become the oldest `time_lru`
bucket and are evicted first, often within the same query — S3 download
→ disk write → immediate delete, pure wasted work with zero retention
for repeat queries.

With a max age matching the cache window, deep-history queries no longer
disturb the hot cache or waste S3 bandwidth and disk IO.

## Coverage

All query-side download paths funnel through `queue_download()` with the
file's real `max_ts` and are covered: search (parquet), tantivy index
(`.ttv`), promql/metrics, and file_list dump. Deliberately **not**
gated: compactor working downloads (`cache_remote_files` and
merge-output writes — required reads/writes, not speculative caching)
and the results/aggregations/metrics_results caches (separate concern).

## Tests

Unit tests for the age check (disabled, unknown ts, recent file, old
file); `cargo test -p openobserve-core --lib file_downloader` passes.
2026-07-15 03:45:44 +00:00
Huaijin 5f65481821 refactor: extract background jobs crate (#13189)
## Summary

- extract background scheduling code into the src/jobs workspace crate
- physically move job sources without path-based module indirection
- move file downloading, MMDB initialization signaling, and
grouped-alert delivery behind core service APIs to keep the dependency
direction one-way
- preserve the existing root job API through re-export and forward
enterprise, cloud, vectorscan, and vortex features

Companion o2-enterprise PR:
https://github.com/openobserve/o2-enterprise/pull/2173

## Validation

- cargo check -p openobserve --features mimalloc
- cargo clippy -p openobserve -p openobserve-api -p openobserve-core -p
openobserve-jobs --all-targets --features mimalloc -- -D warnings
- enterprise cargo check with the o2-enterprise overlay
- cloud cargo check and strict Clippy with the o2-enterprise overlay
- cargo fmt --all -- --check

Build-time benchmarking is intentionally deferred until the
crate-splitting series is complete.
2026-07-14 14:23:53 +00:00
b92d5765ed refactor: extract API frontend crate (#13181)
## Summary

Second step of the crate split (after #13168 which extracted
`openobserve-core`): move `src/handler` and `src/router` into a new
`openobserve-api` crate at `src/api`, so the HTTP/gRPC transport
frontend (routing, auth, extractors, OpenAPI generation) builds as its
own compilation unit.

All 155 moved source files are byte-identical moves (`git mv` only, zero
content changes). The real changes are limited to manifests and
scaffolding:

- **`src/api/src/lib.rs`** re-exports `openobserve_core::{common, job,
service}` (plus `cipher` under `enterprise`) at the crate root, so the
existing `crate::common::...` / `crate::service::...` paths inside the
moved files keep resolving without touching them.
- **`src/lib.rs`** re-exports `openobserve_api::{handler, router}`, so
external paths like `openobserve::handler::...` used by `main.rs` and
`tests/integration_test.rs` are unchanged.
- **Feature forwarding**: `enterprise` / `cloud` / `vectorscan` /
`vortex` / `profiling` on the root crate now forward to
`openobserve-api` as well.
- **`src/enterprise-stubs` → `src/enterprise`**: directory rename, plus
a new `o2_ratelimit` dependency-resolution stub (the api crate depends
on it under the `enterprise` feature; there was no stub for it before).
- `#![feature(variant_count)]` moves with its only use site
(`models/dashboards.rs`) into the api crate.
- **CI**: added `deny.toml` license exceptions for the two new AGPL-3.0
workspace crates (`openobserve-api`, `o2_ratelimit`); updated the
`ui.rs` path patched by the playwright workflows.

`src/api/Cargo.toml` is shared verbatim between OSS and enterprise
builds — only the root manifest is replaced by the enterprise overlay;
the `o2_*` deps resolve via `workspace = true` to either the stubs (OSS)
or the real crates (enterprise).

Companion PR: openobserve/o2-enterprise#2168

## Testing

- `cargo check --workspace` passes (OSS).
- Verified all moved files are 0-diff renames (`git diff -M90% --stat`).
- Verified every `crate::` reference in the moved code resolves through
the re-exports (`service`/`common`/`handler`/`job`/`router`/`cipher`),
with the single `crate::cipher` use correctly gated behind `enterprise`.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-07-14 12:40:47 +00:00
HuaijinandClaude Fable 5 81cc0f2255 refactor: extract application core crate (#13168)
## Summary

Extract the application core (`src/common`, `src/service`, `src/job`,
`src/cipher`) out of the root binary crate into a new workspace crate
`src/core` (package `openobserve-core`). The root crate keeps the binary
entrypoints and edges: `cli`, `handler`, `router`, `migration`, and
`super_cluster_queue`.

This builds on #13162 (remove service → handler dependencies), which
made the extraction possible.

> Naming note: the directory is `src/core` but the package stays
`openobserve-core` — a Cargo dependency literally named `core` shadows
Rust's built-in `core` crate and breaks the `::core::` paths emitted by
derive macros (thiserror, serde, ...).

## What moved

- `src/common`, `src/service`, `src/job`, `src/cipher` →
`src/core/src/...` (467 files moved; 385 of them byte-identical, the
rest only needed `pub(crate)` → `pub` widening and clippy fixes required
by the new crate boundary)
- `ua_regex/regexes.yaml` → `src/core/ua_regex/` (same content, consumer
moved with it)
- `src/handler/grpc/request/search/mod.rs` →
`src/core/src/service/search/grpc_server.rs` (byte-identical; old path
kept via `pub use ... as search`)
- `impl From<MetricsQueryRequest> for cluster_rpc::MetricsQueryRequest`
moved from `handler/grpc/mod.rs` into `service/promql` (orphan rule;
field-for-field identical)
- The `impl From<XError> for Response` blocks scattered across HTTP
handler files (alerts, dashboards, reports, folders, pipeline,
eval_jobs, providers, ratelimit) are consolidated into
`src/core/src/service/http.rs` with unchanged status-code mappings

## Compatibility

`src/lib.rs` re-exports the moved modules (`pub use
openobserve_core::{common, job, service}`, and `cipher` under the
`enterprise` feature), so all existing `crate::service::...` /
`openobserve::common::...` paths keep working — handlers, tests, and
downstream code need no changes.

## Enterprise dependency resolution

`openobserve-core` optionally depends on `o2_enterprise` / `o2_dex` /
`o2_openfga` / `vortex` behind features. So that the OSS repo resolves
on its own, workspace deps point at empty stub packages under
`src/enterprise-stubs/` (never compiled into default builds). Enterprise
builds replace the workspace manifest with `Cargo.toml.openobserve`,
which points these at the real crates.

⚠️ Must be merged together with openobserve/o2-enterprise#2162 (same
branch name) — merging either PR alone breaks the enterprise build.

## Feature forwarding

Root `enterprise` / `cloud` / `vectorscan` / `vortex` features forward
to the corresponding `openobserve-core` features; the core crate
forwards to `config` / `infra` / `o2_enterprise` exactly as the root
crate did before.

## Unit-test fix

The `service::sourcemaps` tests relied on the workspace root being the
test cwd (shared zip fixture via a relative path, sqlite db dir/tables
created by `init-db` from `coverage.sh`). Unit tests of a sub-crate run
with the crate dir as cwd, so they now read the fixture via
`CARGO_MANIFEST_DIR` and create the db dir + the tables they touch
themselves; `src/core/data` is cleaned between the postgres and sqlite
CI passes and gitignored, mirroring `src/infra/data`.

## Cleanup

The extracted crate's manifest is pruned to what core actually uses (45
dependency entries copied from the root crate plus a dead `profiling`
feature removed), and the stale `roaring` dependency (unused since the
tantivy result cache rewrite in #7890) is dropped from the root
manifest. All new files carry the standard AGPL header.

## Testing

- `cargo check --workspace --all-targets`, `cargo clippy -D warnings`,
and `cargo fmt --check` pass
- `service::sourcemaps` unit tests pass under `--test-threads=1` (the CI
setting; they share one db group and are not parallel-safe, same as
before)
- No logic changes anywhere: the diff is moves + visibility widening +
clippy appeasement; error-to-HTTP-response mappings verified
variant-by-variant
- e2e label kept so Playwright runs

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 09:49:48 +00:00
Huaijin 9700fd6c43 perf: parallel zstd compress (#12960)
related to https://github.com/openobserve/o2-enterprise/issues/1860

- [x] limit parallel by the target partitions


## Summary

This PR improves Flight `do_get` response throughput by executing and
encoding output partitions in parallel instead of funneling everything
through a single sequential stream/encoder path.

## Changes

- Switches Flight `do_get` from `execute_stream` to
`execute_stream_partitioned`.
- Adds per-partition encoder tasks that coalesce RecordBatches, encode
Arrow IPC, and apply ZSTD compression independently.
- Splits Flight encoding into:
  - `ChunkCoalescer` for 8192-row batch coalescing.
  - `FlightDataEncoder` for IPC/ZSTD encoding of completed chunks.
- Adds `PartitionEncoderStream` to handle per-partition batch coalescing
and encoding.
- Preserves custom Flight messages behavior:
  - early-emitted messages are sent before the first data message;
  - stats/metrics/peak-memory messages are sent after data completes.
- Uses a fresh dictionary tracker per encoded chunk so
dictionary-encoded columns remain decodable when chunks are encoded
independently.
- Cleans up stream lifecycle handling by aborting partition tasks before
clearing session resources.

## Performance

100M records
single node optimzier disable(to simulate the distribute query)

### Q1
```sql
SELECT
  trace_id,
  count(*) AS cnt,
  max(_timestamp) AS ts
FROM
  "k8s_logs"
GROUP BY
  trace_id ORDER BY cnt DESC LIMIT 100
```
12M trace_id unique value
12M records send from follower to leader
main branch: 6s 
this branch: 3s


### Q2
```sql
SELECT count(distinct request_id) FROM "k8s_logs"
```
100M request_id unique value
100M records send from follower to leader
main branch: 30s
this branch: 11s


### Q3
```sql
SELECT
  kubernetes_namespace_name,
  COUNT(DISTINCT trace_id) AS cnt
FROM
  k8s_logs
GROUP BY
  kubernetes_namespace_name ORDER BY cnt DESC
```
10 kubernetes_namespace_name unique value, 12M trace_id unique value
63M records send from follower to leader
main branch: 21s
this branch: 8.3s

### Q4
```sql
SELECT
  host,
  COUNT(DISTINCT trace_id) AS cnt
FROM
  k8s_logs
GROUP BY
  host ORDER BY cnt DESC
```
2160 host unique value, 12M trace_id unique value
99.57M records send from follower to leader
main branch: 56s
this branch: 20s
2026-07-02 06:07:47 +00:00
Huaijin ce726253f8 fix: projection for hashjoin in broadcast join (#12875) 2026-06-25 07:46:54 +00:00
Huaijin d7b9cc495c chore: use datafuson proto instead of copy (#12812) 2026-06-22 12:02:05 +00:00
Huaijin be9113c735 fix: limit prune issue (#12758) 2026-06-18 14:13:05 +00:00
Huaijin 5be5a302d3 perf: improve approx_distinct performance (#12714)
- close https://github.com/openobserve/o2-enterprise/issues/1862

## todo
- [x] fix access plan
- [x] use forked datafusion
2026-06-17 03:49:37 +00:00
Huaijin 0831badd02 perf: upgrade datafusion to 54 (#12665)
- [x] ~add sort when to many groups, we can do this, but for now do not
do this~
- [x] remove the unsafe for memory pool
- [x] add approx_distinct improve, already fork, will add in next pr
- [x] fork vortex to add cast fix, and export
`.exclude_schemes([IntDictScheme.id()])`
- [x] ~enable_physical_uncorrelated_scalar_subquery test~
2026-06-16 13:27:26 +00:00
Hengfei Yang 890771e319 perf: keep improve histogram on tantivy (#12693) 2026-06-16 10:31:25 +00:00
Huaijin f548a18de4 refactor: access plan struct improve (#12646) 2026-06-15 12:59:55 +00:00
Hengfei Yang 4c43f00036 perf: keep improve histogram on tantivy (#12640) 2026-06-13 12:29:04 +08:00
Hengfei Yang d996349aa4 feat: rewrite tantivy histogram collectors, support histogram() timezone in optimize rules (#12627)
Design at: #12620

Closes #12620
Fixes #12564

## What

Rewrites both tantivy histogram optimize-rule collectors following the
same approach as the recent `TopNCollector` /
`SingleSegmentDocIdCollector` rewrites, and adds timezone support to
both rules.

- `MultiHistogramCollector` (replaces the aggregation framework for
`SimpleMultiHistogram`)
- `SimpleHistogramCollector` (replaces
`tantivy::collector::HistogramCollector` for `SimpleHistogram`)

### Timezone support (#12564)

`histogram(ts, interval, tz)` rewrites to `date_bin(interval,
to_timestamp_micros(_timestamp + offset), origin)`; the optimizer's
`get_column_name` hit the `BinaryExpr` and silently skipped both rules.
Now:
- the visitors extract the fixed offset from that shape
(`get_timestamp_offset`), so the rules fire with a timezone
- `IndexOptimizeMode::SimpleHistogram` / `SimpleMultiHistogram` carry a
`ts_offset` field (no proto change — histogram modes never cross gRPC,
they're re-derived per node)
- bucket edges are computed in shifted wall-clock space and the
collectors bucket on `_timestamp + ts_offset`, so emitted keys match
`date_bin` exactly when merging with non-tantivy partials

## Testing

- New collector unit tests: dense vs sparse equality, ts_offset
shifting, bounds filtering, missing column / missing breakdown docs,
per-bucket truncation with tie-breaks
- Visitor tests now include real-DataFusion-plan timezone cases
(`'+08:00'` simple, `'-05:30'` multi) asserting the extracted shifted
bounds and offset
- `cargo test -p config` (1936 passed), plus `index_optimizer` /
`search::tantivy` / `tantivy_optimize_exec` suites in the main crate;
clippy clean

- Low cardinality: fast `20%` than main
```
histogram(_timestamp, '1h') AS ts, count(*) FROM default GROUP BY ts ORDER BY ts ASC
```
- Low cardinality: fast `30%` than main
```
histgoram(_timestamp, '1h') AS ts, breakdown, count(*) FROM default GROUP BY ts, breakdown ORDER BY ts ASC
```
- High cardinality: faster `5x` than main
```
histgoram(_timestamp, '1h') AS ts, breakdown, count(*) FROM default GROUP BY ts, breakdown ORDER BY ts ASC
```
2026-06-12 10:34:12 +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
Harsh Mahajan c260d9162d fix: changing vendored ui-swagger (#12506) 2026-06-08 10:02:20 +00:00
Hengfei Yang 3e865a3e6a ci: update rust (#12394) 2026-06-02 03:58:01 +00:00
Don Kendall 75df625e06 fix: clear Security audit (lettre CVE, rustls-pemfile migration, core2 ignore) (#11832) 2026-05-31 08:55:53 +08:00
Hengfei Yang 87e7441580 perf: add get_ranges for local cache (#12194)
impl #12195

- [x] perf: add get_ranges for local cache
- [x] perf: add compact fast 
- [x] feat: add CLI reset index-updated-at
- [x] ci: bump tantivy version to 2.6
2026-05-25 08:26:44 +00:00
Hengfei Yang 45c8fb6838 fix: object store bulk delete issue (#12116)
fixed #12105
2026-05-22 10:38:51 +00:00
Hengfei Yang f2cd026f52 fix: file list migration url (#11883) 2026-05-18 06:33:42 +00:00
Harsh Mahajan 9f00716db0 fix: security_audit upgrade (#11861) 2026-05-15 11:56:44 +00:00
Hengfei Yang 17a4b4dc23 fix: reset file-list-jobs with stream (#11854)
Usage:
```
  openobserve reset -c file-list-jobs -t 1700000000000000
  openobserve reset -c file-list-jobs -s default/logs/app
  openobserve reset -c file-list-jobs -t 1700000000000000 -s default/logs/app
```
2026-05-15 10:24:25 +00:00
Hengfei Yang 75bda12998 chore: change default max size to 2GB for compactor (#11629) 2026-05-06 23:07:25 +08:00
dependabot[bot] e6c164ba07 chore(deps): bump rand from 0.10.0 to 0.10.1 (#11260) 2026-04-23 08:23:02 +08:00
Hengfei Yang 77d376efa2 fix: improve real ip logic (#11378) 2026-04-22 22:56:05 +08:00
Huaijin 493dac7433 chore: update datafusion to 53.1.0 (#11310) 2026-04-17 12:03:02 +00:00
Hengfei Yang 69fd00f0c5 fix: implement AES-256-SIV encryption and decryption utilities (#11286) 2026-04-16 19:15:56 +08:00
Hengfei Yang b266560838 feat: support custom AI tools (#11270) 2026-04-15 20:11:35 +08:00
漂流 fbf7283ffc chore: use std instead of once_cell (#11081) 2026-04-06 16:27:16 +08:00
HuaijinandHengfei Yang ada8b3763f chore: upgrade datafusion to 53 (#11093)
- [x] check if still need `CoalesceBatchesExec`
- [x] check object_store upgrade

---------

Co-authored-by: Hengfei Yang <hengfei.yang@gmail.com>
2026-04-06 06:06:51 +00:00
udev 9525aad6fe fix: grpc use native/webpki trust store (#11083) 2026-03-31 11:28:53 +05:30
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
Huaijin 2923938b95 chore: upgrade datafusion to 52.4.0 (#10995) 2026-03-23 16:47:21 +08:00
Huaijin b3a9b3c14f perf: preserve fetch when rewriter FilterExec (#10971) 2026-03-21 20:15:35 +08:00
Hengfei Yang b50de58a97 refactor: update schema field naming and enhance metadata extraction methods (#10945) 2026-03-18 09:01:31 +08:00
Hengfei Yang 53668c8c1a chore: update dependencies in Cargo files (#10929) 2026-03-17 11:14:14 +05:30
dependabot[bot] 283a5f3041 chore(deps): bump lz4_flex from 0.11.5 to 0.11.6 (#10928) 2026-03-17 09:08:02 +08:00
Hengfei Yang dafa382abb fix: handle serde_json arbitrary_precision number in VRL parse_json (#10920) 2026-03-16 21:07:35 +08:00
Hengfei Yang 5d4a909813 fix: create trigger schema (#10896) 2026-03-13 22:36:41 +08:00