Skip to content

epic: complete the mergeable OTel metric primitive set #1201

Description

@keddie

🤖 This comment was generated by Claude on behalf of @keddie.

Epic: complete the mergeable OTel metric primitive set

We can already answer "how many" (Sum) and "how many distinct" (cardinality) in a mergeable, replicate-anywhere-then-combine form. We can't yet answer "what's the current value" or "what's the p99." This epic closes the gap so kuilt covers every OTel metric point type worth supporting — each as a CRDT (join-semilattice merge, idempotent), so metrics from many peers merge losslessly without a central aggregator.

Coverage map

OTel point type Primitive Status
Sum (monotonic / up-down) GCounter / PNCounter ✅ done (#797)
distinct-count HyperLogLog ✅ done (#797)
Gauge (last value) LWWRegister #1202 (ready)
Histogram (explicit buckets) fixed buckets → GCounter #1203 (ready)
ExponentialHistogram / quantiles DDSketch (bucket → GCounter) #1204 (needs-design)
Summary (legacy quantile) deliberately excluded — OTel deprecated it in favor of ExponentialHistogram; building it would add a legacy type

Sub-issues

Placement — largely settled, one seam to hold

Correction to an earlier draft of this issue: the mergeable structures already live in :kuilt-crdtHyperLogLog, CountMinSketch, BloomFilter, GCounter, LWWRegister are all Quilted types there; #797 is the OTel exporter consuming HLL, not the home of the sketch. So the pattern is set:

  • CRDT structures → :kuilt-crdt, each a Quilted<T> rung with the four-law tests (precedent: HLL/CMS). Gauge reuses the existing LWWRegister; Histogram is a bucket → GCounter product; DDSketch is a new Quilted sketch alongside HLL/CMS.
  • OTLP serialization / the exporter mapping → the metrics-exporter module (with kuilt-otel A3: WarpMetricExporter (cumulative counters + HyperLogLog cardinality) #797), so :kuilt-crdt stays OTel-agnostic and dependency-light. Don't leak metrics.proto shapes into the zoo.

The one real design fork is inside #1204 (merge model: unbounded-additive vs. op-based) — see that issue; it doesn't affect Gauge/Histogram.

Cross-cutting notes (not sub-issues)

  • CRDT merge is naturally cumulative. OTel aggregation temporality (delta vs. cumulative) falls out as: cumulative = the merged state; delta = a subtraction against the last-sent state. Only build the delta path if a consumer demands delta temporality — flag, don't pre-build.
  • Config constants are cluster-wide. Each type has a "must-match-to-merge" constant — HLL precision p, histogram boundaries, DDSketch α. Same discipline across all: fixed config, not per-call, mismatch ⇒ reject-or-recoarsen, never silently merge misaligned state.
  • OTLP is the interop target. Gauge → NumberDataPoint; Histogram → HistogramDataPoint; DDSketch → ExponentialHistogramDataPoint (a near-1:1 structural mapping — see Metrics: ExponentialHistogram / quantiles via DDSketch #1204).

Why now

Small, self-contained, mostly reuses existing zoo primitives (only DDSketch is new machinery), and it rounds out the metrics story for the exporter (#797). Worth knocking out sooner rather than later.

Related: #797 (Sum + HLL cardinality in the metric exporter).

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicCoordination umbrella with sub-issues

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions