Skip to content

Commit ad12e84

Browse files
committed
opentelemetry-api: fix already registered instrumentation check
1 parent 415c94f commit ad12e84

File tree

2 files changed

+87
-16
lines changed

2 files changed

+87
-16
lines changed

opentelemetry-api/src/opentelemetry/metrics/_internal/__init__.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
from logging import getLogger
4646
from os import environ
4747
from threading import Lock
48-
from typing import List, Optional, Sequence, Set, Tuple, Union, cast
48+
from typing import Dict, List, Optional, Sequence, Tuple, Union, cast
4949

5050
from opentelemetry.environment_variables import OTEL_PYTHON_METER_PROVIDER
5151
from opentelemetry.metrics._internal.instrument import (
@@ -194,7 +194,7 @@ def __init__(
194194
self._name = name
195195
self._version = version
196196
self._schema_url = schema_url
197-
self._instrument_ids: Set[str] = set()
197+
self._instrument_ids: Dict[str, str] = {}
198198
self._instrument_ids_lock = Lock()
199199

200200
@property
@@ -222,25 +222,25 @@ def _is_instrument_registered(
222222
self, name: str, type_: type, unit: str, description: str
223223
) -> Tuple[bool, str]:
224224
"""
225-
Check if an instrument with the same name, type, unit and description
226-
has been registered already.
225+
Check if an instrument with the same name and type but different
226+
unit or description has been registered already.
227227
228228
Returns a tuple. The first value is `True` if the instrument has been
229229
registered already, `False` otherwise. The second value is the
230230
instrument id.
231231
"""
232232

233-
instrument_id = ",".join(
234-
[name.strip().lower(), type_.__name__, unit, description]
235-
)
233+
instrument_id = ",".join([name.strip().lower(), type_.__name__])
234+
instrument_value = ",".join([unit, description])
236235

237236
result = False
238237

239238
with self._instrument_ids_lock:
240-
if instrument_id in self._instrument_ids:
239+
current_value = self._instrument_ids.get(instrument_id)
240+
if current_value is not None and current_value != instrument_value:
241241
result = True
242242
else:
243-
self._instrument_ids.add(instrument_id)
243+
self._instrument_ids[instrument_id] = instrument_value
244244

245245
return (result, instrument_id)
246246

opentelemetry-api/tests/metrics/test_meter.py

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,42 @@ def create_observable_up_down_counter(
6161

6262

6363
class TestMeter(TestCase):
64-
# pylint: disable=no-member
65-
def test_repeated_instrument_names(self):
64+
def test_no_warnings_on_repeated_instrument_names(self):
65+
try:
66+
test_meter = NoOpMeter("name")
67+
68+
test_meter.create_counter("counter")
69+
test_meter.create_up_down_counter("up_down_counter")
70+
test_meter.create_observable_counter("observable_counter", Mock())
71+
test_meter.create_histogram("histogram")
72+
test_meter.create_gauge("gauge")
73+
test_meter.create_observable_gauge("observable_gauge", Mock())
74+
test_meter.create_observable_up_down_counter(
75+
"observable_up_down_counter", Mock()
76+
)
77+
except Exception as error: # pylint: disable=broad-exception-caught
78+
self.fail(f"Unexpected exception raised {error}")
79+
80+
for instrument_name in [
81+
"counter",
82+
"up_down_counter",
83+
"histogram",
84+
"gauge",
85+
]:
86+
with self.assertNoLogs(level=WARNING):
87+
create_func = getattr(test_meter, f"create_{instrument_name}")
88+
create_func(instrument_name)
89+
90+
for instrument_name in [
91+
"observable_counter",
92+
"observable_gauge",
93+
"observable_up_down_counter",
94+
]:
95+
with self.assertNoLogs(level=WARNING):
96+
create_func = getattr(test_meter, f"create_{instrument_name}")
97+
create_func(instrument_name, Mock())
98+
99+
def test_warnings_on_repeated_instrument_names_with_different_unit(self):
66100
try:
67101
test_meter = NoOpMeter("name")
68102

@@ -85,18 +119,55 @@ def test_repeated_instrument_names(self):
85119
"gauge",
86120
]:
87121
with self.assertLogs(level=WARNING):
88-
getattr(test_meter, f"create_{instrument_name}")(
89-
instrument_name
90-
)
122+
create_func = getattr(test_meter, f"create_{instrument_name}")
123+
create_func(instrument_name, unit="a unit")
124+
125+
for instrument_name in [
126+
"observable_counter",
127+
"observable_gauge",
128+
"observable_up_down_counter",
129+
]:
130+
with self.assertLogs(level=WARNING):
131+
create_func = getattr(test_meter, f"create_{instrument_name}")
132+
create_func(instrument_name, Mock(), unit="a unit")
133+
134+
def test_warnings_on_repeated_instrument_names_with_different_description(
135+
self,
136+
):
137+
try:
138+
test_meter = NoOpMeter("name")
139+
140+
test_meter.create_counter("counter")
141+
test_meter.create_up_down_counter("up_down_counter")
142+
test_meter.create_observable_counter("observable_counter", Mock())
143+
test_meter.create_histogram("histogram")
144+
test_meter.create_gauge("gauge")
145+
test_meter.create_observable_gauge("observable_gauge", Mock())
146+
test_meter.create_observable_up_down_counter(
147+
"observable_up_down_counter", Mock()
148+
)
149+
except Exception as error: # pylint: disable=broad-exception-caught
150+
self.fail(f"Unexpected exception raised {error}")
151+
152+
for instrument_name in [
153+
"counter",
154+
"up_down_counter",
155+
"histogram",
156+
"gauge",
157+
]:
158+
with self.assertLogs(level=WARNING):
159+
create_func = getattr(test_meter, f"create_{instrument_name}")
160+
create_func(instrument_name, description="a description")
91161

92162
for instrument_name in [
93163
"observable_counter",
94164
"observable_gauge",
95165
"observable_up_down_counter",
96166
]:
97167
with self.assertLogs(level=WARNING):
98-
getattr(test_meter, f"create_{instrument_name}")(
99-
instrument_name, Mock()
168+
create_func = getattr(test_meter, f"create_{instrument_name}")
169+
create_func(
170+
instrument_name, Mock(), description="a description"
100171
)
101172

102173
def test_create_counter(self):

0 commit comments

Comments
 (0)