Skip to content

feat(ingester): OTLP wire-decode layer + RFC0003.5 (protobuf equivalence) - #129

Merged
jensholdgaard merged 1 commit into
mainfrom
feat/otlp-receiver-wire-decode
Jun 6, 2026
Merged

feat(ingester): OTLP wire-decode layer + RFC0003.5 (protobuf equivalence)#129
jensholdgaard merged 1 commit into
mainfrom
feat/otlp-receiver-wire-decode

Conversation

@jensholdgaard

Copy link
Copy Markdown
Owner

What

First green slice of the OTLP receiver (RFC 0003 §6.2) — the transport-agnostic wire-decode layer — flipping RFC0003.5 live. Follows the red gate (#128) and the maintainer decisions: start with wire decode, grow the API incrementally.

Changes

  • receiver::decode::decode_protobuf — decodes the ExportLogsServiceRequest payload that both the gRPC and HTTP application/x-protobuf transports carry (one shared decoder), via prost. A hand-rolled DecodeError (no thiserror) wraps the prost failure with a source() chain; a future transport handler maps it to the controlled error RFC0003.11 requires — never a panic.
  • Deps: opentelemetry-proto (same version + features the workspace already pins) and prost. No tonic/axum yet — the live listeners are a later transport slice, so decode is specified + tested at the boundary the transports share.

RFC0003.5 (now live)

A proptest strategy over the OTLP proto value space (scalar + one-level nested array/kvlist AnyValues; multi-resource/scope/record requests) asserts the decoder is:

  • faithfuldecode_protobuf(req.encode_to_vec()) == req;
  • transport-agnostic — the same payload bytes decode identically whether "gRPC"- or "HTTP/x-protobuf"-framed.

The double strategy excludes NaN: protobuf round-trips NaN faithfully, but NaN != NaN would make the equality assertion spuriously fail — the decode contract, not float identity, is under test. Stable across repeated 512-case runs.

Scope / next

  • OTLP/JSON (RFC0003.6 — proto3-JSON encoding rules, the fiddlier path) is the immediate follow-up; it reuses this slice's proptest strategy.
  • Tenant fan-out, the live tonic/axum transports, and the WAL-before-ack path follow as their own slices.
  • The other 14 rfc0003_* tests stay #[ignore]'d.

Verification

  • cargo test -p ourios-ingester ✓ — rfc0003_5 passes; the other 14 remain ignored.
  • cargo fmt --all --check ✓ · cargo clippy --all-targets --all-features -- -D warnings ✓ (workspace)

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

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 1 minute and 31 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ 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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

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: e1b0d0b1-212b-46ed-a7ae-975e3c142e5d

📥 Commits

Reviewing files that changed from the base of the PR and between d49bf0a and 0de2937.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • crates/ourios-ingester/Cargo.toml
  • crates/ourios-ingester/src/lib.rs
  • crates/ourios-ingester/src/receiver.rs
  • crates/ourios-ingester/src/receiver/decode.rs
  • crates/ourios-ingester/tests/rfc0003_5_grpc_http_protobuf_equivalence.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/otlp-receiver-wire-decode

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.

@jensholdgaard
jensholdgaard requested a review from Copilot June 6, 2026 13:28
@jensholdgaard

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

This PR introduces the first “green slice” of the OTLP receiver (RFC 0003 §6.2) by adding a transport-agnostic protobuf wire-decode layer for ExportLogsServiceRequest, along with a property-based test that flips RFC0003.5 (gRPC ≡ HTTP/x-protobuf decode equivalence) live.

Changes:

  • Added receiver::decode::decode_protobuf plus a DecodeError wrapper around prost decode failures.
  • Implemented RFC0003.5 as a proptest-based round-trip + equivalence test over a bounded OTLP proto value space.
  • Updated crate/module docs and added dependencies (opentelemetry-proto, prost, proptest) to support wire decoding and tests.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
crates/ourios-ingester/src/receiver/decode.rs New OTLP protobuf wire-decode module and DecodeError.
crates/ourios-ingester/src/receiver.rs Exposes the new decode module and re-exports decode API.
crates/ourios-ingester/tests/rfc0003_5_grpc_http_protobuf_equivalence.rs Turns RFC0003.5 from ignored stub into a proptest-backed acceptance test.
crates/ourios-ingester/src/lib.rs Updates crate-level docs to reflect receiver “greening” and the new decode slice.
crates/ourios-ingester/Cargo.toml Adds opentelemetry-proto, prost, and proptest dependencies for decoding + tests.

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

Comment on lines +18 to +22
#[derive(Debug)]
pub enum DecodeError {
/// Protobuf bytes failed `prost` decode — a malformed wire payload.
Protobuf(prost::DecodeError),
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 0de2937DecodeError is now #[non_exhaustive], so the RFC0003.6 Json variant lands additively and downstream matches keep a wildcard arm.

Comment thread crates/ourios-ingester/Cargo.toml Outdated
Comment on lines +41 to +42
# `prost::Message::{decode, encode_to_vec}` for the protobuf payload.
prost = { version = "0.14", default-features = false }

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Good catch — real fragility. prost now declares features = ["std"] explicitly (0de2937), rather than relying on workspace feature-unification to satisfy prost::DecodeError: std::error::Error for the source() chain.

Comment on lines +38 to +42
/// An `AnyValue` tree: scalars, plus up to one nesting level of array
/// and kvlist (the structured-body shapes RFC0003.7 will lean on).
fn any_value() -> impl Strategy<Value = AnyValue> {
scalar_value()
.prop_recursive(2, 12, 4, |inner| {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed the doc in 0de2937prop_recursive(2, …) permits up to two nesting levels, so the comment now says "up to two nesting levels" (the depth was intentional for coverage; only the wording was wrong).

…valence)

First green slice of the OTLP receiver (RFC 0003 §6.2). Lands the
transport-agnostic decode layer and flips RFC0003.5 live.

`receiver::decode::decode_protobuf` decodes the `ExportLogsServiceRequest`
payload that both the gRPC and HTTP `application/x-protobuf` transports
carry (they share one decoder), via `prost`. A hand-rolled `DecodeError`
(no thiserror, `#[non_exhaustive]` so the RFC0003.6 `Json` variant is
additive) wraps the prost failure with a source chain; a future transport
handler maps it to the controlled error RFC0003.11 requires. `prost`'s
`std` feature is explicit, since `source()` returns `prost::DecodeError`
as `&dyn std::error::Error`.

RFC0003.5 goes live: a proptest strategy over the OTLP proto value space
(scalar + nested array/kvlist `AnyValue`s, multi-resource/scope/record
requests) asserts decode is faithful (round-trips the original) and
transport-agnostic (the same payload bytes decode identically whether
"gRPC"- or "HTTP"-framed). The double strategy excludes NaN, since
`NaN != NaN` would make the round-trip equality assertion spuriously
fail — the decode contract, not float identity, is under test. Stable
across repeated 512-case runs.

API is grown incrementally per the maintainer decision: this slice adds
only the decode layer + the opentelemetry-proto/prost deps. OTLP/JSON
(RFC0003.6 — proto3-JSON encoding rules) and the live tonic/axum
transports land in the next slices. No live listener yet, so the
transports are tested at the shared decode boundary.

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

@jensholdgaard
jensholdgaard merged commit 7667e36 into main Jun 6, 2026
11 checks passed
@jensholdgaard
jensholdgaard deleted the feat/otlp-receiver-wire-decode branch June 6, 2026 13:41
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