prom-client adapter
If your app already uses prom-client (the de-facto Node /
Prometheus library) for its non-actor metrics,
promClientRegistry(...) lets the framework’s metrics live in
the same prom-client registry — one /metrics endpoint, all
metrics together.
import client from 'prom-client';import { ActorSystem, MetricsExtensionId, promClientRegistry, PromClientAdapterOptions,} from 'actor-ts';
// Your app's existing prom-client registry. `client.register` is// the default global one; here we use a fresh Registry for clarity.const registry = new client.Registry();// ... register your existing prom-client metrics on `registry` ...
const system = ActorSystem.create('my-app');
// Point the metrics extension at a registry that writes straight// into prom-client. Every framework counter / gauge / histogram// from here on lands in `registry` alongside your app metrics.const promAdapterOptions = PromClientAdapterOptions.create() .withClient(client) .withRegistry(registry) .withNamePrefix('actor_ts_');system.extension(MetricsExtensionId).useRegistry( promClientRegistry(promAdapterOptions),);
// Your existing /metrics endpoint now emits framework + app metrics:get(async () => ({ status: 200, body: await registry.metrics(), contentType: registry.contentType,}));promClientRegistry(...) returns a MetricsRegistry that writes
straight through to prom-client — every framework counter,
gauge, and histogram mutation lands in your prom-client registry
synchronously. There’s no background sync, no interval, and no
second copy of the values: prom-client holds the canonical state,
and your existing register.metrics() route emits everything.
When to use it
Section titled “When to use it”Two main reasons:
- Existing prom-client usage — your code has been emitting metrics via prom-client; you don’t want to maintain two registries.
- One scrape endpoint — your operators expect a single
/metricsURL combining all your metrics.
If you don’t already use prom-client, prefer the framework’s native Prometheus exporter — no extra dependency.
Configuration
Section titled “Configuration”type PromClientAdapterOptionsType = { client: PromClientLike; // the prom-client namespace: import client from 'prom-client' registry: PromClientRegistryLike; // the Registry to publish into — typically client.register namePrefix?: string; // prefix applied to every metric name — default: '' maxSeriesPerFamily?: number; // per-family cardinality cap — default: 10 000, 0 disables};client and registry are mandatory — the bridge has nothing to
publish into without them. client is the prom-client namespace
you already import; registry is the Registry it writes into
(usually client.register, the default global registry). The
plain object above works anywhere the builder does — the builder is
the documented default.
namePrefix lets you namespace framework metrics so the
bridge-sourced families are easy to spot in the exposition:
const prefixedOptions = PromClientAdapterOptions.create() .withClient(client) .withRegistry(registry) .withNamePrefix('actorts_');promClientRegistry(prefixedOptions);
// → actorts_messages_delivered_total, actorts_members_up, ...Cardinality cap
Section titled “Cardinality cap”The bridge enforces the same per-family cap as the in-process
registry (default 10 000 label tuples, 0 disables), and it needs
to more urgently: prom-client mints a series inside its own
Counter / Gauge / Histogram on every .labels(...) call and
never expires one, so an unbounded label grows your process’s
resident memory, not just the scrape body.
const cappedOptions = PromClientAdapterOptions.create() .withClient(client) .withRegistry(registry) .withMaxSeriesPerFamily(50_000);promClientRegistry(cappedOptions);Past the cap the bridge rewrites the tuple to the family’s own
label names with every value set to __overflow__, so prom-client
sees at most maxSeriesPerFamily + 1 distinct tuples per family.
Reusing the declared names is not cosmetic: prom-client fixes a
metric’s label names at construction and throws on a .labels(...)
carrying anything else, so a synthetic marker name would fail the
very call meant to contain the damage.
See cardinality discipline
for bucketize, the way to not reach the cap in the first place.
Peer dependency
Section titled “Peer dependency”npm install prom-client# or: bun add prom-clientprom-client is a peer — only required if you use this
adapter.
Where to next
Section titled “Where to next”- Observability overview — the bigger picture.
- Core metrics — the framework’s metric primitives that flow through the bridge.
- Prometheus exporter — the framework-native alternative when you don’t need prom-client.
