---
url: /logly.zig/api/metrics.md
description: >-
  API reference for Logly.zig Metrics struct. Track record counts, bytes
  written, error rates, per-level statistics, and sink throughput with atomic
  counters.
---

# Metrics API

The `Metrics` struct provides comprehensive observability into the logging system's performance and health.

## Quick Reference: Method Aliases

| Full Method | Alias(es) | Description |
|-------------|-----------|-------------|
| `init()` | `create()` | Initialize metrics |
| `deinit()` | `destroy()` | Deinitialize metrics |
| `initWithConfig()` | `createWithConfig()`, `newWithConfig()` | Initialize with config |
| `recordLog()` | `record()`, `log()` | Record log event |
| `recordDrop()` | `drop()`, `dropped()` | Record dropped event |
| `recordError()` | `recordErr()` | Record error event |
| `getSnapshot()` | `metricsSnapshot()` | Get metrics snapshot |
| `formatLevelBreakdown()` | `levels()`, `breakdown()` | Format level breakdown |
| `reset()` | `clear()` | Reset metrics |
| `uptimeSeconds()` | `uptimeSec()` | Get uptime in seconds |
| `bytesPerSecond()` | `throughput()` | Get bytes per second |
| `setRecordLoggedCallback()` | `onRecordLogged()`, `setOnRecordLogged()` | Set record logged callback |
| `setSnapshotCallback()` | `onSnapshot()`, `setOnSnapshot()` | Set snapshot callback |
| `setThresholdCallback()` | `onThreshold()`, `setOnThreshold()` | Set threshold callback |
| `setErrorCallback()` | `onError()`, `setOnError()` | Set error callback |
| `getConfig()` | `getConfiguration()`, `configuration()` | Get configuration |
| `isEnabled()` | `enabled()`, `isActive()` | Check if enabled |
| `recordLogWithLatency()` | `recordWithLatency()`, `logWithLatency()` | Record log with latency |
| `recordSinkWrite()` | `sinkWrite()`, `recordSinkWriteOp()` | Record sink write |
| `recordSinkError()` | `sinkError()`, `recordSinkErrorOp()` | Record sink error |
| `takeSnapshot()` | `captureSnapshot()`, `takeSnapshotNow()` | Take snapshot |
| `getHistory()` | `getSnapshots()`, `snapshots()` | Get snapshots history |
| `exportMetrics()` | `exportData()`, `toString()` | Export metrics |
| `exportJson()` | `json()`, `toJson()` | Export as JSON |
| `exportPrometheus()` | `prometheus()`, `toPrometheus()` | Export as Prometheus |
| `exportStatsd()` | `statsd()`, `toStatsd()` | Export as StatsD |
| `avgLatencyNs()` | `avgLatency()`, `averageLatency()` | Get average latency |
| `minLatencyNs()` | `minLatency()` | Get minimum latency |
| `maxLatencyNs()` | `maxLatency()` | Get maximum latency |
| `getHistogram()` | `latencyHistogram()`, `getLatencyHistogram()` | Get latency histogram |
| `latencyPercentileNs()` | `latencyPercentile()`, `percentileNs()` | Estimate latency percentile (ns) |
| `latencyPercentileMs()` | `percentileMs()` | Estimate latency percentile (ms) |
| `getLatencySummary()` | `latencySummary()`, `summaryLatency()` | Get latency summary (p50/p95/p99) |
| `format()` | `formatMetrics()`, `stringify()` | Format metrics |
| `recordCustomLog()` | `recordCustom()`, `customLog()` | Record custom log |
| `hasRecords()` | `hasData()` | Check if has records |
| `totalRecordCount()` | `recordCount()`, `totalRecords()` | Get total record count |
| `totalBytesLogged()` | `bytesLogged()`, `totalBytes()` | Get total bytes logged |
| `rate()` | `recordsPerSecond()`, `recordsPerSec()` | Get records per second |
| `errorCount()` | `errorTotal()`, `totalErrors()` | Get error count |
| `droppedCount()` | `dropTotal()`, `totalDropped()` | Get dropped count |
| `errorRate()` | `failureRate()` | Get error rate |
| `dropRate()` | `dropPercentage()` | Get drop rate |
| `hasHighErrorRate()` | `highErrorRate()`, `errorRateHigh()` | Check if high error rate |
| `hasHighDropRate()` | `highDropRate()`, `dropRateHigh()` | Check if high drop rate |
| `levelCount()` | `countForLevel()`, `levelRecords()` | Get level count |
| `sinkCount()` | `sinks()`, `sinkTotal()` | Get sink count |
| `totalSinkErrors()` | `sinkErrorsTotal()` | Get total sink errors |
| `totalSinkFlushes()` | `sinkFlushesTotal()` | Get total sink flushes |
| `lastRecordAgeMs()` | `recordAgeMs()`, `ageSinceLastRecordMs()` | Get age since last record |
| `recordSinkFlush()` | `sinkFlush()`, `recordSinkFlushOp()` | Record sink flush |
| `getSinkMetrics()` | `sinkMetrics()`, `getSinkStats()` | Get sink metrics |
| `getSinkMetricsByName()` | `sinkMetricsByName()`, `getSinkStatsByName()` | Get sink metrics by name |
| `hasErrors()` | `hasFailures()` | Check if has errors |
| `hasDropped()` | `hasDrops()` | Check if has dropped |
| `getRecordsWritten()` | `records()`, `written()` | Get records written (SinkMetrics) |
| `getBytesWritten()` | `bytes()`, `bytesWritten()` | Get bytes written (SinkMetrics) |
| `getWriteErrors()` | `writeErrors()`, `errors()` | Get write errors (SinkMetrics) |
| `getFlushCount()` | `flushes()`, `flushCount()` | Get flush count (SinkMetrics) |
| `hasWritten()` | `hasData()`, `isActive()` | Check if has written (SinkMetrics) |
| `getErrorRate()` | `errorRate()`, `failureRate()` | Get error rate (SinkMetrics) |
| `getSuccessRate()` | `successRate()`, `success()` | Get success rate (SinkMetrics) |
| `avgBytesPerRecord()` | `avgBytes()`, `bytesPerRecord()` | Get avg bytes per record (SinkMetrics) |
| `avgRecordsPerFlush()` | `avgRecords()`, `recordsPerFlush()` | Get avg records per flush (SinkMetrics) |
| `throughputBytesPerSecond()` | `throughput()`, `bytesPerSecond()` | Get throughput (SinkMetrics) |
| `getDropRate()` | `dropRate()`, `dropPercentage()` | Get drop rate (Snapshot) |
| `basic()` | `simple()`, `minimal()` | Basic preset (MetricsPresets) |
| `createMetricsSink()` | `metricsSink()`, `sink()` | Create metrics sink (MetricsPresets) |

