Metrics & Monitoring ​
HTTPX includes a thread-safe metrics registry compatible with Prometheus text format (v0.0.4) and zero-allocation point-in-time snapshots.
Metrics Types ​
- Counters (
httpx.Counter): Monotonically increasing 64-bit unsigned values (e.g. total requests, bytes sent, error counts). - Gauges (
httpx.Gauge): Instantly varying 64-bit signed values (e.g. active connections, active requests) with underflow-safe atomic operations. - Histograms (
httpx.Histogram): High-resolution latency tracking using 11 standard Prometheus buckets (0.005,0.01,0.025,0.05,0.1,0.25,0.5,1.0,2.5,5.0,10.0seconds ++Inf), total count, and cumulative sum in seconds with nanosecond precision.
Server Live Metrics Endpoint ​
HTTPX servers automatically track connections, requests, methods, status code classes (2xx, 3xx, 4xx, 5xx), bytes in/out, durations, and errors. You can mount a dynamic Prometheus /metrics endpoint with a single call:
zig
const std = @import("std");
const httpx = @import("httpx");
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const io = std.Io.Threaded.global_single_threaded.io();
var server = try httpx.Server.init(allocator, io, .{ .port = 8080 });
defer server.deinit();
// Mount live Prometheus /metrics endpoint
try server.metrics("/metrics");
try server.get("/", helloHandler);
server.run();
}
fn helloHandler(ctx: *httpx.Context) anyerror!httpx.Response {
return ctx.text("Hello World!");
}Visiting http://localhost:8080/metrics dynamically generates standard Prometheus exposition text with # HELP and # TYPE headers:
text
# HELP http_requests_total Total HTTP requests received
# TYPE http_requests_total counter
http_requests_total 1505
# HELP http_requests_by_method_total Total HTTP requests by method
# TYPE http_requests_by_method_total counter
http_requests_by_method_total{method="GET"} 1420
http_requests_by_method_total{method="POST"} 85
# HELP http_active_connections Number of currently active connections
# TYPE http_active_connections gauge
http_active_connections 4
# HELP http_request_duration_seconds HTTP request duration in seconds
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.005"} 1240
http_request_duration_seconds_bucket{le="0.025"} 1410
http_request_duration_seconds_bucket{le="0.100"} 1490
http_request_duration_seconds_bucket{le="+Inf"} 1505
http_request_duration_seconds_sum 3.421500
http_request_duration_seconds_count 1505Point-in-Time Snapshots ​
HTTPX provides lightweight, lock-free snapshots to inspect metrics without heap allocation or blocking workers:
zig
// Server snapshot with uptime, rate, and connection stats
const snap = server.snapshot();
std.debug.print("Uptime: {d}ms\n", .{snap.uptimeMs});
std.debug.print("Total requests: {d}\n", .{snap.requestsTotal});
std.debug.print("Error rate: {d:.2}%\n", .{snap.errorRate() * 100.0});
std.debug.print("Throughput: {d:.2} req/sec\n", .{snap.requestsPerSecond()});
std.debug.print("Active connections: {d}\n", .{snap.activeConnections});
// Raw metrics snapshot
const m_snap = server.metricsSnapshot();
std.debug.print("Avg latency: {d:.3}ms\n", .{m_snap.averageLatencyMs()});Standalone Registry ​
You can also use httpx.Metrics standalone in custom applications, background workers, or microservices:
zig
var reg = httpx.Metrics{};
reg.requestsTotal.inc();
reg.activeConnections.inc();
reg.recordRequestMethod("GET");
reg.recordResponseFull(200, 12_500_000, 512); // status, latency_ns, bytes
var buf: [4096]u8 = undefined;
var w: std.Io.Writer = .fixed(&buf);
try reg.render(&w);