Skip to content

feat: rfc0018.6 green — preserve out-of-range severity + error.type - #269

Merged
jensholdgaard merged 2 commits into
mainfrom
feat/rfc0018-green-severity
Jun 20, 2026
Merged

feat: rfc0018.6 green — preserve out-of-range severity + error.type#269
jensholdgaard merged 2 commits into
mainfrom
feat/rfc0018-green-severity

Conversation

@jensholdgaard

@jensholdgaard jensholdgaard commented Jun 20, 2026

Copy link
Copy Markdown
Owner

RFC 0018 green (4/6) — preserve out-of-range severity + error.type (RFC0018.6)

Stacked on #268 (base = feat/rfc0018-green-scope-fields); merge #268 first. Diff shows only the severity changes.

Faithful-witness fix (RFC 0018 §3.5 / §3.0): the receiver clamped any out-of-0..=24 SeverityNumber to 0 (severity_to_u8), silently inverting a monotonic scale (25 = most-severe → UNSPECIFIED). Now it preserves the wire value (u8 0..=255); only the non-u8-storable extremes (negative, >255) narrow to 0 (storage invariant).

The metric — OTel convention, not a bespoke counter

Per the maintainer steer ("doesn't weaver provide means? check the OTel docs"), the anomaly is surfaced via the "recording errors on metrics" convention: the standard error.type attribute on the existing ourios.ingest.records counter (error.type=severity_out_of_range on out-of-range records; absent on in-range) — one counter, low-cardinality reason, no new metric name. error.type is upstream OTel, used as a documented code constant and kept out of the Ourios weaver registry (it's not ours to vendor). RFC 0018 §3.5/§5/§6 amended accordingly.

Verification (RFC0018.6, three arms)

  • Preserve + non-u8 — the overturned rfc0003_9 contract test now asserts preservation (25→25, 200→200, 1000→0, -5→0); a §6.2 contract change the RFC authorizes.
  • error.type metricourios-ingester/tests/rfc0018_otlp_compliance.rs (in-memory meter): a 4-record/2-out-of-range batch splits 2 (no error.type) + 2 (error.type=severity_out_of_range).
  • Monotonicityourios-querier/tests/rfc0018_severity.rs: severity >= error matches the preserved 25/200 (25 >= 17), excludes INFO(9).
  • clippy --all-targets, fmt, mdbook, semconv no-diff all clean.

RFC 0018: 4 of 6 §5 scenarios green (.1/.2/.4/.6). Remaining: .3 (retryable errors), .5 (non-finite doubles).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Severity value anomalies in logs are now tracked with error classification in metrics for improved observability.
  • Bug Fixes

    • Enhanced handling of out-of-range severity values during log ingestion.
  • Documentation

    • Updated compliance specifications and testing scenarios for severity number handling.

@jensholdgaard
jensholdgaard requested a review from Copilot June 20, 2026 16:16
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 981d1876-1e06-4b5e-9fa6-5bef54dabb59

📥 Commits

Reviewing files that changed from the base of the PR and between 8fda0ab and 4b86a28.

📒 Files selected for processing (8)
  • crates/ourios-ingester/src/metrics.rs
  • crates/ourios-ingester/src/receiver/materialize.rs
  • crates/ourios-ingester/src/receiver/pipeline.rs
  • crates/ourios-ingester/tests/perf_metrics.rs
  • crates/ourios-ingester/tests/rfc0003_9_edge_otlp_fields.rs
  • crates/ourios-ingester/tests/rfc0018_otlp_compliance.rs
  • crates/ourios-querier/tests/rfc0018_severity.rs
  • docs/rfcs/0018-otlp-log-spec-compliance.md

📝 Walkthrough

Walkthrough

RFC0018.6 changes out-of-range OTLP severity_number handling: values that fit in u8 are now preserved instead of clamped to 0. A new severity_is_out_of_range helper classifies stored values above 24. IngestMetrics::record_batch gains a severity_out_of_range parameter to split the ourios.ingest.records counter by error.type. The pipeline wires the count through, tests are updated or newly implemented, and the RFC doc is revised.

Changes

RFC0018.6 — out-of-range severity preservation and OTel error attribution

Layer / File(s) Summary
severity_to_u8 preservation and severity_is_out_of_range classifier
crates/ourios-ingester/src/receiver/materialize.rs
severity_to_u8 now keeps representable out-of-range u8 values instead of clamping to 0; only negative or >255 wire values narrow to 0. New pub(crate) severity_is_out_of_range(u8) -> bool returns true for stored values above 24.
record_batch counter split by error.type
crates/ourios-ingester/src/metrics.rs
record_batch gains a severity_out_of_range: usize parameter; in-range records are added to ourios.ingest.records without an attribute, out-of-range records are added with error.type = "severity_out_of_range". Two module-level constants (ERROR_TYPE, SEVERITY_OUT_OF_RANGE) are added.
Pipeline counts out-of-range records and forwards to record_batch
crates/ourios-ingester/src/receiver/pipeline.rs, crates/ourios-ingester/tests/perf_metrics.rs
On successful ack, the pipeline filters ingested records via severity_is_out_of_range and counts matches, passing the result as the new argument to self.metrics.record_batch. The perf_metrics test is updated to pass 0 for the new parameter.
Tests for preservation, metrics assertions, querier monotonicity, and RFC doc
crates/ourios-ingester/tests/rfc0003_9_edge_otlp_fields.rs, crates/ourios-ingester/tests/rfc0018_otlp_compliance.rs, crates/ourios-querier/tests/rfc0018_severity.rs, docs/rfcs/0018-otlp-log-spec-compliance.md
rfc0003_9 test is updated to expect preservation for u8-storable inputs. The formerly-ignored RFC0018.6 test is implemented: it materializes records, asserts stored severity_number, then records a batch and asserts the counter split on error.type. A querier integration test validates monotonic severity >= error queries over preserved out-of-range values. The RFC doc updates §3.5 and scenario RFC0018.6 to reflect the new reporting contract.

Sequence Diagram(s)

sequenceDiagram
    participant Client as OTLP Client
    participant materialize as materialize_record / severity_to_u8
    participant pipeline as IngestPipeline
    participant metrics as IngestMetrics
    participant counter as ourios.ingest.records

    Client->>materialize: LogRecord { severity_number: i32 }
    materialize-->>pipeline: MinedRecord { severity_number: u8 (preserved or 0) }
    pipeline->>pipeline: count records where severity_is_out_of_range(severity_number)
    pipeline->>metrics: record_batch(total, out_of_range_count, elapsed)
    metrics->>counter: add(in_range_count) — no error.type
    metrics->>counter: add(out_of_range_count) — error.type = "severity_out_of_range"
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • jensholdgaard/ourios#132: Directly precedes this PR — it introduced the severity_number clamping in materialize.rs that this PR replaces with preservation logic.
  • jensholdgaard/ourios#247: Introduced the IngestMetrics::record_batch method that this PR extends with the severity_out_of_range parameter and error attribution split.
  • jensholdgaard/ourios#266: Added the ignored RFC0018.6 test stub in rfc0018_otlp_compliance.rs that this PR replaces with a fully implemented assertion.

Poem

🐇 A severity out of range, you say?
No more shall we clamp it away!
We preserve the u8, tag the metric with flair,
error.type set with OpenTelemetry care.
The querier still queries, monotone and true —
What a hoppy RFC we just pushed through! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: preserving out-of-range severity values and adding error.type attribution, which are the core features implemented across the changeset.
Description check ✅ Passed The description is comprehensive and well-structured, covering the RFC context, implementation rationale, metric design choice, and verification approach. All required template sections are addressed with substantive content.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rfc0018-green-severity

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

Updates RFC 0018.6 behavior so the receiver preserves out-of-range-but-u8-storable OTLP SeverityNumber values (25–255) instead of clamping them to 0, and surfaces the anomaly via the existing ourios.ingest.records counter using the standard error.type attribute.

Changes:

  • Preserve SeverityNumber wire values in severity_to_u8 for the full u8 range; only non-u8 extremes narrow to 0.
  • Record out-of-range severity occurrences by splitting ourios.ingest.records datapoints using error.type=severity_out_of_range.
  • Add/adjust RFC acceptance tests to cover severity preservation, metric attribution, and querier monotonic severity comparisons.

Reviewed changes

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

Show a summary per file
File Description
docs/rfcs/0018-otlp-log-spec-compliance.md Updates RFC text for severity preservation and error.type metric attribution.
crates/ourios-querier/tests/rfc0018_severity.rs New test ensuring severity >= error matches preserved out-of-range severities.
crates/ourios-ingester/tests/rfc0018_otlp_compliance.rs Implements RFC0018.6 receiver + metrics test logic (and updates imports/helpers).
crates/ourios-ingester/tests/rfc0003_9_edge_otlp_fields.rs Updates RFC0003.9 contract test to assert preservation of 25/200 and narrowing of non-u8 extremes.
crates/ourios-ingester/tests/perf_metrics.rs Updates perf-metrics test for new IngestMetrics::record_batch signature.
crates/ourios-ingester/src/receiver/pipeline.rs Computes out-of-range severity count per batch and passes it into ingest metrics recording.
crates/ourios-ingester/src/receiver/materialize.rs Changes severity narrowing to preserve u8 wire values and adds severity_is_out_of_range.
crates/ourios-ingester/src/receiver.rs Re-exports severity_is_out_of_range from receiver.
crates/ourios-ingester/src/metrics.rs Extends record_batch to split ourios.ingest.records by standard error.type attribute.

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

Comment thread crates/ourios-ingester/tests/rfc0018_otlp_compliance.rs Outdated
Comment thread crates/ourios-ingester/src/receiver.rs Outdated

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 8 out of 8 changed files in this pull request and generated 1 comment.

Comment on lines 9 to +13
//! remain `#[ignore]`d stubs until those receiver changes land (`green`).
//!
//! See `docs/rfcs/0018-otlp-log-spec-compliance.md` §5/§6.

use std::time::Duration;
@jensholdgaard
jensholdgaard changed the base branch from feat/rfc0018-green-scope-fields to main June 20, 2026 17:51
jensholdgaard and others added 2 commits June 20, 2026 19:52
… ingest counter

Faithful-witness fix (RFC 0018 §3.5/§3.0): the receiver clamped any
out-of-`0..=24` SeverityNumber to 0 (`severity_to_u8`), silently inverting
a monotonic scale (25 = most-severe → UNSPECIFIED). Preserve it instead.

- severity_to_u8 now preserves the wire value (u8 0..=255); only the
  non-u8-storable extremes (negative, >255) narrow to 0 (storage invariant).
- Surface the anomaly via the OTel "recording errors on metrics" convention,
  per maintainer steer: NOT a bespoke counter, but the standard `error.type`
  attribute on the existing `ourios.ingest.records` counter
  (error.type=severity_out_of_range on out-of-range records; absent on
  in-range). error.type is upstream OTel — used as a code constant, kept OUT
  of the Ourios weaver registry.
- The pipeline tags out-of-range records post-materialise (severity_is_out_of_range
  on the preserved u8); the rare non-u8→0 extremes aren't separately
  attributed (accepted §3.5 limitation).

Greens RFC0018.6 across three arms: preserve + non-u8 (the overturned
rfc0003_9 contract test, now asserting preservation), error.type metric
(ingester rfc0018, in-memory meter), and monotonicity (querier
rfc0018_severity: `severity >= error` matches a preserved 25). RFC 0018
§3.5/§5/§6 amended from the bespoke metric to the error.type pattern.

RFC 0018: 4 of 6 §5 scenarios green (.1/.2/.4/.6). Remaining: .3, .5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot review:
- severity_is_out_of_range is crate-internal (only the pipeline calls it);
  make it pub(crate) and drop the public re-export — call it via
  super::materialize::. Keeps it off the public receiver API surface.
- remove the orphaned RFC0018.6 scenario doc (old ingest.severity_out_of_range
  wording) the stub→green rewrite left above the ingest_records_sum helper;
  the accurate scenario doc sits on the test fn.

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 8 out of 8 changed files in this pull request and generated no new comments.

@jensholdgaard
jensholdgaard merged commit 5065763 into main Jun 20, 2026
22 checks passed
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