Skip to content

feat: add span-level access for traces#2

Merged
jpkrohling merged 3 commits intoollygarden:mainfrom
jpkrohling:jpkroehling/e-1467-add-span-level-access-for-traces-in-otlp-wire
Feb 17, 2026
Merged

feat: add span-level access for traces#2
jpkrohling merged 3 commits intoollygarden:mainfrom
jpkrohling:jpkroehling/e-1467-add-span-level-access-for-traces-in-otlp-wire

Conversation

@jpkrohling
Copy link
Copy Markdown
Contributor

@jpkrohling jpkrohling commented Feb 17, 2026

Summary

  • Add ScopeSpans and Span byte-slice types with iterators (ResourceSpans.ScopeSpans(), ScopeSpans.Spans()) and field accessors (TraceID(), SpanID(), ParentSpanID())
  • Enable gaps to extract the 3 fields it needs per span directly from raw protobuf bytes, eliminating full pdata unmarshal overhead
  • Field accessors achieve 0 allocations; full iteration is ~1.6x faster and uses ~425x less memory than pdata unmarshal

Resolves E-1467

Test plan

  • Iterator tests: multiple ResourceSpans → ScopeSpans → Spans, verify all yielded
  • Field accessor tests: TraceID, SpanID, ParentSpanID match pdata-set values
  • Root span test: absent parent returns zero value (not error)
  • Multi-resource, multi-scope hierarchy traversal
  • Round-trip: wire extraction matches pdata unmarshal
  • Error handling: malformed protobuf, truncated data, wrong field sizes
  • Benchmarks: 0 allocs for field accessors confirmed

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Directly extract trace IDs, span IDs, and parent span IDs from OTLP wire-format data.
    • Iterate ScopeSpans and Spans efficiently (including span counts) without full unmarshaling, with per-iterator error reporting and zero-allocation identifier access.
  • Tests

    • Expanded tests covering traversal, field accessors, malformed data handling, round-trip verification, cross-resource scenarios, and performance benchmarks.
  • Documentation

    • Updated docs describing the new per-span accessors and iterator APIs.

Add ScopeSpans and Span types with iterators and field accessors to
extract TraceID, SpanID, and ParentSpanID directly from raw protobuf
bytes, avoiding full pdata unmarshal.

Resolves E-1467

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

Adds wire-format iterators and types for OTLP traces (ScopeSpans, Span) plus fixed-size byte extractors (TraceID, SpanID, ParentSpanID) to access span identifiers and nested spans without full unmarshaling; includes tests and benchmarks validating traversal and error cases.

Changes

Cohort / File(s) Summary
Core implementation
otlpwire.go
Adds ScopeSpans and Span types; ResourceSpans.ScopeSpans() iterator (with error hook); ScopeSpans.SpanCount() and ScopeSpans.Spans() iterators; Span.TraceID(), Span.SpanID(), Span.ParentSpanID() accessors; introduces extractFixedBytesField() and per-iterator error propagation to traverse wire-format without full unmarshaling.
Tests & benchmarks
otlpwire_test.go
Adds comprehensive tests for multi-resource/multi-scope/multi-span traversal, identifier extraction, malformed/wrong-size and wire-type error cases, round-trip validation against pdata, root-span handling, and benchmarks for accessors and iteration.
Documentation
README.md
Documents the new API surface: ResourceSpans.ScopeSpans(), ScopeSpans and Span types, and their new methods for iteration and zero-allocation identifier access.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐇 I nibble bytes and hop through spans,
I find trace IDs with nimble plans.
No full unpack — a quick depart,
I pluck the fields, then bound apart.
Tiny hops, but clever heart.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title follows Conventional Commits format with 'feat:' prefix and clearly summarizes the main change: adding span-level access capabilities to traces in the otlp-wire package.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@otlpwire.go`:
- Around line 552-586: The function extractFixedBytesField currently ignores
cases where the tag number matches fieldNum but the wireType is not
protowire.BytesType, treating the field as absent; update extractFixedBytesField
so that when num == fieldNum and wireType != protowire.BytesType it returns a
clear error (e.g., "wrong wire type for field") instead of skipping, leaving all
other behavior (proto3 zero-value handling, size check, skipping other fields
via skipField) unchanged.

Match the existing pattern from extractResourceMessage: when the field
number matches but the wire type is not BytesType, return an error
instead of silently skipping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@otlpwire.go`:
- Around line 165-214: The helpers used by ResourceSpans.ScopeSpans,
ScopeSpans.Spans and ScopeSpans.SpanCount (e.g. forEachRepeatedField and
countOccurrences) currently ignore fields when num == fieldNum but wireType !=
BytesType, which hides malformed data; update those helper functions to return a
clear error when a matching field number has a non-BytesType wire type
(consistent with extractResourceMessage behavior), then propagate that error
back into the iterator error slot (iterErr) in ScopeSpans() and Spans() and
return it from SpanCount() so callers see wrong-wire-type errors instead of
silently skipping the field.
- Around line 30-35: Update the project documentation to include the new public
API types and accessors: add README.md sections describing the ScopeSpans and
Span types, their purpose (raw wire bytes), and document how to use their field
accessors TraceID, SpanID, ParentSpanID and the existing SpanCount() with short
usage examples showing how to obtain and read those fields; also add or update
CLAUDE.md per repository guidelines to mention these additions and any
contribution/CLA instructions. Ensure the docs reference the exact symbols
ScopeSpans, Span, TraceID, SpanID, ParentSpanID, and SpanCount() so users can
find and use the new API.

