Skip to content

Repository files navigation

@haskou/metrics

CI Codecov Renovate npm License: MIT

Metrics and structured logs for TypeScript methods.

Live playground · Open in StackBlitz

import { Metrics, metrics } from '@haskou/metrics';

class UserCreator {
  @Metrics()
  public async create(): Promise<void> {
    // your code
  }
}

await new UserCreator().create();

console.table(metrics.snapshot().metrics);
console.table(metrics.snapshot().logs);

Without a name, the decorator records this method as UserCreator.create. Pass an explicit name such as @Metrics('users.create') when you want a stable name that does not depend on the class.

Use it without setup. The default runtime stores the latest 1,000 metrics and 1,000 logs in memory. Once a buffer fills, it replaces the oldest entry and increments the snapshot's discarded counter.

metrics.clear();

What it captures

Signal Default
Calls, failures, and duration On
UserCreator.create called On
Failure logs with stack traces On
CPU time in microseconds Opt-in
RSS, heap usage, and memory deltas Opt-in

Enable Node.js resource sampling on the methods that need it:

class ReportGenerator {
  @Metrics('reports.generate', {
    recordCpu: true,
    recordMemory: true,
  })
  public async generate(): Promise<void> {
    // ...
  }
}

CPU and memory samples describe the Node.js process. Concurrent work can affect the values, and garbage collection can produce negative memory deltas.

Connect your stack

Use the in-memory runtime during development. Connect production backends at your composition root:

import { Registry } from 'prom-client';
import { configureMetrics } from '@haskou/metrics';
import { ConsoleLoggerAdapter } from '@haskou/metrics/adapters/console';
import { PrometheusMetricsAdapter } from '@haskou/metrics/adapters/prometheus';

const registry = new Registry();

configureMetrics({
  adapter: new PrometheusMetricsAdapter({
    attributeNames: ['service'],
    registry,
  }),
  attributes: { service: 'users-api' },
  defaults: {
    logCalls: false,
    logFailures: true,
    recordDuration: true,
  },
  logger: new ConsoleLoggerAdapter(),
});

Install prom-client only when using this adapter:

npm install prom-client

The ports map directly to the APIs used by common observability tools:

Destination Adapter mapping
Prometheus → Grafana Counters, histograms, and memory gauges
OpenTelemetry → Grafana Cloud or any OTLP backend MetricMeasurement.kind → matching instrument
StatsD / Datadog Measurement kind and unit → vendor API
Loki, Pino, Winston, or OpenTelemetry Logs LoggerPort.write → structured log

Grafana supports Prometheus as a built-in data source. Grafana Cloud also accepts Prometheus metrics and OTLP, so the library does not force a monitoring vendor or SDK into your application.

Prometheus cardinality

Never use identifiers, full URLs, request IDs, user IDs, error messages, stack traces, email addresses, or any other unbounded value as Prometheus attributes. Keep operation names and promoted attributes low-cardinality and stable, such as service, environment, route, method, or a bounded status code.

MetricsPort, LoggerPort, ClockPort, and ResourceUsagePort keep vendor SDKs outside the instrumentation core. See the adapter guide for a complete example.

Integration guides:

Try it online

Open the live playground to run successful and failed methods, inspect metrics and logs, and view captured stack traces. Use StackBlitz if you also want to edit the example in your browser.

To run the same playground locally:

yarn install
yarn playground:dev

Install

npm install @haskou/metrics
yarn add @haskou/metrics

@Metrics supports both standard TypeScript decorators and legacy decorators. Enable experimentalDecorators only when your project still uses the legacy implementation.

Read the documentation for guides and adapter examples.

Releases

Merging a pull request into main or master publishes a new npm version after CI passes. The source branch selects the version bump:

Branch Version
fix or fix/* Patch
feat or feat/* Minor
break or break/* Major

Renovate pull requests with a fix: or fix(...): title publish a patch. See RELEASING.md for trusted publishing, tags, and release notes.

MIT. See LICENSE.txt.

Releases

Packages

Contributors

Languages