AbsoluteJS

Metrics

@absolutejs/metricsv0.3.2betaObservability

Turn every metrics() snapshot in your app into a Prometheus scrape target through one Elysia plugin.

Prometheus / OpenMetrics exposure for Bun and Elysia apps. Every AbsoluteJS package already exposes a typed metrics() snapshot; this package standardizes those shapes into MetricSample[], renders Prometheus text format and mounts a single GET /metrics via an Elysia plugin — no hand-rolled endpoint per service. Anything that scrapes Prometheus text (Prometheus, VictoriaMetrics, Grafana Agent, OTLP collectors) can consume it, and counter/gauge helpers cover your own app metrics.

#Installation

BASH
bun add @absolutejs/metrics

#Capabilities

Overview

Prometheus / OpenMetrics exposure for the AbsoluteJS substrate. Every substrate package already exposes a typed metrics() snapshot — this package converts those snapshots into the scrape format Prometheus, VictoriaMetrics, Grafana Agent, OTLP collectors, etc. all understand.

Why

The substrate ships instrumentation but no exposure path. Operators wire one metricsPlugin() and every metrics() shape across the substrate becomes a scrape target — no hand-rolled /metrics per service.

Usage

On a listener reachable outside a trusted scrape network, authorize before any collector runs:

Output looks like:

Collectors

Each substrate package gets its own subpath import:

Subpath — Source

@absolutejs/metrics/runtime — @absolutejs/runtime

Show 10 more

@absolutejs/metrics/router — @absolutejs/router

@absolutejs/metrics/egress — runtime egress guard

@absolutejs/metrics/queue — @absolutejs/queue

@absolutejs/metrics/sync — @absolutejs/sync engine

@absolutejs/metrics/secrets — @absolutejs/secrets broker

@absolutejs/metrics/rate-limit — @absolutejs/rate-limit

@absolutejs/metrics/audit — @absolutejs/audit

@absolutejs/metrics/dispatch — @absolutejs/dispatch

@absolutejs/metrics/errors — @absolutejs/errors tracker

@absolutejs/metrics/logs — @absolutejs/logs logger

Naming

Convention: abs__ for substrate metrics (abs_runtime_active, abs_queue_completed_total). Your app's metrics should use _ so they don't collide.

Counters end in _total. Gauges don't. (Per Prometheus naming conventions.)

One-line /metrics endpoint

metricsPlugin({ registry }) mounts GET /metrics on any Elysia app and serves Prometheus text format; elysia is an optional peer needed only for the plugin.

Per-source collectors

Subpath collectors (runtime, queue, sync, secrets, rate-limit, audit, dispatch) adapt each substrate package metrics() shape; each takes a plain snapshot function, so the source packages are never hard dependencies.

Custom metric helpers

counter() and gauge() build MetricSample values with help text and labels, so app-specific metrics register alongside substrate ones.

Consistent naming

Substrate metrics follow abs_<source>_<metric> with counters ending in _total, matching Prometheus naming conventions and avoiding collisions with your app metrics.

Outcomes

What you can build

Overview

Prometheus / OpenMetrics exposure for the AbsoluteJS substrate. Every substrate package already exposes a typed metrics() snapshot — this package converts those snapshots into the scrape format Prometheus, VictoriaMetrics, Grafana Agent, OTLP collectors, etc. all understand.

Why

The substrate ships instrumentation but no exposure path. Operators wire one metricsPlugin() and every metrics() shape across the substrate becomes a scrape target — no hand-rolled /metrics per service.

Install

elysia is an optional peer dep (only needed for metricsPlugin).

Hardening checklist

Production guidance

Make every external boundary explicitPin the deployed @absolutejs/metrics version, replace example or memory-backed dependencies with durable implementations, bound external calls, protect credentials, and emit enough evidence to retry or recover safely.

Follow in order

Troubleshooting path

1
Trace from the first failed boundary
Reproduce the smallest canonical @absolutejs/metrics example, confirm the supported entry point and version in the API explorer, then inspect the first boundary that did not produce its documented result.

#Usage

Partial snippet

Working example for Usage.