Comment on lines +30 to +35
// ScopeSpans represents a single ScopeSpans message (raw wire bytes).
type ScopeSpans []byte

// Span represents a single Span message (raw wire bytes).
type Span []byte

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify commit message format (conventional commits)
echo "=== Recent Commits ==="
git log --oneline --decorate -n 20

echo -e "\n=== Checking README.md for new API mentions ==="
rg -n "ScopeSpans|Span\.TraceID|Span\.SpanID|Span\.ParentSpanID|SpanCount\(" README.md 2>/dev/null || echo "Not found in README.md"

echo -e "\n=== Checking CLAUDE.md for new API mentions ==="
rg -n "ScopeSpans|Span\.TraceID|Span\.SpanID|Span\.ParentSpanID|SpanCount\(" CLAUDE.md 2>/dev/null || echo "Not found in CLAUDE.md"

echo -e "\n=== Checking if docs files exist ==="
ls -la README.md CLAUDE.md 2>&1 || echo "One or both doc files missing"

Repository: ollygarden/otlp-wire

Length of output: 665


Update documentation to cover new public API types and field accessors.

Commit format follows conventional commits (✓). However, README.md does not document the new public types (ScopeSpans, Span) or their field accessors (TraceID, SpanID, ParentSpanID); only SpanCount() is mentioned. Additionally, CLAUDE.md is missing and should be created or updated per coding guidelines requiring documentation files to be up to date.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@otlpwire.go` around lines 30 - 35, Update the project documentation to
include the new public API types and accessors: add README.md sections
describing the ScopeSpans and Span types, their purpose (raw wire bytes), and
document how to use their field accessors TraceID, SpanID, ParentSpanID and the
existing SpanCount() with short usage examples showing how to obtain and read
those fields; also add or update CLAUDE.md per repository guidelines to mention
these additions and any contribution/CLA instructions. Ensure the docs reference
the exact symbols ScopeSpans, Span, TraceID, SpanID, ParentSpanID, and
SpanCount() so users can find and use the new API.

Add wrong-wire-type checks to countRepeatedField, countOccurrences, and
forEachRepeatedField, consistent with extractResourceMessage and
extractFixedBytesField. Update README with new span-level API types,
methods, and usage example.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Around line 151-167: The repo is missing CLAUDE.md to cover the new API
surface introduced (ResourceSpans.ScopeSpans, type ScopeSpans and methods
ScopeSpans.SpanCount/Spans, and type Span with TraceID/SpanID/ParentSpanID);
either add a CLAUDE.md that mirrors the API docs from README.md (document
ResourceSpans.ScopeSpans, ScopeSpans, ScopeSpans.SpanCount, ScopeSpans.Spans,
Span.TraceID, Span.SpanID, Span.ParentSpanID with signatures and brief
descriptions) or, if CLAUDE.md is not required, update the project documentation
policy (e.g., contributing or README note) to explicitly state that CLAUDE.md
isn’t needed and confirm in the PR description so reviewers know the omission is
intentional.

Comment on lines +151 to 167
func (r ResourceSpans) ScopeSpans() (iter.Seq[ScopeSpans], func() error)
```

**Scope-level operations (traces):**
```go
type ScopeSpans []byte
func (s ScopeSpans) SpanCount() (int, error)
func (s ScopeSpans) Spans() (iter.Seq[Span], func() error)
```

**Span-level field accessors:**
```go
type Span []byte
func (s Span) TraceID() ([16]byte, error)
func (s Span) SpanID() ([8]byte, error)
func (s Span) ParentSpanID() ([8]byte, error)
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e

echo "=== Recent commits ==="
git log --oneline -n 20

echo -e "\n=== Docs presence ==="
ls -la README.md CLAUDE.md

echo -e "\n=== New API mentions in docs ==="
rg -n "ScopeSpans|Span\.TraceID|Span\.SpanID|Span\.ParentSpanID|SpanCount\(" README.md CLAUDE.md

Repository: ollygarden/otlp-wire

Length of output: 317


🏁 Script executed:

cat -n README.md | sed -n '140,180p'

Repository: ollygarden/otlp-wire

Length of output: 1515


Create CLAUDE.md or confirm if it should document the new API surface.

The commit follows conventional format (✓), and the new API is properly documented in README.md at lines 151-167. However, CLAUDE.md does not exist. Per coding guidelines, documentation files (README.md, CLAUDE.md) must be up to date. Either create CLAUDE.md with API documentation coverage, or clarify whether CLAUDE.md is required for this project.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 151 - 167, The repo is missing CLAUDE.md to cover the
new API surface introduced (ResourceSpans.ScopeSpans, type ScopeSpans and
methods ScopeSpans.SpanCount/Spans, and type Span with
TraceID/SpanID/ParentSpanID); either add a CLAUDE.md that mirrors the API docs
from README.md (document ResourceSpans.ScopeSpans, ScopeSpans,
ScopeSpans.SpanCount, ScopeSpans.Spans, Span.TraceID, Span.SpanID,
Span.ParentSpanID with signatures and brief descriptions) or, if CLAUDE.md is
not required, update the project documentation policy (e.g., contributing or
README note) to explicitly state that CLAUDE.md isn’t needed and confirm in the
PR description so reviewers know the omission is intentional.

@jpkrohling jpkrohling merged commit 0e142b9 into ollygarden:main Feb 17, 2026
2 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.

1 participant