Skip to content

Bug: OTEL_METRICS_KNOWN_FIELD_LIST out of sync with emitted keys (metric series fragmentation and collision) #1723

Description

@prabhaks

Summary

OTEL_METRICS_KNOWN_FIELD_LIST in src/otel/metrics.rs is out of sync with the keys the metric flatteners actually emit. compute_series_hash treats every top-level key that is NOT in this list as a series label, so the mismatch corrupts physical-series identity for metrics in two opposite ways: some real per-sample fields are treated as labels (fragmenting a series into many), and some names that are never emitted are listed (which can merge distinct series if a user attribute happens to use one of those names).

Background

compute_series_hash (src/otel/metrics.rs) hashes metric_name plus every top-level key/value on the flattened data point that is not present in OTEL_METRICS_KNOWN_FIELD_LIST. The result is stored per sample as __series_hash and used by the query layer to group samples into series. So the list must exactly match the set of non-label (sample/metric-level) keys the flatteners emit.

Problem 1: emitted keys missing from the list (series fragmentation)

These are emitted as top-level keys but are absent from the list, so their per-sample values get hashed into the series identity. Samples of the same physical series then get different __series_hash values and are split into many spurious series.

  • min — emitted by flatten_histogram (around line 351, via insert_number_if_some)
  • max — emitted by flatten_histogram (around line 352)
  • data_point_quantile_values — emitted by flatten_summary (around line 471) as a nested array of {quantile, value} objects

Impact: histogram series fragment whenever min/max change across scrapes (routine, especially for DELTA temporality), and summary series fragment as quantile values change every sample.

Problem 2: listed names that are never emitted (dead entries, with collision risk)

These appear in the list but are never emitted as top-level keys, so they exclude any real attribute of the same name from the series hash:

  • value (list) — only ever emitted nested inside the data_point_quantile_values objects (around line 484), never as a top-level key. value is a very common attribute name, so a user label named value would be silently dropped from series identity and distinct series would collide.
  • quantile (list) — same situation (nested only, around line 479); collision risk for an attribute named quantile.
  • data_point_quantile_values_quantile and data_point_quantile_values_value (list) — never emitted anywhere. Harmless dead entries (names are specific enough to be unlikely user labels), but they should be removed for correctness.

Proposed fix

  • Add min, max, and data_point_quantile_values to OTEL_METRICS_KNOWN_FIELD_LIST.
  • Remove value, quantile, data_point_quantile_values_quantile, and data_point_quantile_values_value.
  • Update the list length constant and the OTEL_METRICS_KNOWN_FIELD_LIST.len() test assertion accordingly.
  • Add tests asserting that differing min/max (histogram) and data_point_quantile_values (summary) do not change compute_series_hash, and that a data point attribute named value or quantile does change it.

Related

Same class of issue as exemplar attributes leaking into the series hash, discussed in #1662 (see also #1720). Found while auditing the flattening code after that fix.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions