fix(metrics): convert list attribute values to tuples for aggregation key#5303
Open
grvmishra788 wants to merge 4 commits into
Open
fix(metrics): convert list attribute values to tuples for aggregation key#5303grvmishra788 wants to merge 4 commits into
grvmishra788 wants to merge 4 commits into
Conversation
grvmishra788
added a commit
to grvmishra788/opentelemetry-python
that referenced
this pull request
Jun 15, 2026
… key Assisted-by: Claude Opus 4.6
e4cf25c to
0e563e0
Compare
Contributor
|
Hey I also came across this and am proposing a change to the same code in #5266 -- can you take a look and see if my approach would work for you too ? Feel free to add comments to that PR... |
Contributor
|
Can you either run/modify the existing benchmarks we have for metrics and compare the performance before and after introducing these changes? Also, we may want to close/defer this work given that most of this will likely be addressed by #5266 and/or related work. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
When users pass list-valued attributes to metrics (e.g.
{"tags": ["a", "b"]}), the SDK crashes withTypeError: unhashable type: 'list'. This happens becauseconsume_measurement()builds an aggregation key usingfrozenset(attributes.items()), and lists are not hashable.The
Attributestype inopentelemetry-apiexplicitly allowsSequencevalues, including lists. The trace API already handles this correctly through_clean_attribute(), but the metrics path bypasses that function entirely.Before: Passing a list as an attribute value raises a
TypeErrorand drops the measurement.After: Non-string, non-bytes sequence values are converted to tuples when
frozenset()fails. Measurements with[1, 2]and(1, 2)for the same attribute now produce the same aggregation key, which is consistent with how the rest of the SDK treats sequences.The fix uses a try-first approach: it attempts
frozenset(attributes.items())directly, and only falls back to the conversion loop if aTypeErroris raised. This keeps the hot path (all scalar/tuple attributes) at zero overhead. Strings and bytes are explicitly excluded from conversion since they are technically sequences but should stay as-is.Fixes #3750
Type of change
How Has This Been Tested?
tox -e lint-opentelemetry-sdktox -e py314-test-opentelemetry-sdk -- -raDoes This PR Require a Contrib Repo Change?
Checklist:
Notes
Why try-first instead of always converting? As discussed in #3750, performance matters here because this code runs on every measurement. Benchmarking showed three approaches with very different overhead on the common case (all scalar attributes, 4 keys):
isinstance(Sequence)loopisinstance(list)looplist, not allSequencesubclassesfrozenset()firstThe try-first approach wins clearly on the hot path. When lists are present, the exception + retry costs about 3-4 us per measurement, but that only happens once per unique attribute set (subsequent measurements hit the
aggr_key in self._attributes_aggregationcache).Why not use
_clean_attribute()? The API layer's_clean_attribute()function does similar tuple conversion, but it also validates types and logs warnings. Calling it here would add overhead on every measurement for validation that should have already happened at the API boundary.