Skip to content

Commit b83c786

Browse files
authored
Allow new context argument of metric instrument methods to be passed positionally (#616)
1 parent be4bad5 commit b83c786

File tree

2 files changed

+55
-26
lines changed

2 files changed

+55
-26
lines changed

logfire/_internal/metrics.py

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
import dataclasses
44
from abc import ABC, abstractmethod
55
from threading import Lock
6-
from typing import Any, Generic, Sequence, TypedDict, TypeVar
6+
from typing import Any, Generic, Sequence, TypeVar
77
from weakref import WeakSet
88

9-
from opentelemetry.context import Context
109
from opentelemetry.metrics import (
1110
CallbackT,
1211
Counter,
@@ -21,7 +20,6 @@
2120
)
2221
from opentelemetry.sdk.metrics import MeterProvider as SDKMeterProvider
2322
from opentelemetry.util.types import Attributes
24-
from typing_extensions import Unpack
2523

2624
try:
2725
# This only exists in opentelemetry-sdk>=1.23.0
@@ -213,17 +211,6 @@ def create_observable_up_down_counter(
213211
InstrumentT = TypeVar('InstrumentT', bound=Instrument)
214212

215213

216-
class MaybeContext(TypedDict, total=False):
217-
"""Backward-compatible keyword arguments for methods like `Counter.add`.
218-
219-
Starting with opentelemetry-sdk 1.28.0, these methods accept an additional optional `context` argument.
220-
This is passed to the underlying instrument using `**kwargs` for compatibility with older versions.
221-
This is the type hint for those kwargs.
222-
"""
223-
224-
context: Context | None
225-
226-
227214
class _ProxyInstrument(ABC, Generic[InstrumentT]):
228215
def __init__(
229216
self,
@@ -263,26 +250,30 @@ def __init__(
263250

264251

265252
class _ProxyCounter(_ProxyInstrument[Counter], Counter):
266-
def add( # type: ignore
253+
def add(
267254
self,
268255
amount: int | float,
269256
attributes: Attributes | None = None,
270-
**kwargs: Unpack[MaybeContext],
257+
# Starting with opentelemetry-sdk 1.28.0, these methods accept an additional optional `context` argument.
258+
# This is passed to the underlying instrument using `*args, **kwargs` for compatibility with older versions.
259+
*args: Any,
260+
**kwargs: Any,
271261
) -> None:
272-
self._instrument.add(amount, attributes, **kwargs)
262+
self._instrument.add(amount, attributes, *args, **kwargs)
273263

274264
def _create_real_instrument(self, meter: Meter) -> Counter:
275265
return meter.create_counter(self._name, self._unit, self._description)
276266

277267

278268
class _ProxyHistogram(_ProxyInstrument[Histogram], Histogram):
279-
def record( # type: ignore
269+
def record(
280270
self,
281271
amount: int | float,
282272
attributes: Attributes | None = None,
283-
**kwargs: Unpack[MaybeContext],
273+
*args: Any,
274+
**kwargs: Any,
284275
) -> None:
285-
self._instrument.record(amount, attributes, **kwargs)
276+
self._instrument.record(amount, attributes, *args, **kwargs)
286277

287278
def _create_real_instrument(self, meter: Meter) -> Histogram:
288279
return meter.create_histogram(self._name, self._unit, self._description)
@@ -310,13 +301,14 @@ def _create_real_instrument(self, meter: Meter) -> ObservableUpDownCounter: # p
310301

311302

312303
class _ProxyUpDownCounter(_ProxyInstrument[UpDownCounter], UpDownCounter):
313-
def add( # type: ignore
304+
def add(
314305
self,
315306
amount: int | float,
316307
attributes: Attributes | None = None,
317-
**kwargs: Unpack[MaybeContext],
308+
*args: Any,
309+
**kwargs: Any,
318310
) -> None:
319-
self._instrument.add(amount, attributes, **kwargs)
311+
self._instrument.add(amount, attributes, *args, **kwargs)
320312

321313
def _create_real_instrument(self, meter: Meter) -> UpDownCounter:
322314
return meter.create_up_down_counter(self._name, self._unit, self._description)
@@ -325,13 +317,14 @@ def _create_real_instrument(self, meter: Meter) -> UpDownCounter:
325317
if Gauge is not None: # pragma: no branch
326318

327319
class _ProxyGauge(_ProxyInstrument[Gauge], Gauge):
328-
def set( # type: ignore
320+
def set(
329321
self,
330322
amount: int | float,
331323
attributes: Attributes | None = None,
332-
**kwargs: Unpack[MaybeContext],
324+
*args: Any,
325+
**kwargs: Any,
333326
) -> None: # pragma: no cover
334-
self._instrument.set(amount, attributes, **kwargs)
327+
self._instrument.set(amount, attributes, *args, **kwargs)
335328

336329
def _create_real_instrument(self, meter: Meter): # pragma: no cover
337330
return meter.create_gauge(self._name, self._unit, self._description)

tests/test_metrics.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import requests
88
from dirty_equals import IsInt
99
from inline_snapshot import snapshot
10+
from opentelemetry import metrics
1011
from opentelemetry.metrics import CallbackOptions, Observation
1112
from opentelemetry.sdk.metrics._internal.export import MetricExporter, MetricExportResult
1213
from opentelemetry.sdk.metrics.export import AggregationTemporality, InMemoryMetricReader, MetricsData
@@ -15,6 +16,41 @@
1516
import logfire._internal.metrics
1617
from logfire._internal.exporters.quiet_metrics import QuietMetricExporter
1718

19+
meter = metrics.get_meter('global_test_meter')
20+
21+
global_test_counter = meter.create_counter(name='global_test_counter')
22+
23+
24+
def test_global_test_counter(metrics_reader: InMemoryMetricReader) -> None:
25+
global_test_counter.add(1)
26+
global_test_counter.add(20)
27+
metrics_reader.collect()
28+
global_test_counter.add(300)
29+
global_test_counter.add(4000)
30+
31+
assert get_collected_metrics(metrics_reader) == snapshot(
32+
[
33+
{
34+
'name': 'global_test_counter',
35+
'description': '',
36+
'unit': '',
37+
'data': {
38+
'data_points': [
39+
{
40+
'attributes': {},
41+
'start_time_unix_nano': IsInt(),
42+
'time_unix_nano': IsInt(),
43+
'value': 300 + 4000,
44+
'exemplars': [],
45+
}
46+
],
47+
'aggregation_temporality': AggregationTemporality.DELTA,
48+
'is_monotonic': True,
49+
},
50+
}
51+
]
52+
)
53+
1854

1955
def test_create_metric_counter(metrics_reader: InMemoryMetricReader) -> None:
2056
counter = logfire.metric_counter('counter')

0 commit comments

Comments
 (0)