0
# Metrics Collection
1
2
Comprehensive metrics collection capabilities for recording measurements in distributed systems. OpenTelemetry metrics provide both synchronous and asynchronous instruments for counters, gauges, histograms, and observable metrics with rich dimensional attributes.
3
4
## Capabilities
5
6
### Meter Creation and Management
7
8
Get meters for creating measurement instruments with proper instrumentation scope identification.
9
10
```python { .api }
11
def get_meter(
12
instrumenting_module_name: str,
13
instrumenting_library_version: Optional[str] = None,
14
meter_provider: Optional[MeterProvider] = None,
15
schema_url: Optional[str] = None,
16
attributes: Optional[Attributes] = None,
17
) -> Meter:
18
"""
19
Returns a Meter for use by the given instrumentation library.
20
21
Parameters:
22
- instrumenting_module_name: The name of the instrumentation scope
23
- instrumenting_library_version: Optional version of the instrumentation library
24
- meter_provider: Optional specific MeterProvider to use
25
- schema_url: Optional Schema URL of the emitted telemetry
26
- attributes: Optional attributes of the emitted telemetry
27
28
Returns:
29
Meter instance for creating instruments
30
"""
31
32
def get_meter_provider() -> MeterProvider:
33
"""Gets the current global MeterProvider object."""
34
35
def set_meter_provider(meter_provider: MeterProvider) -> None:
36
"""
37
Sets the current global MeterProvider object.
38
This can only be done once, a warning will be logged if any further attempt is made.
39
"""
40
```
41
42
### Synchronous Instruments
43
44
Create instruments for immediate measurement recording during code execution.
45
46
```python { .api }
47
class Meter(ABC):
48
def create_counter(
49
self,
50
name: str,
51
unit: str = "",
52
description: str = "",
53
) -> Counter:
54
"""
55
Creates a Counter instrument for recording monotonically increasing values.
56
57
Parameters:
58
- name: The name of the instrument
59
- unit: Optional unit of measurement
60
- description: Optional description of what the instrument measures
61
62
Returns:
63
Counter instrument for recording increasing values
64
"""
65
66
def create_up_down_counter(
67
self,
68
name: str,
69
unit: str = "",
70
description: str = "",
71
) -> UpDownCounter:
72
"""
73
Creates an UpDownCounter instrument for values that can increase and decrease.
74
75
Parameters:
76
- name: The name of the instrument
77
- unit: Optional unit of measurement
78
- description: Optional description of what the instrument measures
79
80
Returns:
81
UpDownCounter instrument for recording values that go up and down
82
"""
83
84
def create_histogram(
85
self,
86
name: str,
87
unit: str = "",
88
description: str = "",
89
) -> Histogram:
90
"""
91
Creates a Histogram instrument for recording distributions of values.
92
93
Parameters:
94
- name: The name of the instrument
95
- unit: Optional unit of measurement
96
- description: Optional description of what the instrument measures
97
98
Returns:
99
Histogram instrument for recording value distributions
100
"""
101
102
def create_gauge(
103
self,
104
name: str,
105
unit: str = "",
106
description: str = "",
107
) -> Gauge:
108
"""
109
Creates a Gauge instrument for recording current values.
110
111
Parameters:
112
- name: The name of the instrument
113
- unit: Optional unit of measurement
114
- description: Optional description of what the instrument measures
115
116
Returns:
117
Gauge instrument for recording current values
118
"""
119
```
120
121
### Counter Operations
122
123
Record monotonically increasing values like request counts, bytes processed, or errors.
124
125
```python { .api }
126
class Counter(Instrument):
127
"""Synchronous counter instrument for monotonically increasing values."""
128
129
def add(
130
self,
131
amount: Union[int, float],
132
attributes: Attributes = None,
133
) -> None:
134
"""
135
Records an increment to the counter.
136
137
Parameters:
138
- amount: The increment amount (must be non-negative)
139
- attributes: Optional attributes to associate with the measurement
140
"""
141
142
class NoOpCounter(Counter):
143
"""No-op implementation of Counter."""
144
145
def add(
146
self,
147
amount: Union[int, float],
148
attributes: Attributes = None,
149
) -> None:
150
"""No-op add implementation."""
151
```
152
153
### UpDownCounter Operations
154
155
Record values that can both increase and decrease like queue sizes, active connections, or memory usage.
156
157
```python { .api }
158
class UpDownCounter(Instrument):
159
"""Synchronous up-down counter for values that can increase and decrease."""
160
161
def add(
162
self,
163
amount: Union[int, float],
164
attributes: Attributes = None,
165
) -> None:
166
"""
167
Records a change to the up-down counter.
168
169
Parameters:
170
- amount: The change amount (can be positive or negative)
171
- attributes: Optional attributes to associate with the measurement
172
"""
173
174
class NoOpUpDownCounter(UpDownCounter):
175
"""No-op implementation of UpDownCounter."""
176
177
def add(
178
self,
179
amount: Union[int, float],
180
attributes: Attributes = None,
181
) -> None:
182
"""No-op add implementation."""
183
```
184
185
### Histogram Operations
186
187
Record distributions of values like request durations, response sizes, or temperature readings.
188
189
```python { .api }
190
class Histogram(Instrument):
191
"""Synchronous histogram instrument for recording value distributions."""
192
193
def record(
194
self,
195
amount: Union[int, float],
196
attributes: Attributes = None,
197
) -> None:
198
"""
199
Records a measurement to the histogram.
200
201
Parameters:
202
- amount: The value to record
203
- attributes: Optional attributes to associate with the measurement
204
"""
205
206
class NoOpHistogram(Histogram):
207
"""No-op implementation of Histogram."""
208
209
def record(
210
self,
211
amount: Union[int, float],
212
attributes: Attributes = None,
213
) -> None:
214
"""No-op record implementation."""
215
```
216
217
### Gauge Operations
218
219
Record current values like CPU usage, memory consumption, or current temperature.
220
221
```python { .api }
222
class Gauge(Instrument):
223
"""Synchronous gauge instrument for recording current values."""
224
225
def set(
226
self,
227
amount: Union[int, float],
228
attributes: Attributes = None,
229
) -> None:
230
"""
231
Records a measurement to the gauge.
232
233
Parameters:
234
- amount: The current value to record
235
- attributes: Optional attributes to associate with the measurement
236
"""
237
238
class NoOpGauge(Gauge):
239
"""No-op implementation of Gauge."""
240
241
def set(
242
self,
243
amount: Union[int, float],
244
attributes: Attributes = None,
245
) -> None:
246
"""No-op set implementation."""
247
```
248
249
### Asynchronous Instruments
250
251
Create callback-based instruments for periodic measurement collection.
252
253
```python { .api }
254
class Meter(ABC):
255
def create_observable_counter(
256
self,
257
name: str,
258
callbacks: Optional[Sequence[CallbackT]] = None,
259
unit: str = "",
260
description: str = "",
261
) -> ObservableCounter:
262
"""
263
Creates an ObservableCounter for callback-based monotonic measurements.
264
265
Parameters:
266
- name: The name of the instrument
267
- callbacks: Optional sequence of callback functions
268
- unit: Optional unit of measurement
269
- description: Optional description of what the instrument measures
270
271
Returns:
272
ObservableCounter instrument for callback-based counting
273
"""
274
275
def create_observable_up_down_counter(
276
self,
277
name: str,
278
callbacks: Optional[Sequence[CallbackT]] = None,
279
unit: str = "",
280
description: str = "",
281
) -> ObservableUpDownCounter:
282
"""
283
Creates an ObservableUpDownCounter for callback-based bidirectional measurements.
284
285
Parameters:
286
- name: The name of the instrument
287
- callbacks: Optional sequence of callback functions
288
- unit: Optional unit of measurement
289
- description: Optional description of what the instrument measures
290
291
Returns:
292
ObservableUpDownCounter instrument for callback-based up-down counting
293
"""
294
295
def create_observable_gauge(
296
self,
297
name: str,
298
callbacks: Optional[Sequence[CallbackT]] = None,
299
unit: str = "",
300
description: str = "",
301
) -> ObservableGauge:
302
"""
303
Creates an ObservableGauge for callback-based current value measurements.
304
305
Parameters:
306
- name: The name of the instrument
307
- callbacks: Optional sequence of callback functions
308
- unit: Optional unit of measurement
309
- description: Optional description of what the instrument measures
310
311
Returns:
312
ObservableGauge instrument for callback-based gauge measurements
313
"""
314
```
315
316
### Observable Instrument Types
317
318
Asynchronous instruments that use callbacks for measurement collection.
319
320
```python { .api }
321
class ObservableCounter(Asynchronous):
322
"""Asynchronous counter instrument using callbacks."""
323
324
class NoOpObservableCounter(ObservableCounter):
325
"""No-op implementation of ObservableCounter."""
326
327
class ObservableUpDownCounter(Asynchronous):
328
"""Asynchronous up-down counter instrument using callbacks."""
329
330
class NoOpObservableUpDownCounter(ObservableUpDownCounter):
331
"""No-op implementation of ObservableUpDownCounter."""
332
333
class ObservableGauge(Asynchronous):
334
"""Asynchronous gauge instrument using callbacks."""
335
336
class NoOpObservableGauge(ObservableGauge):
337
"""No-op implementation of ObservableGauge."""
338
```
339
340
### Callback System
341
342
Configure callback functions for asynchronous measurement collection.
343
344
```python { .api }
345
class CallbackOptions:
346
"""Options for instrument callbacks."""
347
348
def __init__(self, timeout_millis: float = 10000) -> None:
349
"""
350
Parameters:
351
- timeout_millis: Timeout for callback execution in milliseconds
352
"""
353
354
class Observation:
355
"""Single measurement observation from a callback."""
356
357
def __init__(
358
self,
359
value: Union[int, float],
360
attributes: Attributes = None,
361
) -> None:
362
"""
363
Parameters:
364
- value: The observed measurement value
365
- attributes: Optional attributes for the observation
366
"""
367
368
@property
369
def value(self) -> Union[int, float]:
370
"""Returns the observation value."""
371
372
@property
373
def attributes(self) -> Attributes:
374
"""Returns the observation attributes."""
375
376
CallbackT = Callable[[CallbackOptions], Iterable[Observation]]
377
```
378
379
### Base Instrument Classes
380
381
Abstract base classes defining the instrument hierarchy.
382
383
```python { .api }
384
class Instrument(ABC):
385
"""Base class for all measurement instruments."""
386
387
@property
388
def name(self) -> str:
389
"""Returns the instrument name."""
390
391
@property
392
def description(self) -> str:
393
"""Returns the instrument description."""
394
395
@property
396
def unit(self) -> str:
397
"""Returns the instrument unit."""
398
399
class Synchronous(Instrument):
400
"""Base class for synchronous instruments that record measurements immediately."""
401
402
class Asynchronous(Instrument):
403
"""Base class for asynchronous instruments that use callbacks for measurement."""
404
```
405
406
### Provider Implementations
407
408
Provider classes for different deployment scenarios.
409
410
```python { .api }
411
class MeterProvider(ABC):
412
"""Abstract base class for meter providers."""
413
414
def get_meter(
415
self,
416
instrumenting_module_name: str,
417
instrumenting_library_version: Optional[str] = None,
418
schema_url: Optional[str] = None,
419
attributes: Optional[Attributes] = None,
420
) -> Meter:
421
"""Returns a Meter for use by the given instrumentation library."""
422
423
class NoOpMeterProvider(MeterProvider):
424
"""The default MeterProvider, used when no implementation is available."""
425
426
def get_meter(
427
self,
428
instrumenting_module_name: str,
429
instrumenting_library_version: Optional[str] = None,
430
schema_url: Optional[str] = None,
431
attributes: Optional[Attributes] = None,
432
) -> Meter:
433
"""Returns a no-op meter."""
434
435
class NoOpMeter(Meter):
436
"""No-op implementation of Meter."""
437
438
def create_counter(self, name: str, **kwargs) -> Counter:
439
"""Returns a no-op counter."""
440
441
def create_up_down_counter(self, name: str, **kwargs) -> UpDownCounter:
442
"""Returns a no-op up-down counter."""
443
444
def create_histogram(self, name: str, **kwargs) -> Histogram:
445
"""Returns a no-op histogram."""
446
447
def create_gauge(self, name: str, **kwargs) -> Gauge:
448
"""Returns a no-op gauge."""
449
450
def create_observable_counter(self, name: str, **kwargs) -> ObservableCounter:
451
"""Returns a no-op observable counter."""
452
453
def create_observable_up_down_counter(self, name: str, **kwargs) -> ObservableUpDownCounter:
454
"""Returns a no-op observable up-down counter."""
455
456
def create_observable_gauge(self, name: str, **kwargs) -> ObservableGauge:
457
"""Returns a no-op observable gauge."""
458
```
459
460
## Usage Examples
461
462
### Basic Counter Usage
463
464
```python
465
from opentelemetry import metrics
466
467
# Get a meter
468
meter = metrics.get_meter(__name__)
469
470
# Create a counter for tracking requests
471
request_counter = meter.create_counter(
472
name="http_requests_total",
473
description="Total number of HTTP requests",
474
unit="1"
475
)
476
477
# Record measurements
478
request_counter.add(1, {"method": "GET", "endpoint": "/api/users"})
479
request_counter.add(1, {"method": "POST", "endpoint": "/api/users"})
480
```
481
482
### Histogram for Latency Tracking
483
484
```python
485
from opentelemetry import metrics
486
import time
487
488
meter = metrics.get_meter(__name__)
489
490
# Create a histogram for request duration
491
duration_histogram = meter.create_histogram(
492
name="http_request_duration_seconds",
493
description="HTTP request duration in seconds",
494
unit="s"
495
)
496
497
# Track request duration
498
start_time = time.time()
499
# ... handle request ...
500
duration = time.time() - start_time
501
502
duration_histogram.record(duration, {
503
"method": "GET",
504
"status_code": "200",
505
"endpoint": "/api/data"
506
})
507
```
508
509
### Observable Metrics with Callbacks
510
511
```python
512
from opentelemetry import metrics
513
from opentelemetry.metrics import CallbackOptions, Observation
514
import psutil
515
516
meter = metrics.get_meter(__name__)
517
518
def get_cpu_usage(options: CallbackOptions):
519
"""Callback function to collect CPU usage."""
520
cpu_percent = psutil.cpu_percent()
521
return [Observation(cpu_percent, {"cpu": "all"})]
522
523
# Create observable gauge with callback
524
cpu_gauge = meter.create_observable_gauge(
525
name="system_cpu_usage_percent",
526
description="Current CPU usage percentage",
527
unit="%",
528
callbacks=[get_cpu_usage]
529
)
530
```
531
532
### Up-Down Counter for Active Connections
533
534
```python
535
from opentelemetry import metrics
536
537
meter = metrics.get_meter(__name__)
538
539
# Create up-down counter for active connections
540
active_connections = meter.create_up_down_counter(
541
name="active_connections",
542
description="Number of active connections",
543
unit="1"
544
)
545
546
# Track connection lifecycle
547
def on_connection_open():
548
active_connections.add(1, {"protocol": "http"})
549
550
def on_connection_close():
551
active_connections.add(-1, {"protocol": "http"})
552
```