## Overview

Metrics tracks record counts, throughput, errors, and per-sink statistics. It uses thread-safe atomic operations for all counters, making it safe for concurrent access without locks on hot paths.

## Export Customization

`Config.MetricsConfig` now includes exporter naming and breakdown controls:

```zig
const cfg = logly.Config.MetricsConfig.production()
    .prometheus()
    .withPrefix("checkout.api")
    .withLatencyHistogram(20)
    .withBreakdowns(true, true);

var metrics = logly.Metrics.initWithConfig(allocator, cfg);
```

Available controls:

| Field / Helper | Purpose |
|----------------|---------|
| `metricPrefix`, `withPrefix()` / `prefix()` | Namespace exported metrics |
| `metricSeparator` | Separator for Prometheus-compatible names |
| `statsdSeparator` | Separator for StatsD metric names |
| `sanitizeNames` | Replace exporter-unsafe characters |
| `exportLevelBreakdown` | Include per-level counters |
| `exportSinkBreakdown` | Include per-sink counters/errors |
| `prometheus()` | Configure Prometheus export naming |
| `statsd()` | Configure StatsD export naming |
| `withAlerts()` / `alerts()` | Configure error/drop thresholds |
| `withLatencyHistogram()` / `histogram()` | Enable latency histogram collection |

