Files
skills/docs/foundation/data/pagination/src/otel/pagination-otel.md
2026-05-29 08:20:56 +01:00

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 singleton PaginationInstruments set, initialising from OTel API on first call.
  • resetPaginationInstruments() — resets the cached singleton for test isolation.
  • PaginationInstruments type — exposes requestTotal (counter), pageSize (histogram), and encodeDecode (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.