Skip to content

Commit 90c0319

Browse files
authored
opentelemetry-sdk: fix typing issues for metrics instruments (#5082)
* opentelemetry-sdk: fix typing issues for metrics instruments * Make the _Instrument runtime checkable
1 parent 3ba556f commit 90c0319

6 files changed

Lines changed: 49 additions & 26 deletions

File tree

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/_view_instrument_match.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
from time import time_ns
1919
from typing import Dict, List, Optional, Sequence
2020

21-
from opentelemetry.metrics import Instrument
2221
from opentelemetry.sdk.metrics._internal.aggregation import (
2322
Aggregation,
2423
AggregationTemporality,
2524
DefaultAggregation,
2625
_Aggregation,
2726
_SumAggregation,
2827
)
28+
from opentelemetry.sdk.metrics._internal.instrument import _Instrument
2929
from opentelemetry.sdk.metrics._internal.measurement import Measurement
3030
from opentelemetry.sdk.metrics._internal.point import DataPointT
3131
from opentelemetry.sdk.metrics._internal.view import View
@@ -37,7 +37,7 @@ class _ViewInstrumentMatch:
3737
def __init__(
3838
self,
3939
view: View,
40-
instrument: Instrument,
40+
instrument: _Instrument,
4141
instrument_class_aggregation: Dict[type, Aggregation],
4242
):
4343
self._view = view

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
Asynchronous,
3636
Counter,
3737
Histogram,
38-
Instrument,
3938
ObservableCounter,
4039
ObservableGauge,
4140
ObservableUpDownCounter,
@@ -59,6 +58,7 @@
5958
from opentelemetry.sdk.metrics._internal.exponential_histogram.mapping.logarithm_mapping import (
6059
LogarithmMapping,
6160
)
61+
from opentelemetry.sdk.metrics._internal.instrument import _Instrument
6262
from opentelemetry.sdk.metrics._internal.measurement import Measurement
6363
from opentelemetry.sdk.metrics._internal.point import Buckets as BucketsPoint
6464
from opentelemetry.sdk.metrics._internal.point import (
@@ -1200,7 +1200,7 @@ class Aggregation(ABC):
12001200
@abstractmethod
12011201
def _create_aggregation(
12021202
self,
1203-
instrument: Instrument,
1203+
instrument: _Instrument,
12041204
attributes: Attributes,
12051205
reservoir_factory: Callable[
12061206
[Type[_Aggregation]], ExemplarReservoirBuilder
@@ -1231,7 +1231,7 @@ class DefaultAggregation(Aggregation):
12311231

12321232
def _create_aggregation(
12331233
self,
1234-
instrument: Instrument,
1234+
instrument: _Instrument,
12351235
attributes: Attributes,
12361236
reservoir_factory: Callable[
12371237
[Type[_Aggregation]], ExemplarReservoirBuilder
@@ -1323,7 +1323,7 @@ def __init__(
13231323

13241324
def _create_aggregation(
13251325
self,
1326-
instrument: Instrument,
1326+
instrument: _Instrument,
13271327
attributes: Attributes,
13281328
reservoir_factory: Callable[
13291329
[Type[_Aggregation]], ExemplarReservoirBuilder
@@ -1372,7 +1372,7 @@ def __init__(
13721372

13731373
def _create_aggregation(
13741374
self,
1375-
instrument: Instrument,
1375+
instrument: _Instrument,
13761376
attributes: Attributes,
13771377
reservoir_factory: Callable[
13781378
[Type[_Aggregation]], ExemplarReservoirBuilder
@@ -1416,7 +1416,7 @@ class SumAggregation(Aggregation):
14161416

14171417
def _create_aggregation(
14181418
self,
1419-
instrument: Instrument,
1419+
instrument: _Instrument,
14201420
attributes: Attributes,
14211421
reservoir_factory: Callable[
14221422
[Type[_Aggregation]], ExemplarReservoirBuilder
@@ -1450,7 +1450,7 @@ class LastValueAggregation(Aggregation):
14501450

14511451
def _create_aggregation(
14521452
self,
1453-
instrument: Instrument,
1453+
instrument: _Instrument,
14541454
attributes: Attributes,
14551455
reservoir_factory: Callable[
14561456
[Type[_Aggregation]], ExemplarReservoirBuilder
@@ -1468,7 +1468,7 @@ class DropAggregation(Aggregation):
14681468

14691469
def _create_aggregation(
14701470
self,
1471-
instrument: Instrument,
1471+
instrument: _Instrument,
14721472
attributes: Attributes,
14731473
reservoir_factory: Callable[
14741474
[Type[_Aggregation]], ExemplarReservoirBuilder

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/instrument.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,21 @@
1717

1818
from logging import getLogger
1919
from time import time_ns
20-
from typing import TYPE_CHECKING, Generator, Iterable, List, Sequence, Union
20+
from typing import (
21+
TYPE_CHECKING,
22+
Generator,
23+
Iterable,
24+
List,
25+
Protocol,
26+
Sequence,
27+
Union,
28+
cast,
29+
runtime_checkable,
30+
)
2131

2232
# This kind of import is needed to avoid Sphinx errors.
2333
from opentelemetry.context import Context, get_current
24-
from opentelemetry.metrics import CallbackT
34+
from opentelemetry.metrics import Asynchronous, CallbackT, Synchronous
2535
from opentelemetry.metrics import Counter as APICounter
2636
from opentelemetry.metrics import Histogram as APIHistogram
2737
from opentelemetry.metrics import ObservableCounter as APIObservableCounter
@@ -55,7 +65,15 @@
5565
)
5666

5767

58-
class _Synchronous:
68+
@runtime_checkable
69+
class _Instrument(Protocol):
70+
name: str
71+
unit: str
72+
description: str
73+
instrumentation_scope: InstrumentationScope
74+
75+
76+
class _Synchronous(_Instrument, Synchronous):
5977
def __init__(
6078
self,
6179
name: str,
@@ -79,7 +97,7 @@ def __init__(
7997

8098
name = result["name"]
8199
unit = result["unit"]
82-
description = result["description"]
100+
description = cast(str, result["description"])
83101

84102
self.name = name.lower()
85103
self.unit = unit
@@ -93,13 +111,13 @@ def _is_enabled(self) -> bool:
93111
return self._meter_config is None or self._meter_config.is_enabled
94112

95113

96-
class _Asynchronous:
114+
class _Asynchronous(_Instrument, Asynchronous):
97115
def __init__(
98116
self,
99117
name: str,
100118
instrumentation_scope: InstrumentationScope,
101119
measurement_consumer: MeasurementConsumer,
102-
callbacks: Iterable[CallbackT] | None = None,
120+
callbacks: Sequence[CallbackT] | None = None,
103121
unit: str = "",
104122
description: str = "",
105123
*,
@@ -118,7 +136,7 @@ def __init__(
118136

119137
name = result["name"]
120138
unit = result["unit"]
121-
description = result["description"]
139+
description = cast(str, result["description"])
122140

123141
self.name = name.lower()
124142
self.unit = unit

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from __future__ import annotations
16+
1517
from dataclasses import dataclass
16-
from typing import Union
18+
from typing import TYPE_CHECKING, Union
1719

1820
from opentelemetry.context import Context
19-
from opentelemetry.metrics import Instrument
2021
from opentelemetry.util.types import Attributes
2122

23+
if TYPE_CHECKING:
24+
from opentelemetry.sdk.metrics._internal.instrument import _Instrument
25+
2226

2327
@dataclass(frozen=True)
2428
class Measurement:
@@ -35,6 +39,6 @@ class Measurement:
3539

3640
value: Union[int, float]
3741
time_unix_nano: int
38-
instrument: Instrument
42+
instrument: _Instrument
3943
context: Context
4044
attributes: Attributes = None

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/metric_reader_storage.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from opentelemetry.metrics import (
2121
Asynchronous,
2222
Counter,
23-
Instrument,
2423
ObservableCounter,
2524
)
2625
from opentelemetry.sdk.metrics._internal._view_instrument_match import (
@@ -36,6 +35,7 @@
3635
_LastValueAggregation,
3736
_SumAggregation,
3837
)
38+
from opentelemetry.sdk.metrics._internal.instrument import _Instrument
3939
from opentelemetry.sdk.metrics._internal.measurement import Measurement
4040
from opentelemetry.sdk.metrics._internal.point import (
4141
ExponentialHistogram,
@@ -70,13 +70,13 @@ def __init__(
7070
self._lock = RLock()
7171
self._sdk_config = sdk_config
7272
self._instrument_view_instrument_matches: Dict[
73-
Instrument, List[_ViewInstrumentMatch]
73+
_Instrument, List[_ViewInstrumentMatch]
7474
] = {}
7575
self._instrument_class_temporality = instrument_class_temporality
7676
self._instrument_class_aggregation = instrument_class_aggregation
7777

7878
def _get_or_init_view_instrument_match(
79-
self, instrument: Instrument
79+
self, instrument: _Instrument
8080
) -> List[_ViewInstrumentMatch]:
8181
# Optimistically get the relevant views for the given instrument. Once set for a given
8282
# instrument, the mapping will never change
@@ -253,7 +253,7 @@ def collect(self) -> Optional[MetricsData]:
253253

254254
def _handle_view_instrument_match(
255255
self,
256-
instrument: Instrument,
256+
instrument: _Instrument,
257257
view_instrument_matches: List["_ViewInstrumentMatch"],
258258
) -> None:
259259
for view in self._sdk_config.views:
@@ -292,7 +292,7 @@ def _handle_view_instrument_match(
292292

293293
@staticmethod
294294
def _check_view_instrument_compatibility(
295-
view: View, instrument: Instrument
295+
view: View, instrument: _Instrument
296296
) -> bool:
297297
"""
298298
Checks if a view and an instrument are compatible.

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/view.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
ExemplarReservoirBuilder,
3131
SimpleFixedSizeExemplarReservoir,
3232
)
33+
from opentelemetry.sdk.metrics._internal.instrument import _Instrument
3334

3435
_logger = getLogger(__name__)
3536

@@ -164,7 +165,7 @@ def __init__(
164165

165166
# pylint: disable=too-many-return-statements
166167
# pylint: disable=too-many-branches
167-
def _match(self, instrument: Instrument) -> bool:
168+
def _match(self, instrument: _Instrument) -> bool:
168169
if self._instrument_type is not None:
169170
if not isinstance(instrument, self._instrument_type):
170171
return False

0 commit comments

Comments
 (0)