### MetricsConfig

Global configuration for metrics collection and export.

```zig
pub const MetricsConfig = struct {
    enabled: bool = false,
    trackLevels: bool = true,
    trackSinks: bool = true,
    trackLatency: bool = false,
    enableHistogram: bool = false,
    histogramBuckets: usize = 20,
    exportFormat: ExportFormat = .none,
    export_interval_ms: u64 = 60000,
    exportLevelBreakdown: bool = true,
    exportSinkBreakdown: bool = true,
    metricPrefix: []const u8 = "logly",
    metricSeparator: []const u8 = "_",
    statsdSeparator: []const u8 = ".",
    sanitizeNames: bool = true,
    
    pub const ExportFormat = enum {
        none,
        json,
        prometheus,
        statsd,
    };
};
```

## Types

### Metrics

The main metrics controller with atomic counters and callback support.

```zig
pub const Metrics = struct {
    totalRecords: std.atomic.Value(u64),
    totalBytes: std.atomic.Value(u64),
    droppedRecords: std.atomic.Value(u64),
    errorCount: std.atomic.Value(u64),
    levelCounts: [10]std.atomic.Value(u64),
    startTime: i64,
    sinkMetrics: std.ArrayList(SinkMetrics),
    
    // Callbacks
    onRecordLogged: ?*const fn (Level, u64) void,
    onMetricsSnapshot: ?*const fn (*const Snapshot) void,
    onThresholdExceeded: ?*const fn (MetricType, u64, u64) void,
    onErrorDetected: ?*const fn (ErrorEvent, u64) void,
};
```

### MetricType

Types of metrics for threshold notifications.

```zig
pub const MetricType = enum {
    totalRecords,
    totalBytes,
    droppedRecords,
    errorCount,
    recordsPerSecond,
    bytesPerSecond,
};
```

### ErrorEvent

Error event types for monitoring.

```zig
pub const ErrorEvent = enum {
    recordsDropped,
    sinkWriteError,
    bufferOverflow,
    samplingDrop,
};
```

### SinkMetrics

Per-sink statistics with atomic counters.

```zig
pub const SinkMetrics = struct {
    name: []const u8,
    recordsWritten: std.atomic.Value(u64),
    bytesWritten: std.atomic.Value(u64),
    writeErrors: std.atomic.Value(u64),
    flushCount: std.atomic.Value(u64),
};
```

#### Getter Methods

| Method | Return | Description |
|--------|--------|-------------|
| `getRecordsWritten()` | `u64` | Get total records written |
| `getBytesWritten()` | `u64` | Get total bytes written |
| `getWriteErrors()` | `u64` | Get write errors count |
| `getFlushCount()` | `u64` | Get flush count |

#### Boolean Checks

| Method | Return | Description |
|--------|--------|-------------|
| `hasWritten()` | `bool` | Check if any records have been written |
| `hasErrors()` | `bool` | Check if any errors have occurred |

#### Rate Calculations

| Method | Return | Description |
|--------|--------|-------------|
| `getErrorRate()` | `f64` | Calculate error rate (0.0 - 1.0) |
| `getSuccessRate()` | `f64` | Calculate success rate (0.0 - 1.0) |
| `avgBytesPerRecord()` | `f64` | Calculate average bytes per record |
| `avgRecordsPerFlush()` | `f64` | Calculate average records per flush |
| `throughputBytesPerSecond(elapsedSeconds)` | `f64` | Calculate bytes per second throughput |

#### Reset

| Method | Description |
|--------|-------------|
| `reset()` | Reset all statistics to initial state |

