Skip to content

feat(server): querier OTel metrics + flip RFC 0016 green (rfc0016 .6) - #285

Merged
jensholdgaard merged 4 commits into
mainfrom
rfc0016-green-metrics
Jun 22, 2026
Merged

feat(server): querier OTel metrics + flip RFC 0016 green (rfc0016 .6)#285
jensholdgaard merged 4 commits into
mainfrom
rfc0016-green-metrics

Conversation

@jensholdgaard

@jensholdgaard jensholdgaard commented Jun 22, 2026

Copy link
Copy Markdown
Owner

What

RFC 0016 green slice 3 (final): emit the querier role's OpenTelemetry metrics (RFC0016.6), the last red arm — this flips RFC 0016 → green (7/7 §5). Slices 1 (#283, handler) and 2 (#284, role env-gating + compose) preceded.

OTel design (consulted the OpenTelemetry docs)

The OTel naming spec is explicit: record raw count components, derive ratios/utilization in the backend (the *.usage + state pattern; *.utilization is a derived/optional presentation metric). So instead of a pre-computed "pruning ratio" histogram:

  • ourios.query.duration — histogram, unit s (the {operation}.duration convention), tagged by ourios.query.kind (logs | drift). A failed query carries the upstream error.type attribute on this same metric (the "recording errors on metrics" convention — no bespoke error metric).
  • ourios.query.row_groups — counter, unit {row_group}, split by ourios.query.row_group.state (scanned | pruned). The two states partition the candidate row groups, so the B1 pruned fraction derives in the backend as pruned / (scanned + pruned).

Flagging for OTel review: the RFC §5 wording said "pruning-ratio metric"; I realized it as raw scanned/pruned counts per the OTel usage/state convention (ratios derived, not pre-computed). If you'd prefer a literal *.utilization gauge as well, happy to add — wanted the spec-correct base metric first.

New names flow through the semconv registry (semconv/registry/{metrics,attributes}.yaml) + weaver (regenerated ourios-semconv). Recorded in the server handler around run_query/run_drift, built against the global meter (RFC 0001 §6.8).