TS
import { Elysia } from 'elysia';
import { createMetricsRegistry, metricsPlugin } from '@absolutejs/metrics';
import { runtimeCollector } from '@absolutejs/metrics/runtime';
import { routerCollector } from '@absolutejs/metrics/router';
import { egressCollector } from '@absolutejs/metrics/egress';
import {
	queueCollector,
	wakeSchedulerCollector
} from '@absolutejs/metrics/queue';
import { syncCollector } from '@absolutejs/metrics/sync';
import { secretsCollector } from '@absolutejs/metrics/secrets';
import { auditCollector } from '@absolutejs/metrics/audit';
import { dispatchCollector } from '@absolutejs/metrics/dispatch';
import { errorsCollector } from '@absolutejs/metrics/errors';
import { logsCollector } from '@absolutejs/metrics/logs';

const registry = createMetricsRegistry();
registry.register(
	'runtime',
	runtimeCollector(() => runtime.metrics())
);
registry.register(
	'router',
	routerCollector(() => router.metrics())
);
registry.register(
	'egress',
	egressCollector(() => egressGuard.metrics())
);
registry.register(
	'queue',
	queueCollector(() => worker.metrics())
);
registry.register(
	'billing-wakes',
	wakeSchedulerCollector(() => billingScheduler.metrics(), {
		labels: { scheduler: 'billing' }
	})
);
registry.register(
	'sync',
	syncCollector(() => engine.metrics())
);
registry.register(
	'secrets',
	secretsCollector(() => broker.metrics())
);
registry.register(
	'audit',
	auditCollector(() => audit.metrics())
);
registry.register(
	'dispatch',
	dispatchCollector(() => dispatcher.metrics())
);
registry.register(
	'errors',
	errorsCollector(() => tracker.metrics())
);
registry.register(
	'logs',
	logsCollector(() => logger.metrics())
);

const app = new Elysia().use(await metricsPlugin({ registry }));
//        GET /metrics → Prometheus text

#Usage 2

Partial snippet

On a listener reachable outside a trusted scrape network, authorize before any collector runs:

TS
const app = new Elysia().use(
	await metricsPlugin({
		registry,
		authorize: (request) =>
			request.headers.get('authorization') === `Bearer ${scrapeToken}`
	})
);

#Custom Metrics

Partial snippet

Expose your own counters and gauges next to the substrate metrics.

TS
import { counter, gauge } from '@absolutejs/metrics';

registry.register('app', () => [
	counter('myapp_requests_total', requestCount, {
		help: 'Total HTTP requests',
		labels: { route: '/api/users' }
	}),
	gauge('myapp_workers', activeWorkers, {
		help: 'Currently running workers'
	})
]);

#Quick Start

Partial snippet

Register a collector per source and mount the scrape endpoint with one plugin.

TS
import { createMetricsRegistry, metricsPlugin } from '@absolutejs/metrics';
import { auditCollector } from '@absolutejs/metrics/audit';
import { queueCollector } from '@absolutejs/metrics/queue';
import { runtimeCollector } from '@absolutejs/metrics/runtime';
import { syncCollector } from '@absolutejs/metrics/sync';
import { Elysia } from 'elysia';

const registry = createMetricsRegistry();
registry.register('audit', auditCollector(() => audit.metrics()));
registry.register('queue', queueCollector(() => worker.metrics()));
registry.register('runtime', runtimeCollector(() => runtime.metrics()));
registry.register('sync', syncCollector(() => engine.metrics()));

const app = new Elysia().use(await metricsPlugin({ registry }));
// GET /metrics → Prometheus text
Loose coupling by design
Collectors rely on TypeScript structural typing: pass () => instance.metrics() from @absolutejs/runtime, queue, sync, secrets, rate-limit, audit or dispatch and the shapes line up without importing those packages here.

#API reference

Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.

11 symbols
MetricTypetypePermalink

@absolutejs/metrics — Prometheus / OpenMetrics exposure for the AbsoluteJS substrate. The substrate already wears its instrumentation on its sleeve: every package exposes a metrics() method returning a typed snapshot. What's missing is the last mile — converting those shapes into the Prometheus text format so scrapers can read them. Shape: 1. MetricSample is the small intermediate format: a { name, value, type, help?, labels? } shape that maps cleanly to Prometheus / OpenMetrics output. 2. Metri

TS
type MetricType = 'counter' | 'gauge' | 'histogram' | 'untyped';
Exported from @absolutejs/metrics

Current package surface

What ships today

@absolutejs/metricsv0.3.2 · betaObservabilitynpmSource
15entry points40symbols

Import surface · click to copy