### Snapshot

A point-in-time snapshot of metrics, useful for reporting.

```zig
pub const Snapshot = struct {
    totalRecords: u64,
    totalBytes: u64,
    droppedRecords: u64,
    errorCount: u64,
    uptimeMs: i64,
    recordsPerSecond: f64,
    bytesPerSecond: f64,
    levelCounts: [10]u64,
    
    pub fn getDropRate(self: *const Snapshot) f64;
};
```

## Methods

### Initialization

#### `init(allocator: std.mem.Allocator) Metrics`

Initializes a new Metrics instance with all counters at zero.

**Alias:** `create`

#### `initWithConfig(allocator: std.mem.Allocator, config: MetricsConfig) Metrics`

Initializes a new Metrics instance with custom configuration.

#### `initWithIo(allocator: std.mem.Allocator, io_handle: std.Io, config: MetricsConfig) Metrics`

Initializes a new Metrics instance with an explicit I/O handle and custom configuration.

#### `deinit(self: *Metrics) void`

Releases all resources associated with metrics.

**Alias:** `destroy`

### Callbacks

#### `setRecordLoggedCallback(callback: *const fn (Level, u64) void) void`

Sets the callback invoked when a record is logged.

#### `setSnapshotCallback(callback: *const fn (*const Snapshot) void) void`

Sets the callback invoked when a metrics snapshot is taken.

#### `setThresholdCallback(callback: *const fn (MetricType, u64, u64) void) void`

Sets the callback invoked when metrics exceed thresholds.

#### `setErrorCallback(callback: *const fn (ErrorEvent, u64) void) void`

Sets the callback invoked when errors or dropped records are detected.

### Configuration

#### `getConfig() MetricsConfig`

Returns the current metrics configuration.

#### `isEnabled() bool`

Returns true if metrics collection is enabled.

### Recording

#### `recordLog(level: Level, bytes: u64) void`

Records a successful log event with its level and size.

**Alias**: `record`, `log`

#### `recordLogWithLatency(level: Level, bytes: u64, latencyNs: u64) void`

Records a log with latency measurement for histogram tracking.

#### `recordDrop() void`

Records a dropped log event (e.g., due to buffer overflow).

**Alias**: `drop`, `dropped`

#### `recordError() void`

Records an internal error.

**Alias**: `recordErr`

#### `recordCustomLog(bytes: u64) void`

Records a log using a custom level.

### Sink Tracking

#### `addSink(name: []const u8) !usize`

Adds a sink to track. Returns the sink index.

#### `recordSinkWrite(sinkIndex: usize, bytes: u64) void`

Records a successful write to a sink.

#### `recordSinkError(sinkIndex: usize) void`

Records a write error on a sink.

#### `recordSinkFlush(sinkIndex: usize) void`

Records a flush operation on a sink.

#### `getSinkMetrics(sinkIndex: usize) ?SinkMetrics`

Returns sink metrics by index.

#### `getSinkMetricsByName(name: []const u8) ?SinkMetrics`

Returns sink metrics by name.

### Snapshots

#### `getSnapshot() Snapshot`

Returns a thread-safe snapshot of the current metrics.

**Alias**: `metricsSnapshot`

#### `takeSnapshot() !Snapshot`

Takes a snapshot and optionally stores in history.

#### `getHistory() []const Snapshot`

Returns the snapshot history.

#### `formatLevelBreakdown(allocator: Allocator) ![]u8`

Returns a formatted string showing log counts by level.

**Alias**: `levels`, `breakdown`

### Export

#### `exportMetrics(allocator: Allocator) ![]u8`

Exports metrics in the configured format.

#### `exportJson(allocator: Allocator) ![]u8`

Exports metrics as JSON format.

#### `exportPrometheus(allocator: Allocator) ![]u8`

Exports metrics as Prometheus exposition format.

#### `exportStatsd(allocator: Allocator) ![]u8`