Tests

  • RFC0016.6 in its own integration binary (own process — it installs a process-global in-memory MeterProvider, single-threaded, mirroring ourios-ingester's perf_metrics): a multi-hour corpus where each file holds a distinct template_id; a selective template_id == 1 query prunes the rest; asserts the response's row_groups_pruned > 0 and the exported metric stream (duration histogram count == 1; the pruned-state counter == the response's pruned count).
  • Hardened RFC0016.5's disabled-role case (was intermittently failing locally): it now confirms no listener binds and reaps the process, rather than blind-waiting then asserting a clean SIGTERM exit — a compactor-only server prints no readiness line, so the wait raced signal-handler setup. Graceful shutdown stays asserted in the enabled case, which waits for the printed address first (like rfc0003_16).
  • Local gate green: cargo fmt --all --check, cargo clippy -p ourios-server -p ourios-semconv --all-targets --all-features -- -D warnings, cargo test -p ourios-server -p ourios-semconv, weaver registry check, regenerated ourios-semconv is in sync, mdbook build. .5/.7 ran 4× clean.

Invariants / hazards

Observability (§6.3): the querier is now self-observable. New metric/attribute names went through the weaver registry (no hand-written flat names). No hot-path or on-disk-format change; multi-tenancy and the H6 boundary are unchanged from #283/#284.

RFC 0016 status

green — all seven §5 scenarios pass. gRPC and authn/z beyond tenant-scoping remain deferred (§7).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added OpenTelemetry metrics for query observability, including query duration histogram and row-group scanning/pruning counters tagged by query kind
    • Query metrics are now tracked and exportable for monitoring query performance and pruning effectiveness
  • Documentation

    • Updated RFC status reflecting completed query-serving endpoint implementation and metrics observability
  • Tests

    • Added integration test validating query metrics emission and row-group pruning observability

Emit the querier role's OpenTelemetry metrics (RFC 0016 §3.6), filling the
last red arm (RFC0016.6) and flipping RFC 0016 to `green` (7/7 §5).

Per the OpenTelemetry usage/state convention (confirmed via the OTel docs:
record raw counts, derive ratios in the backend), the pruning signal is
emitted as raw scanned-vs-pruned row-group counts rather than a pre-computed
ratio histogram:

- `ourios.query.duration` (histogram, `s`) tagged by `ourios.query.kind`
  (logs | drift), and with the upstream `error.type` attribute on a failed
  query (the "recording errors on metrics" convention — no bespoke error
  metric).
- `ourios.query.row_groups` (counter, `{row_group}`) split by
  `ourios.query.row_group.state` (scanned | pruned). The two states partition
  the candidate row groups, so the B1 pruned fraction derives in the backend
  as `pruned / (scanned + pruned)`.

New names flow through the semconv registry + weaver (regenerated
ourios-semconv). Recorded in the server handler around run_query / run_drift,
built against the global meter (RFC 0001 §6.8).

RFC0016.6 lives in its own integration binary (its own process) since it
installs a process-global in-memory MeterProvider: a multi-hour corpus where
each file holds a distinct template_id, a selective `template_id ==` query
prunes the rest, and the test asserts both the response's row_groups_pruned
and the exported metric stream (the pruned-state counter == the response).

Also hardens RFC0016.5's disabled-role case: it now just confirms no listener
binds and reaps the process, rather than blind-waiting then asserting a clean
SIGTERM exit (a compactor-only server prints no readiness line, so the wait
raced signal-handler setup — graceful shutdown stays asserted in the enabled
case, which waits for the printed address first).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jensholdgaard
jensholdgaard requested a review from Copilot June 22, 2026 16:02
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jensholdgaard, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 28 minutes and 3 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 61e66a38-37fc-4450-8984-aa46ec7c2a0f

📥 Commits

Reviewing files that changed from the base of the PR and between 7dab2da and b08d072.

📒 Files selected for processing (2)
  • crates/ourios-server/src/querier.rs
  • crates/ourios-server/tests/rfc0016_5_7_served_querier.rs
📝 Walkthrough

Walkthrough

Implements RFC0016.6 observability by adding two OpenTelemetry metrics—a query-duration histogram and a row-group scanned/pruned counter—to the ourios-server querier handler. New semconv constants and YAML registry definitions back these metrics. An in-memory integration test validates both the HTTP response statistics and exported OTel metric values. The RFC0016 document status advances to green.

Changes

RFC0016.6 Query Observability Metrics

Layer / File(s) Summary
Semconv constants and registry definitions
semconv/registry/attributes.yaml, semconv/registry/metrics.yaml, crates/ourios-semconv/src/lib.rs
Registers ourios.query.kind and ourios.query.row_group.state attribute groups plus ourios.query.duration (histogram) and ourios.query.row_groups (counter) metric definitions in YAML, and exposes matching pub const string constants in the generated crate.
QuerierMetrics instruments and handler wiring
crates/ourios-server/Cargo.toml, crates/ourios-server/src/querier.rs
Adds opentelemetry and ourios-semconv dependencies; introduces QuerierMetrics holding a duration histogram and row-group counter (with pre-seeded state series); extends QuerierState; wires construction in router(); instruments handle_query with Instant-based elapsed recording and query_error_type tagging on failure.
RFC0016.6 integration test and test isolation fix
crates/ourios-server/Cargo.toml, crates/ourios-server/tests/rfc0016_6_query_metrics.rs, crates/ourios-server/tests/rfc0016_5_7_served_querier.rs, crates/ourios-server/tests/rfc0016_query_endpoint.rs
Adds opentelemetry_sdk testing dev-dependencies; implements rfc0016_6_pruning_is_observable verifying response pruning stats and exported OTel metric values; switches the RFC0016.5 disabled-process teardown from terminate_and_assert_clean to drop to avoid a readiness-signal race; replaces the old scaffold with an explanatory comment.
RFC0016 status update to green
docs/rfcs/0016-query-serving-endpoint.md
Changes front-matter status from red to green and inserts a status note enumerating passing scenarios, pruning metric conventions, and deferred items.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • jensholdgaard/ourios#88: Extracts row_groups_pruned/row_groups_scanned statistics from the DataFusion executed plan — the raw counts that this PR now surfaces via the HTTP response and exports as ourios.query.row_groups OTel counter.
  • jensholdgaard/ourios#105: Establishes the weaver-forge generated ourios-semconv crate and constants-generation pipeline that this PR extends with four new OURIOS_QUERY_* constants.
  • jensholdgaard/ourios#283: Modifies the same crates/ourios-server/src/querier.rs query execution handler that this PR further extends to record OTel duration and row-group metrics.

Poem

🐇 Hop, hop — a histogram blooms today,
Row groups pruned and scanned in metered array.
The querier glows green, its RFC complete,
Duration recorded, each query neat.
With semconv constants and counters aglow,
This bunny now watches the telemetry flow! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: implementing querier OTel metrics for RFC 0016 slice 6 and marking RFC 0016 as complete (green).
Description check ✅ Passed The description covers the PR's purpose, design rationale, testing strategy, and validation approach. However, the checklist section shows all items unchecked, which may indicate incomplete verification or a draft state.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rfc0016-green-metrics

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds OpenTelemetry metrics for the querier role (RFC 0016 §3.6), updates semantic-convention registry + generated constants, and flips RFC 0016 to green by replacing the last red-gate stub with an end-to-end metrics integration test.

Changes:

  • Define and emit ourios.query.duration (histogram) and ourios.query.row_groups (counter split by scanned/pruned) from the querier handler.
  • Extend semconv registry (metrics + attributes) and regenerate ourios-semconv constants accordingly.
  • Add a dedicated RFC0016.6 integration test binary that installs a process-global in-memory MeterProvider and asserts exported metric data; adjust RFC0016.5 served-binary test to avoid flaky shutdown sequencing.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
semconv/registry/metrics.yaml Registers the two new querier metrics and required attributes/units.
semconv/registry/attributes.yaml Registers ourios.query.kind and ourios.query.row_group.state attribute enums.
docs/rfcs/0016-query-serving-endpoint.md Marks RFC 0016 as green and documents the final metrics slice outcome.
crates/ourios-server/tests/rfc0016_query_endpoint.rs Removes the RFC0016.6 ignored stub and points to the new binary test.
crates/ourios-server/tests/rfc0016_6_query_metrics.rs New integration test validating pruning stats + exported OTel metric stream.
crates/ourios-server/tests/rfc0016_5_7_served_querier.rs Updates disabled-role cleanup logic to avoid readiness/shutdown races.
crates/ourios-server/src/querier.rs Implements querier OTel instruments and records success/error measurements.
crates/ourios-server/Cargo.toml Adds OTel metrics API + semconv deps; adds dev-deps for in-memory exporter test.
crates/ourios-semconv/src/lib.rs Regenerated constants for new metric and attribute keys.
Cargo.lock Locks new dependencies (opentelemetry, opentelemetry_sdk, ourios-semconv).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ourios-server/tests/rfc0016_5_7_served_querier.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ourios-server/tests/rfc0016_5_7_served_querier.rs`:
- Around line 156-160: The `drop(disabled)` call only sends an asynchronous kill
signal without waiting for the process to actually exit, which can cause race
conditions when the enabled-phase process spawns immediately after. Instead of
just dropping the `disabled` variable, explicitly wait for the process to finish
exiting by calling `.wait()` on it (or using `timeout` as done elsewhere in the
test) before the enabled process is spawned at line 163, ensuring deterministic
test execution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7857a0c3-eed3-4373-b43c-33a1254ee29c

📥 Commits

Reviewing files that changed from the base of the PR and between c788f9f and 7dab2da.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • crates/ourios-semconv/src/lib.rs
  • crates/ourios-server/Cargo.toml
  • crates/ourios-server/src/querier.rs
  • crates/ourios-server/tests/rfc0016_5_7_served_querier.rs
  • crates/ourios-server/tests/rfc0016_6_query_metrics.rs
  • crates/ourios-server/tests/rfc0016_query_endpoint.rs
  • docs/rfcs/0016-query-serving-endpoint.md
  • semconv/registry/attributes.yaml
  • semconv/registry/metrics.yaml

Comment thread crates/ourios-server/tests/rfc0016_5_7_served_querier.rs Outdated
#285)

Replace `drop(disabled)` with `disabled.kill().await` (SIGKILL + wait) in
RFC0016.5: `kill_on_drop` only fires a best-effort, un-awaited signal, so the
compactor-only process could linger while the enabled-phase process spawns —
a CI flake. `Child::kill` reaps it deterministically first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Comment thread crates/ourios-server/src/querier.rs Outdated
The `ourios.query.row_groups` seeding is not attribute-free (the `state`
attribute is required); reword to say it seeds once per state value, rather
than the ingester's single attribute-free `add(0, &[])`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.

Comment thread crates/ourios-server/src/querier.rs
Comment thread crates/ourios-server/tests/rfc0016_5_7_served_querier.rs
@jensholdgaard
jensholdgaard merged commit 699bfb4 into main Jun 22, 2026
21 checks passed
@jensholdgaard
jensholdgaard deleted the rfc0016-green-metrics branch June 22, 2026 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants