or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context.mdindex.mdlogging.mdmetrics.mdpropagation.mdtracing.md

metrics.mddocs/

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

```