Skip to content

Commit 43288ca

Browse files
authored
Instrument instances are always created through a Meter (#2844)
* Instrument instances are always created through a Meter * Fix lint and add changelog * fix lint
1 parent c9222bf commit 43288ca

File tree

9 files changed

+309
-185
lines changed

9 files changed

+309
-185
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
([#2754](https://github.com/open-telemetry/opentelemetry-python/pull/2754))
1818
- Fix --insecure of CLI argument
1919
([#2696](https://github.com/open-telemetry/opentelemetry-python/pull/2696))
20+
- Instrument instances are always created through a Meter
21+
([#2844](https://github.com/open-telemetry/opentelemetry-python/pull/2844))
2022

2123
## [1.12.0rc2-0.32b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.12.0rc2) - 2022-07-04
2224

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

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@
3131
)
3232
from opentelemetry.metrics import UpDownCounter as APIUpDownCounter
3333
from opentelemetry.sdk.metrics._internal.instrument import (
34-
Counter,
35-
Histogram,
36-
ObservableCounter,
37-
ObservableGauge,
38-
ObservableUpDownCounter,
39-
UpDownCounter,
34+
_Counter,
35+
_Histogram,
36+
_ObservableCounter,
37+
_ObservableGauge,
38+
_ObservableUpDownCounter,
39+
_UpDownCounter,
4040
)
4141
from opentelemetry.sdk.metrics._internal.measurement_consumer import (
4242
MeasurementConsumer,
@@ -72,7 +72,7 @@ def create_counter(self, name, unit="", description="") -> APICounter:
7272
(
7373
is_instrument_registered,
7474
instrument_id,
75-
) = self._is_instrument_registered(name, Counter, unit, description)
75+
) = self._is_instrument_registered(name, _Counter, unit, description)
7676

7777
if is_instrument_registered:
7878
# FIXME #2558 go through all views here and check if this
@@ -89,7 +89,7 @@ def create_counter(self, name, unit="", description="") -> APICounter:
8989
with self._instrument_id_instrument_lock:
9090
return self._instrument_id_instrument[instrument_id]
9191

92-
instrument = Counter(
92+
instrument = _Counter(
9393
name,
9494
self._instrumentation_scope,
9595
self._measurement_consumer,
@@ -109,7 +109,7 @@ def create_up_down_counter(
109109
is_instrument_registered,
110110
instrument_id,
111111
) = self._is_instrument_registered(
112-
name, UpDownCounter, unit, description
112+
name, _UpDownCounter, unit, description
113113
)
114114

115115
if is_instrument_registered:
@@ -127,7 +127,7 @@ def create_up_down_counter(
127127
with self._instrument_id_instrument_lock:
128128
return self._instrument_id_instrument[instrument_id]
129129

130-
instrument = UpDownCounter(
130+
instrument = _UpDownCounter(
131131
name,
132132
self._instrumentation_scope,
133133
self._measurement_consumer,
@@ -147,7 +147,7 @@ def create_observable_counter(
147147
is_instrument_registered,
148148
instrument_id,
149149
) = self._is_instrument_registered(
150-
name, ObservableCounter, unit, description
150+
name, _ObservableCounter, unit, description
151151
)
152152

153153
if is_instrument_registered:
@@ -165,7 +165,7 @@ def create_observable_counter(
165165
with self._instrument_id_instrument_lock:
166166
return self._instrument_id_instrument[instrument_id]
167167

168-
instrument = ObservableCounter(
168+
instrument = _ObservableCounter(
169169
name,
170170
self._instrumentation_scope,
171171
self._measurement_consumer,
@@ -185,7 +185,7 @@ def create_histogram(self, name, unit="", description="") -> APIHistogram:
185185
(
186186
is_instrument_registered,
187187
instrument_id,
188-
) = self._is_instrument_registered(name, Histogram, unit, description)
188+
) = self._is_instrument_registered(name, _Histogram, unit, description)
189189

190190
if is_instrument_registered:
191191
# FIXME #2558 go through all views here and check if this
@@ -202,7 +202,7 @@ def create_histogram(self, name, unit="", description="") -> APIHistogram:
202202
with self._instrument_id_instrument_lock:
203203
return self._instrument_id_instrument[instrument_id]
204204

205-
instrument = Histogram(
205+
instrument = _Histogram(
206206
name,
207207
self._instrumentation_scope,
208208
self._measurement_consumer,
@@ -221,7 +221,7 @@ def create_observable_gauge(
221221
is_instrument_registered,
222222
instrument_id,
223223
) = self._is_instrument_registered(
224-
name, ObservableGauge, unit, description
224+
name, _ObservableGauge, unit, description
225225
)
226226

227227
if is_instrument_registered:
@@ -239,7 +239,7 @@ def create_observable_gauge(
239239
with self._instrument_id_instrument_lock:
240240
return self._instrument_id_instrument[instrument_id]
241241

242-
instrument = ObservableGauge(
242+
instrument = _ObservableGauge(
243243
name,
244244
self._instrumentation_scope,
245245
self._measurement_consumer,
@@ -261,7 +261,9 @@ def create_observable_up_down_counter(
261261
(
262262
is_instrument_registered,
263263
instrument_id,
264-
) = self._is_instrument_registered(name, Counter, unit, description)
264+
) = self._is_instrument_registered(
265+
name, _ObservableUpDownCounter, unit, description
266+
)
265267

266268
if is_instrument_registered:
267269
# FIXME #2558 go through all views here and check if this
@@ -278,7 +280,7 @@ def create_observable_up_down_counter(
278280
with self._instrument_id_instrument_lock:
279281
return self._instrument_id_instrument[instrument_id]
280282

281-
instrument = ObservableUpDownCounter(
283+
instrument = _ObservableUpDownCounter(
282284
name,
283285
self._instrumentation_scope,
284286
self._measurement_consumer,

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545
ObservableGauge,
4646
ObservableUpDownCounter,
4747
UpDownCounter,
48+
_Counter,
49+
_Histogram,
50+
_ObservableCounter,
51+
_ObservableGauge,
52+
_ObservableUpDownCounter,
53+
_UpDownCounter,
4854
)
4955
from opentelemetry.sdk.metrics._internal.point import MetricsData
5056
from opentelemetry.util._once import Once
@@ -164,6 +170,7 @@ class MetricReader(ABC):
164170
# FIXME add :std:envvar:`OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE`
165171
# to the end of the documentation paragraph above.
166172

173+
# pylint: disable=too-many-branches
167174
def __init__(
168175
self,
169176
preferred_temporality: Dict[type, AggregationTemporality] = None,
@@ -189,22 +196,22 @@ def __init__(
189196
== "DELTA"
190197
):
191198
self._instrument_class_temporality = {
192-
Counter: AggregationTemporality.DELTA,
193-
UpDownCounter: AggregationTemporality.CUMULATIVE,
194-
Histogram: AggregationTemporality.DELTA,
195-
ObservableCounter: AggregationTemporality.DELTA,
196-
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
197-
ObservableGauge: AggregationTemporality.CUMULATIVE,
199+
_Counter: AggregationTemporality.DELTA,
200+
_UpDownCounter: AggregationTemporality.CUMULATIVE,
201+
_Histogram: AggregationTemporality.DELTA,
202+
_ObservableCounter: AggregationTemporality.DELTA,
203+
_ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
204+
_ObservableGauge: AggregationTemporality.CUMULATIVE,
198205
}
199206

200207
else:
201208
self._instrument_class_temporality = {
202-
Counter: AggregationTemporality.CUMULATIVE,
203-
UpDownCounter: AggregationTemporality.CUMULATIVE,
204-
Histogram: AggregationTemporality.CUMULATIVE,
205-
ObservableCounter: AggregationTemporality.CUMULATIVE,
206-
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
207-
ObservableGauge: AggregationTemporality.CUMULATIVE,
209+
_Counter: AggregationTemporality.CUMULATIVE,
210+
_UpDownCounter: AggregationTemporality.CUMULATIVE,
211+
_Histogram: AggregationTemporality.CUMULATIVE,
212+
_ObservableCounter: AggregationTemporality.CUMULATIVE,
213+
_ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
214+
_ObservableGauge: AggregationTemporality.CUMULATIVE,
208215
}
209216

210217
if preferred_temporality is not None:
@@ -217,18 +224,69 @@ def __init__(
217224
f"Invalid temporality value found {temporality}"
218225
)
219226

220-
self._instrument_class_temporality.update(preferred_temporality or {})
227+
if preferred_temporality is not None:
228+
for typ, temporality in preferred_temporality.items():
229+
if typ is Counter:
230+
self._instrument_class_temporality[_Counter] = temporality
231+
elif typ is UpDownCounter:
232+
self._instrument_class_temporality[
233+
_UpDownCounter
234+
] = temporality
235+
elif typ is Histogram:
236+
self._instrument_class_temporality[
237+
_Histogram
238+
] = temporality
239+
elif typ is ObservableCounter:
240+
self._instrument_class_temporality[
241+
_ObservableCounter
242+
] = temporality
243+
elif typ is ObservableUpDownCounter:
244+
self._instrument_class_temporality[
245+
_ObservableUpDownCounter
246+
] = temporality
247+
elif typ is ObservableGauge:
248+
self._instrument_class_temporality[
249+
_ObservableGauge
250+
] = temporality
251+
else:
252+
raise Exception(f"Invalid instrument class found {typ}")
253+
221254
self._preferred_temporality = preferred_temporality
222255
self._instrument_class_aggregation = {
223-
Counter: DefaultAggregation(),
224-
UpDownCounter: DefaultAggregation(),
225-
Histogram: DefaultAggregation(),
226-
ObservableCounter: DefaultAggregation(),
227-
ObservableUpDownCounter: DefaultAggregation(),
228-
ObservableGauge: DefaultAggregation(),
256+
_Counter: DefaultAggregation(),
257+
_UpDownCounter: DefaultAggregation(),
258+
_Histogram: DefaultAggregation(),
259+
_ObservableCounter: DefaultAggregation(),
260+
_ObservableUpDownCounter: DefaultAggregation(),
261+
_ObservableGauge: DefaultAggregation(),
229262
}
230263

231-
self._instrument_class_aggregation.update(preferred_aggregation or {})
264+
if preferred_aggregation is not None:
265+
for typ, aggregation in preferred_aggregation.items():
266+
if typ is Counter:
267+
self._instrument_class_aggregation[_Counter] = aggregation
268+
elif typ is UpDownCounter:
269+
self._instrument_class_aggregation[
270+
_UpDownCounter
271+
] = aggregation
272+
elif typ is Histogram:
273+
self._instrument_class_aggregation[
274+
_Histogram
275+
] = aggregation
276+
elif typ is ObservableCounter:
277+
self._instrument_class_aggregation[
278+
_ObservableCounter
279+
] = aggregation
280+
elif typ is ObservableUpDownCounter:
281+
self._instrument_class_aggregation[
282+
_ObservableUpDownCounter
283+
] = aggregation
284+
elif typ is ObservableGauge:
285+
self._instrument_class_aggregation[
286+
_ObservableGauge
287+
] = aggregation
288+
else:
289+
raise Exception(f"Invalid instrument class found {typ}")
232290

233291
@final
234292
def collect(self, timeout_millis: float = 10_000) -> None:

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

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ def callback(
132132

133133

134134
class Counter(_Synchronous, APICounter):
135+
def __new__(cls, *args, **kwargs):
136+
if cls is Counter:
137+
raise TypeError("Counter must be instantiated via a meter.")
138+
return super().__new__(cls)
139+
135140
def add(
136141
self, amount: Union[int, float], attributes: Dict[str, str] = None
137142
):
@@ -146,6 +151,11 @@ def add(
146151

147152

148153
class UpDownCounter(_Synchronous, APIUpDownCounter):
154+
def __new__(cls, *args, **kwargs):
155+
if cls is UpDownCounter:
156+
raise TypeError("UpDownCounter must be instantiated via a meter.")
157+
return super().__new__(cls)
158+
149159
def add(
150160
self, amount: Union[int, float], attributes: Dict[str, str] = None
151161
):
@@ -155,14 +165,29 @@ def add(
155165

156166

157167
class ObservableCounter(_Asynchronous, APIObservableCounter):
158-
pass
168+
def __new__(cls, *args, **kwargs):
169+
if cls is ObservableCounter:
170+
raise TypeError(
171+
"ObservableCounter must be instantiated via a meter."
172+
)
173+
return super().__new__(cls)
159174

160175

161176
class ObservableUpDownCounter(_Asynchronous, APIObservableUpDownCounter):
162-
pass
177+
def __new__(cls, *args, **kwargs):
178+
if cls is ObservableUpDownCounter:
179+
raise TypeError(
180+
"ObservableUpDownCounter must be instantiated via a meter."
181+
)
182+
return super().__new__(cls)
163183

164184

165185
class Histogram(_Synchronous, APIHistogram):
186+
def __new__(cls, *args, **kwargs):
187+
if cls is Histogram:
188+
raise TypeError("Histogram must be instantiated via a meter.")
189+
return super().__new__(cls)
190+
166191
def record(
167192
self, amount: Union[int, float], attributes: Dict[str, str] = None
168193
):
@@ -178,4 +203,34 @@ def record(
178203

179204

180205
class ObservableGauge(_Asynchronous, APIObservableGauge):
206+
def __new__(cls, *args, **kwargs):
207+
if cls is ObservableGauge:
208+
raise TypeError(
209+
"ObservableGauge must be instantiated via a meter."
210+
)
211+
return super().__new__(cls)
212+
213+
214+
# Below classes exist to prevent the direct instantiation
215+
class _Counter(Counter):
216+
pass
217+
218+
219+
class _UpDownCounter(UpDownCounter):
220+
pass
221+
222+
223+
class _ObservableCounter(ObservableCounter):
224+
pass
225+
226+
227+
class _ObservableUpDownCounter(ObservableUpDownCounter):
228+
pass
229+
230+
231+
class _Histogram(Histogram):
232+
pass
233+
234+
235+
class _ObservableGauge(ObservableGauge):
181236
pass

0 commit comments

Comments
 (0)