Skip to content

In-Storage & WAL Coupling - #4

Draft
dashpole wants to merge 3 commits into
mainfrom
prototype/opt-a-in-storage-coupling
Draft

In-Storage & WAL Coupling#4
dashpole wants to merge 3 commits into
mainfrom
prototype/opt-a-in-storage-coupling

Conversation

@dashpole

@dashpole dashpole commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Why is this change necessary?

Possible fix for prometheus#17857

In Remote Write 2.0 (PRW 2.0), the specification mandates:

"At least one element in samples or in histograms MUST be provided. A TimeSeries MUST NOT include both samples and histograms."

Historically, Prometheus has treated exemplars as a series-level attribute rather than a sample-level attribute. headAppenderV2.Commit() writes float/histogram samples and exemplars to separate WAL records (record.Samples vs. record.Exemplars). When the WAL Watcher tails the WAL and pushes them into Remote Write shard queues, they are processed as independent series items. For PRW 2.0, this causes standalone exemplar records to be emitted as writev2.TimeSeries containing exemplars with 0 samples and 0 histograms, directly violating the PRW 2.0 specification and causing failures in PRW 2.0 receivers (e.g. OpenTelemetry Collector, Mimir, Google Cloud Managed Prometheus).

What does this PR do?

This PR implements Option A: End-to-End Per-Sample Association (In-Storage & WAL Coupling):

  1. Compound WAL Records (tsdb/record):

    • Introduces compound record types: RefSampleV2, RefHistogramSampleV2, RefFloatHistogramSampleV2, and RefCustomBucketsHistogramSampleV2.
    • Adds binary encoders and full-fidelity decoders for record.SamplesV2 (10), record.HistogramSamplesV2 (11), record.FloatHistogramSamplesV2 (12), and record.CustomBucketsHistogramSamplesV2 (13).
    • Implements zero-allocation exemplar skipping decoders (skipExemplars) used during recovery/fast replay when exemplars are not needed.
  2. Head Appender & TSDB Dual-Write (tsdb/head_append_v2.go, tsdb/head_wal.go):

    • Extends headAppenderV2.Append to package attached exemplars into compound batches and commit compound WAL records.
    • Preserves PromQL /api/v1/query_exemplars via dual-write to in-memory h.exemplars (CircularExemplarStorage).
    • Supports mixed-version WAL replay (interleaved V1 and V2 records across restarts/upgrades).
    • Restores attached exemplars into ExemplarStorage during Head WAL replay recovery.
  3. WAL Watcher & Remote Write Pipeline (tsdb/wlog/watcher.go, storage/remote/queue_manager.go):

    • WAL Watcher streams compound sample+exemplar units to QueueManager.
    • Supports zero-allocation exemplar stripping when sendExemplars=false or during non-tailing replay.
    • populateV2TimeSeries maps attached exemplars directly to the metric's writev2.TimeSeries object, guaranteeing 0 empty/standalone exemplar series.
    • Preserves 100% backward compatibility for PRW 1.0 endpoints (prompb.WriteRequest).

Verification & Testing

  • go test -v -race ./tsdb/record/... ./tsdb/... ./tsdb/wlog/... ./storage/remote/... (All PASS)
  • BenchmarkRecord/DecodeSamplesV2_ZeroAllocStripping: 0 allocs/op
  • Verified mixed-version WAL replay and PromQL ExemplarQuerier assertions after replay.

Implement compound WAL records and full pipeline coupling between samples
and exemplars for issue prometheus#17857 (Option A):
- Define compound record types (RefSampleV2, RefHistogramSampleV2, RefFloatHistogramSampleV2, RefCustomBucketsHistogramSampleV2) in tsdb/record.
- Implement zero-allocation exemplar skipping decoders for replay efficiency.
- Update HeadAppenderV2 to commit compound WAL records while dual-writing to in-memory ExemplarStorage to preserve PromQL query invariants.
- Update WAL Watcher to stream compound records directly to QueueManager, populating PRW 2.0 TimeSeries with attached exemplars and PRW 1.0 conversions.
- Add comprehensive test coverage verifying mixed WAL replay, rollback semantics, PRW 2.0/1.0 exemplar attachment, and zero-allocation decoding.
@dashpole dashpole changed the title Prototype/opt a in storage coupling In-Storage & WAL Coupling Aug 27, 2026
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