Otel.Metrics.Aggregation.ExplicitBucketHistogram (otel v0.4.1)

Copy Markdown View Source

Explicit bucket histogram aggregation.

Uses :counters for thread-safe bucket increments and ets:update_counter / ets:update_element for atomic count, sum, min, and max updates.

ETS entry format: {key, counters_ref, min, max, sum, count, start_time, reservoir_state}.

The eighth slot holds the exemplar reservoir state (Otel.Metrics.Exemplar.Reservoir.AlignedHistogramBucket) so a single ETS row carries everything collect/3 needs to emit a datapoint with exemplars.

Cumulative-only — collect/3 returns running totals since stream start. Delta temporality is not supported (minikube hardcodes cumulative; spec metrics/sdk.md L1290-L1297 default).

Configuration parameters

Otel.Metrics.Meter.register_instrument/3 resolves :boundaries from the instrument's advisory :explicit_bucket_boundaries (when present).

KeyDefaultDescription
:boundaries@default_boundaries (15 OTel-default buckets)Bucket boundaries per metrics/sdk.md L660-L661

Spec metrics/sdk.md L662 also lists a RecordMinMax Stream config knob; minikube has no Views so it is permanently on and not exposed here. The encoder's min: nil / max: nil path still exists for the brief concurrent-collect window before the first measurement updates the ETS row.

Summary

Functions

aggregate(metrics_tab, key, value, opts)

@spec aggregate(
  metrics_tab :: :ets.table(),
  key :: term(),
  value :: number(),
  opts :: map()
) :: :ok

collect(metrics_tab, stream_name, opts)

@spec collect(
  metrics_tab :: :ets.table(),
  stream_key :: String.t(),
  opts :: map()
) :: [Otel.Metrics.Aggregation.datapoint()]

default_boundaries()

@spec default_boundaries() :: [number()]

offer_exemplar(metrics_tab, key, value, time, filtered_attrs, ctx)

@spec offer_exemplar(
  metrics_tab :: :ets.table(),
  key :: term(),
  value :: number(),
  time :: non_neg_integer(),
  filtered_attrs :: %{required(String.t()) => term()},
  ctx :: Otel.Ctx.t()
) :: :ok