3.7 KiB
Pagination OTel Instrumentation
(no submodules)
Purpose
The OTel module provides optional OpenTelemetry instrumentation for pagination operations. It exposes three instruments — a counter for request totals, a histogram for page sizes, and a histogram for encode/decode durations — using a lazy-initialisation pattern that gracefully degrades to silent no-op stubs when @opentelemetry/api is absent from the runtime. This makes instrumentation completely safe in environments without an OTel exporter and avoids adding a hard peer dependency on the OTel API.
Features
getPaginationInstruments()— returns the singletonPaginationInstrumentsset, initialising from OTel API on first call.resetPaginationInstruments()— resets the cached singleton for test isolation.PaginationInstrumentstype — exposesrequestTotal(counter),pageSize(histogram), andencodeDecode(histogram).- Graceful no-op fallback — all instruments are safe to call without an exporter installed.
- Named instruments follow the OpenTelemetry semantic-conventions pattern:
pagination.<scope>.<metric>.
Usage: Basic Example
import { getPaginationInstruments } from "@suaveplan/pagination/otel";
const { requestTotal, pageSize } = getPaginationInstruments();
// Record a successful cursor request
requestTotal.add(1, { strategy: "cursor", outcome: "success" });
// Record that a page returned 10 items
pageSize.record(10, { strategy: "cursor" });
Usage: Advanced Example
import { getPaginationInstruments } from "@suaveplan/pagination/otel";
async function trackedFetch(cursor: string | undefined) {
const { requestTotal, pageSize, encodeDecode } = getPaginationInstruments();
const t0 = performance.now();
try {
const result = await fetchPage(cursor);
requestTotal.add(1, { strategy: "cursor", outcome: "success" });
pageSize.record(result.items.length, { strategy: "cursor" });
encodeDecode.record(performance.now() - t0, { direction: "decode", type: "cursor" });
return result;
} catch (err) {
requestTotal.add(1, { strategy: "cursor", outcome: "error" });
throw err;
}
}
API Reference
getPaginationInstruments(): PaginationInstruments
Returns the singleton instrument set. On the first call, attempts to acquire a meter from @opentelemetry/api via dynamic require. If OTel is absent or has no metrics API, all instruments are replaced with silent stubs. The result is cached for subsequent calls.
resetPaginationInstruments(): void
Resets the cached instruments to null, forcing re-initialisation on the next getPaginationInstruments() call. Intended for test isolation only — do not call in production.
PaginationInstruments
| Field | Type | OTel instrument name |
|---|---|---|
requestTotal |
OtelCounter |
pagination.request.total |
pageSize |
OtelHistogram |
pagination.page.size |
encodeDecode |
OtelHistogram |
pagination.encode_decode.duration_ms |
Instruments support an optional attributes record (e.g., { strategy: "cursor", outcome: "success" }).
Implementation Notes
Dynamic require is used (instead of a static import) so the module compiles without @opentelemetry/api in package.json. The try/catch wraps the entire OTel setup so any initialisation error (missing package, no metrics key) silently activates the no-op path. Callers do not need to check whether OTel is available — all four instrument methods (add, record) are always safe to call.