Skip to content

fix(otel): sync OTEL_METRICS_KNOWN_FIELD_LIST with emitted keys (#1723) - #1724

Merged
nitisht merged 5 commits into
parseablehq:mainfrom
prabhaks:fix/1723-known-field-list
Aug 1, 2026
Merged

fix(otel): sync OTEL_METRICS_KNOWN_FIELD_LIST with emitted keys (#1723)#1724
nitisht merged 5 commits into
parseablehq:mainfrom
prabhaks:fix/1723-known-field-list

Conversation

@prabhaks

@prabhaks prabhaks commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

What

Fixes #1723.

compute_series_hash in src/otel/metrics.rs treats every top-level data-point key that is not in OTEL_METRICS_KNOWN_FIELD_LIST as a series label. The list had drifted from the keys the flatteners actually emit, in both directions, corrupting physical-series identity for metrics.

Emitted but missing from the list (series fragmentation)

These are emitted as top-level keys but were absent from the list, so their per-sample values were hashed into __series_hash, splitting one physical series into many:

  • min, max — histogram per-sample statistics (flatten_histogram)
  • data_point_quantile_values — summary quantile array (flatten_summary)

Listed but never emitted top-level (dead entries, with collision risk)

  • value, quantile — only ever emitted nested inside the data_point_quantile_values objects, never as top-level keys. Because they were listed, a user attribute literally named value or quantile was silently excluded from series identity, merging distinct series. value is a common label name, so this was the higher-risk one.
  • data_point_quantile_values_quantile, data_point_quantile_values_value — never emitted anywhere. Harmless dead entries, removed for correctness.

Change

  • Add data_point_quantile_values to the list.
  • Remove value, quantile, data_point_quantile_values_quantile, data_point_quantile_values_value.
  • Rename the emitted histogram statistics from bare min/max to data_point_min/data_point_max, matching the naming convention every other data-point field already uses (data_point_value, data_point_count, data_point_sum, etc.), and add both to the list under their new names. This was raised in review: bare min/max would have shadowed a real user attribute of the same name and wrongly excluded it from the series hash, the same collision risk as value/quantile above.
  • List length 38 -> 37 (relative to main post-fix(otel): preserve all exemplars per data point (#1662) #1720, which already carries exemplars).
  • Tests: differing data_point_min/data_point_max (histogram) and data_point_quantile_values (summary) no longer change compute_series_hash; a data-point attribute named value, quantile, min, or max still does; plus a guard asserting the list contents and length.

Verification

  • cargo test --lib otel::metrics: 18 passed, 0 failed.
  • cargo clippy --all-targets -- -D warnings: clean on this file.
  • Cross-checked the full set of top-level keys emitted by every flattener (number/gauge/sum/histogram/exp-histogram/summary, exemplars, flags, aggregation temporality, metric-level and resource/scope envelope fields) against the updated list: they now correspond 1:1, with no missing keys and no dead entries.
  • Rebased cleanly onto main after fix(otel): preserve all exemplars per data point (#1662) #1720 merged.

Summary by CodeRabbit

  • Bug Fixes

    • Corrected metric field names for sample-level quantiles, minimums, and maximums.
    • Updated histogram data to consistently use prefixed minimum and maximum fields.
    • Removed obsolete flattened metric fields.
  • Tests

    • Expanded coverage for metric series hashing and known-field membership.
    • Added validation for the updated set of 39 known metric fields.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The OTEL known-field list now matches emitted metric keys. Histogram min/max and summary quantile values are excluded from series identity. Top-level value, quantile, min, and max attributes remain series labels. Tests cover the updated behavior.

Changes

OTEL series identity

Layer / File(s) Summary
Align metric field contract
src/otel/metrics.rs
The known-field list includes data_point_min, data_point_max, and data_point_quantile_values. It removes obsolete entries and updates histogram flattening keys.
Validate series-hash classification
src/otel/metrics.rs
Tests verify sample fields do not alter series hashes, top-level attributes do alter them, and the known-field list contains 37 entries.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: parmesant

Poem

I’m a rabbit with a tidy hash,
Sorting fields in a metrics stash.
Min and max now hop away,
Labels keep their names in play.
Quantiles bloom, collisions dash!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: synchronizing the OTEL metrics known-field list with emitted keys.
Description check ✅ Passed The description identifies issue #1723, explains the bug and fix, and documents tests and verification, although it omits the template checklist.
Linked Issues check ✅ Passed The changes address issue #1723 by synchronizing emitted fields, preventing series fragmentation, preserving attribute identity, and adding regression tests.
Out of Scope Changes check ✅ Passed The changes remain within the linked issue scope and focus on metric flattening, series hashing, known fields, and related tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 12, 2026
@prabhaks

Copy link
Copy Markdown
Contributor Author

@parmesant @nikhilsinhaparseable Please review this issue and fix!

@nitisht

nitisht commented Jul 28, 2026

Copy link
Copy Markdown
Member

@prabhaks can you address the conflict pls

…eablehq#1723)

compute_series_hash treats any top-level data-point key not in
OTEL_METRICS_KNOWN_FIELD_LIST as a series label, so the list must match
the keys the flatteners actually emit. It had drifted both ways:

- Emitted but missing (fragmented series): `min` and `max` (histogram
  per-sample stats) and `data_point_quantile_values` (summary quantile
  array). Their per-sample values leaked into __series_hash, splitting a
  physical series into many.
- Listed but never emitted as top-level keys (dead entries): `quantile`
  and `value` (only emitted nested inside data_point_quantile_values),
  plus the never-used data_point_quantile_values_quantile /
  data_point_quantile_values_value. `value`/`quantile` also risked
  collisions: a user attribute of that name was silently dropped from
  series identity, merging distinct series.

Add the 3 missing keys, remove the 4 dead ones (length 37 -> 36), and
add tests for min/max and quantile-value fragmentation plus the
value/quantile collision.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/otel/metrics.rs (1)

207-228: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep legacy flat exemplar attributes out of __series_hash.

With flatten_exemplars enabled, insert_attributes(map, &exemplar(filtered_attributes)) writes non-prefixed exemplar keys into the data-point map. compute_series_hash treats every top-level key outside OTEL_METRICS_KNOWN_FIELDS and without exemplars_ as a label, so traces or spans with different exemplar attributes are hashed as different physical series. Exclude filtered_attributes from the hash, or prefix these flat keys so only the legacy exemplar_* columns are emitted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/otel/metrics.rs` around lines 207 - 228, Update the flatten_exemplars
handling around insert_attributes and compute_series_hash so filtered exemplar
attributes cannot contribute to __series_hash. Either exclude those attributes
when computing the hash or prefix their flattened keys consistently, while
preserving emission of the legacy exemplar_* columns and ensuring only actual
series labels affect the hash.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/otel/metrics.rs`:
- Around line 66-68: Update the histogram field handling in the metrics
serialization and known-field definitions so per-sample statistics use
non-conflicting keys such as data_point_min and data_point_max. Ensure emitted
histogram.min and histogram.max values and the corresponding
OTEL_METRICS_KNOWN_FIELD_LIST entries use the prefixed names consistently,
preserving user min/max attributes for __series_hash.

---

Outside diff comments:
In `@src/otel/metrics.rs`:
- Around line 207-228: Update the flatten_exemplars handling around
insert_attributes and compute_series_hash so filtered exemplar attributes cannot
contribute to __series_hash. Either exclude those attributes when computing the
hash or prefix their flattened keys consistently, while preserving emission of
the legacy exemplar_* columns and ensuring only actual series labels affect the
hash.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 73faa5d3-fe22-42ee-9743-ef4d30175996

📥 Commits

Reviewing files that changed from the base of the PR and between 5c90805 and cb8d8cb.

📒 Files selected for processing (1)
  • src/otel/metrics.rs

Comment thread src/otel/metrics.rs Outdated
…ibutes

Bare min/max top-level keys collide with any OTel attribute literally
named min or max once added to OTEL_METRICS_KNOWN_FIELD_LIST, wrongly
excluding that attribute from the series hash. Renamed to
data_point_min/data_point_max, matching every other data-point field's
naming convention, and added a regression test for the collision case.
@prabhaks

Copy link
Copy Markdown
Contributor Author

Good catch, thanks. Bare min/max would have shadowed a real user attribute with the same name and wrongly excluded it from the series hash, the same class of bug this PR is meant to fix for value/quantile.

Renamed the emitted keys to data_point_min/data_point_max, matching the existing naming convention for every other data point field (data_point_value, data_point_count, data_point_sum, etc), and added a regression test that a user attribute literally named min or max still affects the series hash. Pushed in e417c87.

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
src/otel/metrics.rs (1)

367-368: 🗄️ Data Integrity & Integration | 🔵 Trivial

Renaming histogram min/maxdata_point_min/data_point_max is a breaking change for existing consumers.

This correctly fixes the shadowing issue raised in the previous review, but note that any dashboards, saved queries, or downstream tooling referencing the old bare min/max histogram columns will silently stop populating after this change (and historical rows retain the old column names). Worth a release/migration note if such consumers exist.

🔍 Verification script
#!/bin/bash
# Look for other references to bare histogram min/max fields that might need updating.
rg -nP --type=rust '"min"|"max"' src/ --glob '!src/otel/metrics.rs'
rg -n 'histogram.*min|histogram.*max' docs/ 2>/dev/null
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/otel/metrics.rs` around lines 367 - 368, Document the breaking rename
performed in the histogram serialization around insert_number_if_some, including
migration guidance for consumers of the former bare min/max columns and the new
data_point_min/data_point_max names. Preserve the current field names in code
and add the release or migration note in the project’s established documentation
location.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/otel/metrics.rs`:
- Around line 367-368: Document the breaking rename performed in the histogram
serialization around insert_number_if_some, including migration guidance for
consumers of the former bare min/max columns and the new
data_point_min/data_point_max names. Preserve the current field names in code
and add the release or migration note in the project’s established documentation
location.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 56d25bd2-01ca-47d7-b67a-0b460a99ffed

📥 Commits

Reviewing files that changed from the base of the PR and between cb8d8cb and e417c87.

📒 Files selected for processing (1)
  • src/otel/metrics.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 28, 2026
@prabhaks

Copy link
Copy Markdown
Contributor Author

@parmesant whenever you get time - please look into this!

@coderabbitai coderabbitai Bot mentioned this pull request Jul 30, 2026
3 tasks
Signed-off-by: parmesant <anant.v09@protonmail.com>

@coderabbitai coderabbitai Bot left a comment

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/otel/metrics.rs (1)

42-42: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Fix the known-field array length.

OTEL_METRICS_KNOWN_FIELD_LIST declares [&str; 38], but the initializer contains 37 entries. Rust rejects the mismatch at compile time, and the same list length assertion expects 37.

Proposed fix
-pub const OTEL_METRICS_KNOWN_FIELD_LIST: [&str; 38] = [
+pub const OTEL_METRICS_KNOWN_FIELD_LIST: [&str; 37] = [
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/otel/metrics.rs` at line 42, Update the array length declaration in
OTEL_METRICS_KNOWN_FIELD_LIST from [&str; 38] to [&str; 37] to match the number
of string entries actually provided in the initializer, which contains 37
elements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/otel/metrics.rs`:
- Line 42: Update the array length declaration in OTEL_METRICS_KNOWN_FIELD_LIST
from [&str; 38] to [&str; 37] to match the number of string entries actually
provided in the initializer, which contains 37 elements.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c9370c88-f319-4466-b965-8a396314c0da

📥 Commits

Reviewing files that changed from the base of the PR and between e417c87 and f9cd2f5.

📒 Files selected for processing (1)
  • src/otel/metrics.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 31, 2026
it still appears in list of columns for entries where it can't be flattened

@coderabbitai coderabbitai Bot left a comment

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/otel/metrics.rs (1)

1112-1135: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Fix the known-field validation test before merge.

At Line 1112, the test expects 37 entries, but the list contains 39 entries. After that correction, Lines 1130-1131 also fail because those fields are intentionally present in the known-field list.

Proposed fix
-        assert_eq!(OTEL_METRICS_KNOWN_FIELD_LIST.len(), 37);
+        assert_eq!(OTEL_METRICS_KNOWN_FIELD_LIST.len(), 39);

...
-            "data_point_quantile_values_quantile",
-            "data_point_quantile_values_value",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/otel/metrics.rs` around lines 1112 - 1135, Update the known-field
validation test around OTEL_METRICS_KNOWN_FIELD_LIST to expect 39 entries
instead of 37. Revise the negative assertions for the intentionally present
fields so they no longer require absence, while preserving absence checks only
for fields that were actually removed from OTEL_METRICS_KNOWN_FIELDS.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/otel/metrics.rs`:
- Around line 1112-1135: Update the known-field validation test around
OTEL_METRICS_KNOWN_FIELD_LIST to expect 39 entries instead of 37. Revise the
negative assertions for the intentionally present fields so they no longer
require absence, while preserving absence checks only for fields that were
actually removed from OTEL_METRICS_KNOWN_FIELDS.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f725bb6-38cd-404d-854d-0c0c395fdb6c

📥 Commits

Reviewing files that changed from the base of the PR and between f9cd2f5 and 6b9589f.

📒 Files selected for processing (1)
  • src/otel/metrics.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 31, 2026
@nitisht
nitisht merged commit c7e9c95 into parseablehq:main Aug 1, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

4 participants