2.8 KiB
telemetry
(no submodules)
Purpose
Provides the shared OpenTelemetry meter and instrument set used by every
public entry point of @suaveplan/email-processing. Instruments are
constructed lazily on first call, then cached so each metric is bound
exactly once per process — this is what makes the package's
spec-conformance test (which runs against a real MeterProvider +
InMemoryMetricExporter) deterministic. There are no mocks: the test
setup installs a real meter provider before any source module imports.
Features
- Lazy, idempotent singleton (
getEmailProcessingInstruments) with an explicit test-onlyresetEmailProcessingInstrumentsfor re-binding after a fresh meter provider is installed in setup. - Stable instrument names under the
email_processing.*prefix. - Six counters and one histogram covering parse counts, parse failures, attachment outcomes, attachment extraction duration, hook invocations, DKIM/SPF/DMARC outcomes, spam classification counts, and thread grouping counts.
- Strictly typed
EmailProcessingInstrumentsinterface — counter misuses become typecheck errors at the call site.
Usage: Basic
import { getEmailProcessingInstruments } from "@suaveplan/email-processing/otel";
const m = getEmailProcessingInstruments();
m.parseCounter.add(1);
Usage: Advanced
import {
getEmailProcessingInstruments,
resetEmailProcessingInstruments,
} from "@suaveplan/email-processing/otel";
// In a test setup file:
resetEmailProcessingInstruments();
const meter = getEmailProcessingInstruments();
const start = performance.now();
await processAttachments(parsed.attachments);
meter.attachmentExtractionDurationMs.record(performance.now() - start, {
"attachment.count": parsed.attachments.length,
});
API Reference
EmailProcessingInstruments— readonly interface listing every counter and histogram, plus the underlyingmeter.getEmailProcessingInstruments(): EmailProcessingInstruments— returns the cached instrument set, building it on first call.resetEmailProcessingInstruments(): void— clears the cache so the nextgetEmailProcessingInstruments()rebuilds against whateverMeterProvideris currently registered viametrics.setGlobal*.
Implementation Notes
The instruments are constructed against metrics.getMeter(...), which
defers to whichever MeterProvider was last installed via
metrics.setGlobalMeterProvider. Tests install an
InMemoryMetricExporter-backed provider in tests/setup/polyfills.ts
before any source module loads; production code installs a real
exporter via the application bootstrap. The histogram unit is "ms"
and intentionally simple: the package emits durations in milliseconds
from performance.now() deltas, so dashboards can read directly without
unit conversion.