Skip to content

Ports and telemetry records

All ports return synchronously. An adapter may buffer or batch work internally, but instrumentation does not await network or storage I/O.

Metrics

typescript
interface MetricsPort {
  increment(measurement: MetricMeasurement): void;
  observe(measurement: MetricMeasurement): void;
}

MetricMeasurement.toPrimitives() returns:

typescript
interface MetricMeasurementPrimitives {
  attributes: Readonly<Record<string, string | number | boolean>>;
  kind: MetricKind;
  name: string;
  operation: string;
  unit: MetricUnit;
  value: number;
}
KindPort methodUnit
callsincrementcount
failuresincrementcount
durationobservemilliseconds
cpu.userobservemicroseconds
cpu.systemobservemicroseconds
memory.rssobservebytes
memory.heap_usedobservebytes
memory.rss_deltaobservebytes
memory.heap_used_deltaobservebytes

Adapters should choose the vendor instrument from kind and convert values from unit when the backend expects base units. name contains the configured generic metric name; operation contains the logical operation label.

Structured logs

typescript
interface LoggerPort {
  write(entry: InstrumentationLog): void;
}

InstrumentationLog.toPrimitives() returns:

typescript
interface InstrumentationLogPrimitives {
  attributes: Readonly<Record<string, string | number | boolean>>;
  level: 'called' | 'failed';
  message: string;
  operation: string;
  stackTrace?: string;
}

called is a lifecycle value, not a logging severity. Logging adapters choose their vendor severity. The built-in console adapter uses log for calls and error for failures. Instrumentation never includes arguments or return values.

Clock and resource usage

typescript
interface ClockPort {
  now(): ElapsedMilliseconds;
}

interface ResourceUsagePort {
  capture(): ResourceUsageSnapshot;
}

ResourceUsageSnapshot contains user and system CPU microseconds, resident set bytes, and heap-used bytes. CPU and memory describe the whole Node.js process; concurrent work and garbage collection affect per-operation deltas.

Default inspection snapshot

typescript
interface MetricsInspectionSnapshot {
  capacity: { logs: number; metrics: number };
  discarded: { logs: number; metrics: number };
  logs: readonly InMemoryLogRecord[];
  metrics: readonly InMemoryMetricRecord[];
}

Metric records add recordedAt and type to MetricMeasurementPrimitives. Log records add recordedAt to InstrumentationLogPrimitives. Timestamps use Unix milliseconds.

Public errors

ErrorMeaning
InvalidOperationNameErrorAn explicit operation name is empty
InvalidMetricsDecoratorTargetError@Metrics was applied to a non-method
InvalidBufferCapacityErrorAn in-memory capacity is not a positive int
NonErrorThrownErrorA non-Error throw needed a fallback stack
UnsupportedPrometheusMetricErrorA metric kind reached the wrong adapter method

Instrumentation contains errors raised by ports. Constructor and decorator validation errors still reach the caller.

Package entrypoints

EntrypointContents
@haskou/metricsCore API, ports, records, and values
@haskou/metrics/testingIn-memory, manual, and no-op doubles
@haskou/metrics/adapters/consoleConsole structured logger
@haskou/metrics/adapters/nodeNode.js CPU and memory sampling
@haskou/metrics/adapters/prometheusprom-client metrics adapter