Skip to content
UniKVS
Esc
↑↓navigate↵open⌘Jpreview
On this page

@unikvs/metrics

Middleware that records operation counts, byte sizes, and use-hook duration, forwardable to OTel or Prometheus.

Overview

Metrics records operation counts, byte sizes, and use-hook duration, with aggregation and external export. The use-hook duration does not include storage I/O latency.Middleware

Use it for performance visibility and operational monitoring. Measurements stay in memory and can be forwarded to OTel instruments or custom sinks.

  • name is Metrics.
  • isOpen is always true.
  • use measures each operation’s use-hook chain success and duration; storage I/O latency is not included. encode / decode and streams also record byte sizes.
  • Recording never throws; sink failures are ignored.

Install with:

npm install @unikvs/metrics @opentelemetry/api
pnpm add @unikvs/metrics @opentelemetry/api
yarn add @unikvs/metrics @opentelemetry/api
bun add @unikvs/metrics @opentelemetry/api
nub add @unikvs/metrics @opentelemetry/api
aube add @unikvs/metrics @opentelemetry/api

@opentelemetry/api is only needed when exporter is "otel". Memory-only aggregation and Prometheus output (toPrometheusString()) do not need it.

Usage

Metrics implements IMiddleware. Pass it to UniKvs with use().

import { Metrics } from "@unikvs/metrics";

Constructor arguments:

PropType
exporter?MetricsExporterKind | MetricsExporter

Where to forward measurements. Pass a built-in exporter name or a custom sink. Measurements are always kept in memory regardless of this setting.

TypeMetricsExporterKind | MetricsExporter
meterProvider?MetricsMeterProvider

OTel MeterProvider used when exporter is "otel".

TypeMetricsMeterProvider
registry?unknown

Opaque registry handle kept for external Prometheus integration. The exposition text comes from toPrometheusString().

Typeunknown
onRecord?(record: MetricRecord) => void

Called every time a measurement is recorded.

Type(record: MetricRecord) => void
clock?() => number

Clock returning milliseconds. Defaults to performance.now().

Type() => number

The following measures operations and reads the aggregation:

import { Memory } from "@unikvs/memory";
import { Metrics } from "@unikvs/metrics";
import * as unikvs from "unikvs";

const metrics = new Metrics();
const kvs = new unikvs.Builder<{ k1: unikvs.PlainValue<string> }>()
  .use(metrics)
  .persist(new Memory())
  .build();

await kvs.open();
await kvs.set("k1", "hello");
console.log(metrics.getMetrics().total); // record count
console.log(metrics.toPrometheusString()); // Prometheus format
await kvs.close();

Metrics

Middleware that records operation metrics. Measurements stay in memory and are available via getMetrics() and toPrometheusString().

MetricsOptions

Options accepted by the Metrics constructor. Specifies the exporter and clock.

MetricsAction

Operation names observed by the metrics middleware. Equivalent to IMiddleware.UseContext["action"].

MetricsOutcome

Whether the observed use hook chain, or the encode, decode, or stream operation, succeeded or failed. "success" or "error". For use, this is not the storage operation’s outcome.

MetricsExporterKind

Built-in exporter selected by name. "otel" forwards to instruments; "prometheus" means in-memory retention plus text output.

MetricsExporter

Custom sink receiving every recorded measurement.

MetricRecord

Measurement observed for a single hook execution.

PropType
actionMetricsAction

The observed operation.

TypeMetricsAction
outcomeMetricsOutcome

Whether the observed hook succeeded or failed. For the use hook, this is not the storage operation's outcome.

TypeMetricsOutcome
durationMsnumber

Wall-clock duration of the observed hook chain (ms). For use, this is the use-hook chain, not storage I/O latency. For streams, it runs from wrapping until settlement (source/transform completion, read failure, or cancellation) and can include stream consumption time. Completion here means the source/transform finished, not that the destination has been fully drained.

Typenumber
bytes?number | undefined

Observed byte count. Undefined when unknown.

Typenumber | undefined
keystring | undefined

Target key. Undefined for keyless clear.

Typestring | undefined

MetricsActionSummary

Per-operation-name counters.

PropType
actionstring

Operation name.

Typestring
countnumber

Total recorded measurements.

Typenumber
successnumber

Successful measurements.

Typenumber
errornumber

Failed measurements.

Typenumber
totalBytesnumber

Total observed bytes.

Typenumber
totalDurationMsnumber

Total observed elapsed time (ms).

Typenumber

MetricsSnapshot

Snapshot of all measurements recorded so far.

PropType
totalnumber

Total recorded measurements.

Typenumber
byActionRecord<string, MetricsActionSummary>

Aggregation keyed by operation name.

TypeRecord<string, MetricsActionSummary>
recordsreadonly MetricRecord[]

All recorded measurements (in record order).

Typereadonly MetricRecord[]

Data types

Method Input Output
encode unknown unknown (passthrough)
decode unknown unknown (passthrough)
encodeStream unknown (chunk) unknown (chunk, passthrough)
decodeStream unknown (chunk) unknown (chunk, passthrough)
  • use records one measurement per operation, with bytes as undefined. durationMs is the use-hook chain duration and does not include storage I/O latency.
  • Storage I/O failures that run after the use hooks are not reflected in use records. This includes plain-value set write failures, get read failures other than missing keys, stream acquisition and missing-key failures, and delete / has / clear / copy / move failures.
  • Metrics records only failures of the hooks themselves and read failures or cancellations of a wrapped stream; a missing-key get is not recorded as an error either. A plain-value set that fails during encoding can produce use success plus an encode error.
  • Stream records settle at the earliest of stream completion, read failure, or cancellation. Completion records success; read failures and cancellations record error. A destination failure that cancels the stream before completion also records error. Failures after settlement are not reflected, and a source that is already locked before wrapping records nothing.
  • Stream durationMs runs from wrapping until settlement (source/transform completion, read failure, or cancellation) and can include stream consumption time. Completion here means the source/transform finished, not that the destination has been fully drained. For use, encode, and decode, durationMs is the hook-chain duration.
  • Metrics does not implement afterUse, so it emits no separate record for mutating-operation outcomes. Core use runs before storage I/O, so no middleware can observe storage-operation outcomes from use. Core provides an afterUse hook for post-I/O outcomes.
  • encode and decode pass data through, also recording bytes for strings, ArrayBuffer, and ArrayBufferView. Other types record undefined.
  • Streams pass chunks through and record the total chunk size as one record on settlement.
  • This middleware deliberately omits key labels so toPrometheusString() cardinality stays flat. Per-key detail is available via getMetrics() and onRecord.

Errors

This package has no package-specific errors.

Recording never throws and sink failures are ignored, so metrics never break the operation pipeline. When a hook fails, the error is recorded and then rethrown. For streams, read failures and cancellations are also recorded as error. However, use completes before storage I/O, so storage operation failures are not reflected in use records.

Was this page helpful?