open-telemetry / open-telemetry/opentelemetry-python
Default-view fallback stream is never checked for conflicting metric identities (warning is order-dependent)
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: (verified on macOS)
- Python version: any supported (verified on Python 3.10)
- SDK version: current
main(96df63ad) - API version: same as SDK
What happened?
MetricReaderStorage has two places that create a metric stream for an
instrument, but only one of them runs the "conflicting metrics identities"
check:
_handle_view_instrument_match— one_ViewInstrumentMatchper matching
View, each checked against every existing match withconflicts().- The
_DEFAULT_VIEWfallback in_get_or_init_view_instrument_match
(used when no view matches the instrument) — appended directly, with no
conflict check at all.
So when a view renames another instrument's stream to the name of an
instrument that itself takes the fallback path, the duplicate identity is
reported only if the renamed instrument happens to record second. If it
records first, the fallback stream is added silently and two streams with
identical identity (name, unit, aggregation) are exported without any
warning.
The spec requires the warning regardless of which stream came first
(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.
This is a follow-up to the same-instrument conflict fix (PR #5627 ), which
closed the equivalent gap between views matching the same instrument but
deliberately left the fallback path out of scope.
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="counter_a", name="counter_b")],
)
meter = mp.get_meter("m")
meter.create_counter("counter_a", unit="u").add(1) # stream renamed to "counter_b"
meter.create_counter("counter_b", unit="u").add(1) # no view matches -> fallback, also "counter_b"
md = reader.get_metrics_data()
print([m.name for m in md.resource_metrics[0].scope_metrics[0].metrics])
# ['counter_b', 'counter_b'] — no warning logged
Swap the two add() calls (so counter_b records first) and the warning
is emitted, because the view match is then checked against the stored
fallback match.
Expected Result
The "Views ... will cause conflicting metrics identities" warning is emitted
in both arrival orders.
Actual Result
No warning when the fallback stream is registered second; two metrics with
identical identity are silently exported in the same payload.
Additional context
Proposed direction: route both stream-creation sites through a single
registration helper that runs the conflict scan (over already-registered
matches plus the in-progress list for the current instrument) before
appending, so the check cannot be bypassed by either path. The warning
message would also need a wording that does not assume both sides are
user-configured views, since one side may be the implicit default view.
Would you like to implement a fix?
Yes
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
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 in MetricReaderStorage at _get_or_init_view_instrument_match and _handle_view_instrument_match, comparing the fallback and view-match registration paths. Reproduce the counter_a/counter_b example in both arrival orders, then add coverage for each case. Done means the conflicting metric identity warning is emitted regardless of which stream is registered first.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- observability-sre
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 74/100