Files
skills/docs/identity/auth/better-auth-surrealdb/src/otel/instruments.md
2026-05-29 08:20:56 +01:00

2.9 KiB

otel/instruments

(no submodules)

Purpose

Wires the package's OpenTelemetry metrics surface and exposes a thin instrument(op) helper the adapter wraps around every CRUD method. The helper records one counter point (with outcome: "success" | "error") plus one histogram observation per call, so dashboards can pivot on model/operation/outcome and also see the per-operation latency distribution.

Features

  • better_auth.surrealdb.operations_total counter — attributes: model, operation, outcome.
  • better_auth.surrealdb.operation_duration_ms histogram — attribute: operation.
  • Lazy meter resolution: the meter and instruments are constructed on first use (not at module load) so tests can install a real MeterProvider via setGlobalMeterProvider before the adapter begins issuing operations.
  • Universal: uses performance.now() when available, falls back to Date.now() when running under bundlers that strip performance.
  • resetInstrumentsForTesting() clears the lazy cache so a re-imported test environment resolves the new provider.

Usage: Basic

import { instrument } from "@suaveplan/better-auth-surrealdb/otel";

const row = await instrument({
    model: "session",
    operation: "create",
    run: async () => insertSessionRow(),
});

Usage: Advanced

import { instrument } from "@suaveplan/better-auth-surrealdb/otel";
import { metrics } from "@opentelemetry/api";
import { MeterProvider, PeriodicExportingMetricReader, InMemoryMetricExporter, AggregationTemporality } from "@opentelemetry/sdk-metrics";

// Install provider BEFORE first instrument() call:
const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000 });
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);

await instrument({ model: "user", operation: "findOne", run: async () => ({ ok: true }) });
await provider.forceFlush();
const collected = exporter.getMetrics();

API Reference

  • instrument<T>(op): Promise<T> — wraps a () => Promise<T> with counter + histogram observations; rethrows on failure.
  • InstrumentedOp<T> — { model: string; operation: string; run: () => Promise<T> }.
  • AdapterOutcome — "success" | "error".
  • resetInstrumentsForTesting() — invalidates the lazy cache.

Implementation Notes

The lazy-init pattern is critical: importing OTel metrics at module load returns a noop meter unless setGlobalMeterProvider has been called by the host. Caching the meter+instruments after first use keeps subsequent calls allocation-free. performance.now() is preferred for sub-millisecond resolution but Date.now() is a correct fallback because the histogram records millisecond observations regardless.