feat(ingester): ingest + sink metrics for perf observability - #247
Conversation
The ingest front (OTLP → WAL → handoff) and the RFC 0014 record sink
emitted no metrics, so a performance run couldn't see ingest throughput,
the WAL-before-ack latency, or flush behaviour. Fill those blind spots
with 8 new instruments (+1 attribute), authored in the weaver registry
and regenerated into `ourios-semconv` (the no-diff CI gate stays green;
names verified against the OTel metric-naming spec):
ourios.ingest.records counter {record}
ourios.ingest.batches counter {batch}
ourios.wal.append.duration histogram s
ourios.sink.flush.duration histogram s [trigger]
ourios.sink.flush.records counter {record} [trigger]
ourios.sink.flush.errors counter {error}
ourios.sink.derive.errors counter {error}
ourios.sink.buffer.usage updowncounter By
+ attribute ourios.sink.flush.trigger (size|age|rotation|ceiling)
`IngestMetrics` records throughput + the durable-commit latency on each
acked batch in `IngestPipeline::ingest`. `SinkMetrics` records flush
duration/rows by trigger, flush/derive errors, and buffer occupancy in
`ParquetRecordSink`. Both resolve through the global meter (RFC 0001 §6.8
API/SDK split) — no-op when no provider is installed. System-aggregate
(no tenant/service attributes) so a perf run reads throughput directly;
`flush.trigger` is the one added dimension — it shows whether flushes are
healthy (size) or memory-pressured (ceiling), low cardinality, mirroring
`compaction.result`.
Verified: weaver registry check; idempotent regen; a new in-memory-export
integration test (`tests/perf_metrics.rs`) asserting the names, the
trigger split, and the recorded values; fmt/clippy clean; ingester +
server suites green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 48 minutes and 59 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 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds OpenTelemetry metrics instrumentation to the ingester write path. New ChangesIngest and Sink OTel Metrics
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
Adds end-to-end performance observability for the ingester ingest front (OTLP → WAL durable commit → miner handoff) and the RFC 0014 Parquet record sink by defining new semantic-convention metrics/attributes and wiring them into the ingest and sink hot paths, with an in-memory-exporter integration test to validate the exported stream.
Changes:
- Define 8 new metrics and 1 new attribute (
ourios.sink.flush.trigger) insemconv/registry/*and regenerateourios-semconvconstants. - Instrument
IngestPipeline::ingestwith throughput counters and a WAL-before-ack latency histogram viaIngestMetrics. - Instrument
ParquetRecordSinkflush behavior (duration/records by trigger), error counters, and buffer usage viaSinkMetrics, plus add a dedicated integration test asserting exported names and basic aggregates.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| semconv/registry/metrics.yaml | Adds ingest/WAL and sink metric definitions (names, instruments, units, and required trigger attribute where applicable). |
| semconv/registry/attributes.yaml | Adds ourios.sink.flush.trigger enum attribute with `size |
| crates/ourios-semconv/src/lib.rs | Regenerates semconv constants for new metric names and the new attribute key. |
| crates/ourios-ingester/src/metrics.rs | Introduces IngestMetrics and SinkMetrics using the global meter, with seeding for attribute-free instruments. |
| crates/ourios-ingester/src/receiver/pipeline.rs | Records per-acked-batch throughput and durable-commit latency in the ingest pipeline. |
| crates/ourios-ingester/src/record_sink.rs | Records sink flush metrics (including trigger), error counters, and buffer usage deltas during emit/flush paths. |
| crates/ourios-ingester/tests/perf_metrics.rs | New integration test using in-memory metrics exporter to validate names, trigger split, and basic totals/counts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
`cargo clippy --all-targets` flagged `|dp| dp.value()` / `|dp| dp.count()` in tests/perf_metrics.rs (redundant_closure_for_method_calls). Use the method references, matching the same pattern already used in the file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Why
The ingest front (OTLP → WAL → miner handoff) and the RFC 0014 record sink emitted no metrics, so a performance run can't see ingest throughput, the WAL-before-ack latency, or flush behaviour. This fills those blind spots ahead of a perf test (
CLAUDE.md§6.3 — "every subsystem exposes metrics").What
8 new instruments + 1 attribute, authored in
semconv/registry/and regenerated intoourios-semconv(thesemconvno-diff CI gate stays green; names verified against the OTel metric-naming spec — no units in names, correct pluralization, UpDownCounter not pluralized,usagefor buffer-vs-ceiling):ourios.ingest.records{record}ourios.ingest.batches{batch}ourios.wal.append.durationsourios.sink.flush.durations[trigger]ourios.sink.flush.records{record}[trigger]ourios.sink.flush.errors{error}ourios.sink.derive.errors{error}ourios.sink.buffer.usageBy+ ourios.sink.flush.trigger(size | age | rotation | ceiling).IngestMetrics— records throughput + the durable-commit latency (group-commit window + fsync) on each acked batch inIngestPipeline::ingest.SinkMetrics— records flush duration/rows bytrigger, flush/derive errors, and buffer occupancy inParquetRecordSink.Design notes
tenant/serviceattributes) so a perf run reads total throughput directly; tenant/transport are documented opt-in follow-ons (high cardinality).flush.triggeris the one added dimension: it shows whether flushes are healthy (sizeright-sizing) or memory-pressured (ceiling). Low cardinality, mirrors the existingcompaction.resultpattern.wal.iobytes counter — the houseioconvention carries a read/write direction (ourios.io.direction), but WAL append is write-only; byte-rate is derivable, andwal.append.durationis the headline WAL signal.Tests
tests/perf_metrics.rs— drives the instruments through an in-memory exporter and asserts the registry names, thetriggersplit (size=5, rotation=3, age=0), the counter/up-down totals, and the histogram's flush count.No invariant (§3) is altered — this is pure additive observability per §6.3.
🤖 Generated with Claude Code
Summary by CodeRabbit