xtc_stats(3)
---xtc_stats(3)
runtime statistics: counters, gauges, histograms
| XTC_STATS(3) | Library Functions Manual | XTC_STATS(3) |
NAME
xtc_counter_create,
xtc_counter_inc,
xtc_counter_add,
xtc_counter_read,
xtc_counter_destroy,
xtc_gauge_create,
xtc_gauge_set,
xtc_gauge_add,
xtc_gauge_read,
xtc_gauge_destroy,
xtc_hist_create,
xtc_hist_record,
xtc_hist_quantile,
xtc_hist_count,
xtc_hist_destroy,
xtc_metrics_iterate,
xtc_metrics_dump_prometheus —
runtime statistics: counters, gauges, histograms
SYNOPSIS
#include <xtc.h>
#include <xtc_stats.h>
int
xtc_counter_create(const
char *name, xtc_counter_t
**out);
void
xtc_counter_inc(xtc_counter_t
*c);
void
xtc_counter_add(xtc_counter_t
*c, int64_t
delta);
uint64_t
xtc_counter_read(const
xtc_counter_t *c);
void
xtc_counter_destroy(xtc_counter_t
*c);
int
xtc_gauge_create(const
char *name, xtc_gauge_t
**out);
void
xtc_gauge_set(xtc_gauge_t
*g, int64_t v);
int64_t
xtc_gauge_read(const
xtc_gauge_t *g);
void
xtc_gauge_destroy(xtc_gauge_t
*g);
int
xtc_hist_create(const
char *name, xtc_hist_t
**out);
void
xtc_hist_record(xtc_hist_t
*h, int64_t
value_ns);
int64_t
xtc_hist_quantile(const
xtc_hist_t *h, double
q);
void
xtc_hist_destroy(xtc_hist_t
*h);
int
xtc_metrics_iterate(xtc_metric_visit_fn
fn, void
*user);
int
xtc_metrics_dump_prometheus(int
fd);
DESCRIPTION
xtc_stats is the runtime telemetry layer.
Three metric kinds:
- counter
- Monotonic non-negative count (requests served, errors observed).
- gauge
- Current value, can move up or down (active connections, queue depth).
- histogram
- Distribution; supports quantile queries (p50, p99, p999). For latency tracking.
- Counters are
per-CPU
sharded:
xtc_counter_inc() hits one cache-line-isolated atomic on the calling CPU. No cross-CPU coherence traffic on the hot path. Reads sum all shards. - Gauges are a single _Atomic int64_t. For low-frequency-update gauges this is fine; high-frequency gauges should be modeled as a counter pair instead.
- Histograms are per-CPU sharded (one log-linear bucket
array per CPU);
xtc_hist_record() hits one shard's atomic counter.xtc_hist_quantile() merges shards under no lock (relaxed atomic loads).
Observability discipline: the implementation is designed not to obscure observability tools. Updating a counter compiles to one CPU-shard sched_getcpu (cached in TLS) plus one atomic_fetch_add; under perf-stat(1) this shows up as the program's CPU pattern, not as overhead in the telemetry layer.
xtc_counter_create(),
xtc_gauge_create(),
xtc_hist_create()
register the metric in a global registry keyed by name
(up to 64 chars). The matching
xtc_counter_destroy(),
xtc_gauge_destroy(),
and
xtc_hist_destroy()
unregister and free a metric. The registry supports walking via
xtc_metrics_iterate()
or dumping in Prometheus exposition format via
xtc_metrics_dump_prometheus()
to a file descriptor.
EXAMPLES
xtc_counter_t *requests;
xtc_hist_t *latency;
xtc_counter_create("rexis.requests", &requests);
xtc_hist_create ("rexis.req_latency_ns", &latency);
/* Hot path: */
int64_t t0 = now_ns();
handle_request();
xtc_counter_inc(requests);
xtc_hist_record(latency, now_ns() - t0);
/* Periodic dump (e.g. via xtc_timer): */
xtc_metrics_dump_prometheus(scrape_fd);
PROMETHEUS OUTPUT
xtc_metrics_dump_prometheus() emits, for
each metric:
# TYPE rexis.requests counter rexis.requests 12345 # TYPE rexis.queue_depth gauge rexis.queue_depth 42 # TYPE rexis.req_latency_ns histogram rexis.req_latency_ns_count 12345 rexis.req_latency_ns_p50 1500 rexis.req_latency_ns_p99 9800 rexis.req_latency_ns_p999 24000
A trivial scrape server reads fd and forwards to HTTP. See examples/05_rexis/metrics.c for an example dump-on-timer pattern.
SEE ALSO
HISTORY
Appeared in xtc 0.1.
| May 28, 2026 | Debian |