Otel.SDK.Metrics.Aggregation.Base2ExponentialBucketHistogram (otel v0.2.0)

Copy Markdown View Source

Base2 Exponential Bucket Histogram aggregation (metrics/sdk.md §Base2 Exponential Bucket Histogram Aggregation L670-L760, Status: Stable, v1.55.0).

Compresses bucket boundaries using base = 2^(2^-scale), yielding a high-dynamic-range histogram with bounded relative error per bucket. Bucket index i holds measurements in (base^i, base^(i+1)].

Configuration parameters

Pass via opts (typically through Stream.aggregation_options):

KeyDefaultDescription
:max_size160Max buckets per range (positive/negative) — spec L680
:max_scale20Max scale parameter — spec L680
:record_min_maxtrueWhether to record min/max — spec L680

The :zero_threshold field is fixed at 0 in this implementation; values that map exactly to zero (or underflow to subnormal-zero) accumulate into zero_count.

Storage and concurrency

Each (stream_key, reader_id, attributes) cell holds a single ETS row carrying the full per-cell state in a map. aggregate/4 is read-modify-write under the same key. Concurrent aggregate/4 calls on the same attribute cell may lose updates; the design assumes write-serialised use through Otel.SDK.Metrics.MetricReader.collect/1 and the single-writer instrument facade. This trade-off matches Java OTel SDK's synchronized-block approach ported to ETS.

Mapping function

Uses the logarithm method documented in spec metrics/data-model.md §"All Scales: Use the Logarithm Function" L820-L880, with a special case for exact powers of two (spec L867-L869). The natural-logarithm formula is exact except near power-of-two boundaries, where :math.log/1 accumulated error can produce off-by- one results — the special case eliminates this.

Auto-scale-down

When a measurement would push the populated-bucket count beyond :max_size, the histogram downscales by 1 (scale - 1) and merges adjacent buckets. Spec metrics/sdk.md §"Maintain the ideal scale" L755-L760 SHOULD: "adjust the histogram scale as necessary to maintain the best resolution possible, within the constraint of maximum size." Downscale repeats until the measurement fits.

References

  • SDK §Base2 Exponential Bucket Histogram Aggregation: opentelemetry-specification/specification/metrics/sdk.md L670-L760
  • Data model §ExponentialHistogram: opentelemetry-specification/specification/metrics/data-model.md L539-L955
  • Proto ExponentialHistogramDataPoint: opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto L222

Summary

Types

Per-cell state stored in ETS as the second tuple element: {key, state}.

Types

state()

@type state() :: %{
  scale: integer(),
  positive: %{required(integer()) => non_neg_integer()},
  negative: %{required(integer()) => non_neg_integer()},
  zero_count: non_neg_integer(),
  min: number() | :unset,
  max: number() | :unset,
  sum: number(),
  count: non_neg_integer(),
  start_time: non_neg_integer()
}

Per-cell state stored in ETS as the second tuple element: {key, state}.

Functions

map_to_index(value, scale)

@spec map_to_index(value :: number(), scale :: integer()) :: integer()