Exports metrics as StatsD format.

### Latency

#### `avgLatencyNs() u64`

Returns average latency in nanoseconds.

#### `minLatencyNs() u64`

Returns minimum latency in nanoseconds.

#### `maxLatencyNs() u64`

Returns maximum latency in nanoseconds.

#### `getHistogram() [20]u64`

Returns histogram bucket data.

#### `latencyPercentileNs(percentile: f64) u64`

Estimates latency percentile in nanoseconds using histogram buckets.

#### `latencyPercentileMs(percentile: f64) f64`

Estimates latency percentile in milliseconds.

#### `getLatencySummary() LatencySummary`

Returns aggregated latency values including `min`, `max`, `avg`, `p50`, `p95`, and `p99`.

### Statistics

#### `totalRecordCount() u64`

Returns the total number of records logged.

#### `totalBytesLogged() u64`

Returns the total bytes written.

#### `errorCount() u64`

Returns the total error count.

#### `droppedCount() u64`

Returns the count of dropped records.

#### `errorRate() f64`

Returns the error rate (0.0 - 1.0).

#### `dropRate() f64`

Returns the drop rate (0.0 - 1.0).

#### `rate() f64`

Returns records per second throughput.

#### `bytesPerSecond() f64`

Returns bytes per second throughput.

**Alias**: `throughput`

#### `uptime() i64`

Returns uptime in milliseconds.

#### `uptimeSeconds() f64`

Returns uptime in seconds.

**Alias**: `uptimeSec`

#### `levelCount(level: Level) u64`

Returns the count for a specific log level.

#### `sinkCount() usize`

Returns the number of sinks being tracked.

#### `totalSinkErrors() u64`

Returns total sink write errors across all tracked sinks.

#### `totalSinkFlushes() u64`

Returns total sink flush count across all tracked sinks.

#### `lastRecordAgeMs() ?i64`

Returns age in milliseconds since the last recorded log entry, or `null` when no record has been logged yet.

### State

#### `hasRecords() bool`

Returns true if any records have been logged.

#### `hasErrors() bool`

Returns true if any errors have occurred.

#### `hasDropped() bool`

Returns true if any records have been dropped.

#### `hasHighErrorRate(threshold: f64) bool`

Returns true if error rate exceeds the threshold.

#### `hasHighDropRate(threshold: f64) bool`

Returns true if drop rate exceeds the threshold.

#### `reset() void`

Resets all metrics to zero.

**Alias**: `clear`

## Presets

### MetricsPresets

```zig
pub const MetricsPresets = struct {
    /// Creates a basic metrics instance.
    pub fn basic(allocator: std.mem.Allocator) Metrics;
    
    /// Creates a metrics sink configuration.
    pub fn createMetricsSink(filePath: []const u8) SinkConfig;
};
```

## Example

```zig
const Metrics = @import("logly").Metrics;

// Initialize
var metrics = Metrics.init(allocator);
defer metrics.deinit();

// Record logs
metrics.recordLog(.info, 256);
metrics.recordLog(.err, 512);

// Check statistics
const snapshot = metrics.getSnapshot();
std.debug.print("Records: {d}\n", .{snapshot.totalRecords});
std.debug.print("Rate: {d:.2} rec/s\n", .{snapshot.recordsPerSecond});

// Check health
if (metrics.hasHighErrorRate(0.01)) {
    std.debug.print("Warning: High error rate!\n", .{});
}

// Get level breakdown
const breakdown = try metrics.formatLevelBreakdown(allocator);
defer allocator.free(breakdown);
std.debug.print("{s}\n", .{breakdown});

// Reset if needed
metrics.reset();
```

## Performance

* **Lock-free**: All hot paths use atomic operations
* **Low overhead**: ~1-2% CPU for enabled metrics
* **Thread-safe**: Safe for concurrent access from multiple threads
* **Batch updates**: Reduces contention in high-throughput scenarios
