Skip to content

Exponential histogram support in ITS#3558

Draft
jmacd wants to merge 8 commits into
open-telemetry:mainfrom
jmacd:jmacd/expohisto
Draft

Exponential histogram support in ITS#3558
jmacd wants to merge 8 commits into
open-telemetry:mainfrom
jmacd:jmacd/expohisto

Conversation

@jmacd

@jmacd jmacd commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Change Summary

Experimental specification in open-telemetry/opentelemetry-specification#5230

What issue does this PR close?

Part of #2428
Fixes #2458

How are these changes tested?

See also https://github.com/jmacd/rust-expohisto.

Are there any user-facing changes?

Users get exponential histogram at normal and detailed level of internal metrics through ITS.

Changelog

  • Added a .chloggen/*.yaml entry
  • This PR is a chore (indicated in title)
  • This is a documentation-only PR.

jmacd and others added 7 commits July 22, 2026 16:45
Introduce the otap-df-expohisto crate: an allocation-free, zero-unsafe,
zero-dependency OpenTelemetry exponential histogram. Bucket-index lookup
tables are pre-generated and checked in (src/lookup_tables.rs,
src/inverse_factors.rs) so the crate builds without a code-generation step
or external build dependencies.

Scoped to the core library (Histogram / HistogramNN / HistogramPN, mapping,
lookup, boundary, quantile); benches, fuzz, and the exhaustive upstream test
suite are omitted. This is the foundation for encoding ITS histogram
instruments as OTLP exponential histogram points.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
Add the first ITS integration step for the vendored expohisto crate: encoding
primitives that project aggregations onto OTLP ExponentialHistogramDataPoints,
living alongside the MetricSet-to-OTLP code in the telemetry crate.

- exponential_histogram_data_point: projects an expohisto HistogramView onto a
  positive-range exponential point, recovering OTLP zero_count as
  count - sum(positive bucket counts) and preserving sum/min/max.
- mmsc_exponential_histogram_data_point: projects a min/max/sum/count summary
  onto the bucketless "basic" exponential form, so every histogram tier can
  share the exponential-histogram point type.

These are covered by documented unit tests and are not yet wired into
encode_metric; that follows once a histogram-carrying MetricValue variant and
the Mmsc/Histogram<NORMAL>/Histogram<DETAILED> instrument enum land.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
Switch the internal Mmsc instrument's OTLP projection from an
explicit-bounds Histogram point to a bucketless delta
ExponentialHistogram point (scale 0, no positive/negative buckets),
preserving exact min, max, sum, and count. This aligns the "basic"
Mmsc tier with the forthcoming exponential-histogram instrument tiers
so all tiers share a single OTLP point type.

Wires the previously-added mmsc_exponential_histogram_data_point
primitive into encode_metric, extends the metric-stream coalescing
helpers (metric_data_compatible / append_metric_points) to handle
ExponentialHistogram, updates the module documentation table, and
adjusts the affected encoder tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
…n tiers

Introduce the exponential-histogram instrument foundation in the telemetry
crate, ahead of wiring it through the metric pipeline:

- HISTOGRAM_NORMAL_WORDS (10) and HISTOGRAM_DETAILED_WORDS (26) name the
  expohisto word-pool sizes for the two histogram tiers.
- Distribution is a delta instrument enum with a Basic tier (inline Mmsc,
  min/max/sum/count) and boxed Normal/Detailed exponential-histogram tiers.
  It offers basic()/normal()/detailed() constructors plus record, reset,
  count, is_empty, and same-tier merge, mirroring Mmsc's delta semantics and
  rejecting negative/NaN/infinite observations.

This is additive and self-contained: Distribution is not yet carried by
MetricValue or accepted by the #[metric_set] macro. Because it boxes
expohisto histograms (which are Clone, not Copy), Distribution is not Copy;
wiring it into MetricValue in a later step will make MetricValue non-Copy.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
…sizes

Box the Basic(Mmsc) tier so all Distribution variants are pointer-sized,
removing the variant_size_differences lint allowance instead of suppressing
it. This keeps the enum uniformly small when carried by value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
…ribution

Prepare the internal telemetry aggregation for exponential-histogram tiers by
adding a `MetricValue::Distribution(Box<Distribution>)` variant. Because the
boxed distribution is not `Copy`, `MetricValue` is now `Clone`-only:

- Rework `MetricValue` methods to be reference-based (`is_zero`, `zero_of_kind`,
  `add_in_place`, `reset`, `to_f64`, `to_u64_lossy`) with `Distribution` arms.
- Keep serde `Serialize`/`Deserialize` for the existing scalar/Mmsc wire format;
  mark the new `Distribution` variant `#[serde(skip)]` since it is not yet
  produced by any instrument and has no stable wire representation.
- Add `Distribution::tier_name` and `Distribution::summary` accessors and use
  them for validation formatting.
- Fix the cross-crate ripple from dropping `Copy`: clone-on-yield in the
  metrics iterator, borrow/clone at merge sites in engine `pipeline_ctrl`,
  admin telemetry rendering (with deferred `unreachable!` seams for
  distribution rendering), and validation metric formatting.
- Add a documented telemetry unit test exercising the Distribution variant's
  merge/reset/zero_of_kind behavior.

Distribution values cannot yet be produced (no descriptor Instrument variant or
macro support); those seams are intentionally deferred to a follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
…stogram point

Give MetricValue::Distribution a real, stable serde wire form instead of
skipping it: a distribution now serializes to the OTel exponential-histogram
point shape, consistent with the OTLP proto export.

- Add `ExponentialHistogramPoint` (scale, zero_count, positive offset/buckets,
  count, and optional sum/min/max) as the serde wire form, plus
  `Distribution::to_point` projecting each tier onto it (basic -> bucketless,
  normal/detailed -> positive bucket range at the view scale).
- Introduce `DistributionValue { Live(Distribution), Point(...) }`. Both forms
  serialize identically to the point shape; deserializing yields a read-only
  `Point` because the vendored histogram cannot be rebuilt from buckets. This
  is sufficient for the admin JSON endpoint and validation, which only read
  distribution values.
- Change `MetricValue::Distribution` to `Box<DistributionValue>` and declare it
  before `Mmsc` so an exponential-histogram point object is not mis-parsed as
  an Mmsc summary under `#[serde(untagged)]`.
- Add tests: point projection with zero recovery, live->point serde
  round-trip, MetricValue untagged disambiguation, and read-only point
  reset/merge no-ops.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
@github-actions github-actions Bot added lang:rust Pull requests that update Rust code area:observability Engine observability labels Jul 23, 2026
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Jul 23, 2026

Copy link
Copy Markdown

Pull request dashboard status

Status last refreshed: 2026-07-23 03:12:52 UTC.

  • Waiting on: Author
  • Next step: Move out of draft to request review.

This automated status or its linked feedback items may be incorrect. If something looks wrong, please report it with the result you expected.

…d-to-end

Add `Instrument::ExponentialHistogram` and the `HistogramNormal`/
`HistogramDetailed` instruments so `#[metric_set]` fields can declare a
distribution tier by field type. The macro maps these types to a delta F64
exponential-histogram instrument, and `encode_metric` projects the live
`Distribution` (basic/normal/detailed) onto an OTLP exponential-histogram
point via the tested `exphist` primitives, removing the last `dead_code`
allow on the view primitive.

Admin Prometheus/line-protocol rendering now expands distributions to their
min/max/sum/count summary (full bucket rendering deferred) instead of
panicking. Adds a macro-level integration test and an OTLP encode test
(record -> snapshot -> merge -> encode).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c95c1ba9-b197-45aa-9f7b-145982b3e4d6
@github-actions github-actions Bot added area:engine Internal engine features area:validation Work related to extended validation testing labels Jul 23, 2026
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 56.26374% with 995 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.58%. Comparing base (c79986e) to head (651e54b).
⚠️ Report is 6 commits behind head on main.

❌ Your patch check has failed because the patch coverage (56.26%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3558      +/-   ##
==========================================
- Coverage   86.80%   86.58%   -0.22%     
==========================================
  Files         780      799      +19     
  Lines      318504   321683    +3179     
==========================================
+ Hits       276464   278527    +2063     
- Misses      41516    42632    +1116     
  Partials      524      524              
Components Coverage Δ
otap-dataflow 87.59% <56.26%> (-0.27%) ⬇️
query_engine 89.57% <ø> (ø)
otel-arrow-go 52.45% <ø> (ø)
quiver 92.20% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@@ -0,0 +1,19 @@
# Use this changelog template to create an entry for release notes.

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.

Should we combine these 3 chloggen yaml files into a single one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:engine Internal engine features area:observability Engine observability area:validation Work related to extended validation testing lang:rust Pull requests that update Rust code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Exponential histogram aggregator data structure

2 participants