# "Metrics & Telemetry"
_Path: en/lua/system/metrics_
> "Record application metrics using counters, gauges, and histograms."
## Table of Contents
- Metrics & Telemetry
## Content
# Metrics & Telemetry
The `metrics` module records application counters, gauges, and histogram observations.
This is an API reference. The snippets show one observation at a time and propagate collector errors.
Every function returns `true, nil` after passing the observation to the active collector. If the execution context has no collector, it returns `nil` and a non-retryable `errors.INTERNAL` error.
Labels are optional. Only entries with both a string key and a string value are recorded; other entries are silently ignored. A non-table labels argument is treated as if no labels were supplied.
Metric names are forwarded without local validation.
## Loading
```lua
local metrics = require("metrics")
```
### `metrics.counter_inc`
Increment a counter by one.
```lua
local recorded, err = metrics.counter_inc("requests_total", {method = "POST"})
if err then return nil, err end
return recorded
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Metric name |
| `labels` | table? | Label key-value pairs |
**Returns:** `boolean, error`
### `metrics.counter_add`
Add a value to a counter.
```lua
local recorded, err = metrics.counter_add("bytes_total", 1024, {direction = "out"})
if err then return nil, err end
return recorded
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Metric name |
| `value` | number | Value to add |
| `labels` | table? | Label key-value pairs |
**Returns:** `boolean, error`
The runtime forwards the value unchanged and does not require it to be positive.
### `metrics.gauge_set`
Set a gauge to the current value.
```lua
local recorded, err = metrics.gauge_set("queue_depth", 42, {queue = "emails"})
if err then return nil, err end
return recorded
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Metric name |
| `value` | number | Current value |
| `labels` | table? | Label key-value pairs |
**Returns:** `boolean, error`
### `metrics.gauge_inc`
Increment a gauge by one.
```lua
local recorded, err = metrics.gauge_inc("connections", {pool = "db"})
if err then return nil, err end
return recorded
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Metric name |
| `labels` | table? | Label key-value pairs |
**Returns:** `boolean, error`
### `metrics.gauge_dec`
Decrement a gauge by one.
```lua
local recorded, err = metrics.gauge_dec("connections", {pool = "db"})
if err then return nil, err end
return recorded
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Metric name |
| `labels` | table? | Label key-value pairs |
**Returns:** `boolean, error`
### `metrics.histogram`
Record a histogram observation.
```lua
local recorded, err = metrics.histogram("duration_seconds", 0.123, {method = "GET"})
if err then return nil, err end
return recorded
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Metric name |
| `value` | number | Observed value |
| `labels` | table? | Label key-value pairs |
**Returns:** `boolean, error`
## Errors
| Condition | Kind | Retryable |
|-----------|------|-----------|
| Collector not available | `errors.INTERNAL` | no |
Invalid name or value types raise Lua argument errors instead of returning structured errors.
See [Error Handling](lua/core/errors.md) for working with errors.
## Navigation
Previous: "Terminal I/O" (lua/system/io)
Next: "OS Time" (lua/system/ostime)