open-telemetry / open-telemetry/opentelemetry-python
View identity-conflict warning never fires when the conflicting views match the same instrument
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 19
Description
Describe your environment
- OS: any (verified on macOS)
- Python version: any supported (verified on Python 3.10)
- SDK version: current
main(96df63ad); the gap exists since the warning was introduced in #2608 - API version: same as SDK
What happened?
MetricReaderStorage._handle_view_instrument_match warns when a new
_ViewInstrumentMatch conflicts with an existing one ("Views %s and %s will
cause conflicting metrics identities"). The conflict check only iterates
self._instrument_view_instrument_matches.values() — the matches of
previously seen instruments. The list being built for the current
instrument is only written into that dict after all views are processed
(_get_or_init_view_instrument_match), so when two views match the same
instrument and produce identical stream identities, the conflict is invisible
to the check: both streams are exported under the same name in one payload and
nothing is logged.
The spec requires the warning
(https://opentelemetry.io/docs/specs/otel/metrics/sdk/#view):
If applying the View results in conflicting metric identities the
implementation SHOULD apply the View and emit a warning.
The SDK does the "apply" half (both streams are exported) but skips the
"emit a warning" half in exactly the case that is easiest to hit — e.g. two
views selecting different attribute_keys for the same instrument without
renaming one of them.
Steps to Reproduce
import logging
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import InMemoryMetricReader
from opentelemetry.sdk.metrics.view import View
logging.basicConfig(level=logging.WARNING)
reader = InMemoryMetricReader()
mp = MeterProvider(
metric_readers=[reader],
views=[
View(instrument_name="requests", attribute_keys={"path"}),
View(instrument_name="requests", attribute_keys={"method"}),
],
)
counter = mp.get_meter("m").create_counter("requests", unit="1")
counter.add(1, {"path": "/a", "method": "GET"})
md = reader.get_metrics_data()
print([m.name for m in md.resource_metrics[0].scope_metrics[0].metrics])
# ['requests', 'requests'] — duplicate identity in one payload, no warning
Control: the same conflict split across two instruments
(View(instrument_name="c1", name="foo") + View(instrument_name="c2", name="foo")) does log the warning, so only the same-instrument path is affected.
Expected Result
A "Views ... will cause conflicting metrics identities" warning is emitted,
the same as when the conflicting views match different instruments.
Actual Result
No warning. Two metrics with identical identity (same name, unit, aggregation)
are silently exported in the same payload, which backends treat as a duplicate
/ conflicting stream.
Additional context
Proposed fix (I have a branch ready and can open a PR): include the
in-progress view_instrument_matches list in the conflict scan, e.g.
for existing_view_instrument_matches in (
*self._instrument_view_instrument_matches.values(),
view_instrument_matches,
):
plus two tests extending the existing test_view_instrument_match_conflict_*
series (same-instrument conflict warns; same instrument with different view
names does not).
Would you like to implement a fix?
Yes
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at MetricReaderStorage._handle_view_instrument_match and trace how get_or_init_view_instrument_match records matches for the current instrument. Run the existing test_view_instrument_match_conflict* series first. Done means a same-instrument identity conflict emits the warning, while different view names for the same instrument do not.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- observability
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100