3.1 KiB
otel/instruments
(no submodules)
Purpose
Registers the OpenTelemetry counter and histogram that every CLI command
in @suaveplan/server-keys emits exactly once per invocation through the
runFunction wrapper. The instruments live behind the global meter
provider supplied by @opentelemetry/api, so production deployments can
plug in any exporter (OTLP, Prometheus, Jaeger) without changing the
package. Tests wire an in-memory MeterProvider in tests/setup/polyfills.ts
before any source module is imported, so the meter resolved at load time
is the real provider's meter, never the noop fallback.
The recordCommand(command, outcome, durationMs, errorCode?) helper is the
single call site every command goes through — keeping the attribute keys
consistent and the histogram unit (ms) authoritative.
Features
- Counter
server_keys.command_total{command, command.outcome[, command.error_code]}. - Histogram
server_keys.command_duration_ms{command, command.outcome[, command.error_code]}withunit: "ms". - Stable attribute-key constants (
ATTR_COMMAND,ATTR_OUTCOME,ATTR_ERROR_CODE) so tests can assert by name. recordCommandrecords both instruments atomically so dashboards built on the counter and the histogram never disagree.
Usage: Basic
import { recordCommand } from "@suaveplan/server-keys/otel/instruments";
const start = performance.now();
try {
await doWork();
recordCommand("create-root-keys", "success", performance.now() - start);
} catch (err) {
recordCommand("create-root-keys", "error", performance.now() - start);
throw err;
}
Usage: Advanced
Attach the typed error code when failing, so dashboards can break down failures by reason without scraping log lines:
import { recordCommand } from "@suaveplan/server-keys/otel/instruments";
import { ServerKeysError } from "@suaveplan/server-keys/error-codes/error-codes";
try {
await prepareFileCommand(...);
recordCommand("prepare-file", "success", elapsed);
} catch (err) {
const code = err instanceof ServerKeysError ? err.code : "UNKNOWN";
recordCommand("prepare-file", "error", elapsed, code);
throw err;
}
Or query the in-memory test exporter to assert on emitted metrics:
await flushTestMetrics(); // from tests/setup/polyfills.ts
API Reference
commandTotal: Counter— total CLI commands executed.commandDurationMs: Histogram— per-command duration (ms).ATTR_COMMAND,ATTR_OUTCOME,ATTR_ERROR_CODE— string-literal attribute keys.CommandOutcome = "success" | "error".recordCommand(command, outcome, durationMs, errorCode?)— record one observation on both instruments.
Implementation Notes
metrics.getMeter(name, version) returns the meter from the current
global provider; if no provider is registered, the API package returns a
noop meter so production code never throws on missing telemetry. Setting
the meter provider AFTER instruments.ts is imported has no effect on
this module's meter handle, so the test polyfill must register the
provider before any import that transitively loads instruments.ts.