import type { Attributes, Counter, Histogram, Meter, ObservableGauge, } from "@opentelemetry/api"; /** * Create a monotonically increasing counter instrument on the given meter. * * Counters track cumulative totals that never decrease (e.g. total requests, * total errors). Use a histogram instead when you need distribution data. * * @param meter - OTel `Meter` instance to create the counter on. * @param name - Instrument name following the OTel naming convention (`.`). * @param description - Optional human-readable description shown in metric explorers. * @returns An OTel `Counter` instrument. * * @example * ```ts * const requestCounter = createCounter(meter, "http.server.request_count", "Total HTTP requests"); * requestCounter.add(1, { "http.method": "GET" }); * ``` */ export function createCounter( meter: Meter, name: string, description?: string ): Counter { return meter.createCounter( name, description !== undefined ? { description } : {} ); } /** * Create a histogram instrument on the given meter. * * Histograms record the distribution of values (e.g. request durations, * payload sizes). Use this over a counter when percentile data matters. * * @param meter - OTel `Meter` instance. * @param name - Instrument name. * @param description - Optional description. * @param unit - Optional unit string (e.g. `"ms"`, `"By"`). * @returns An OTel `Histogram` instrument. * * @example * ```ts * const latency = createHistogram(meter, "http.server.duration", "Request duration", "ms"); * latency.record(42, { "http.route": "/api/users" }); * ``` */ export function createHistogram( meter: Meter, name: string, description?: string, unit?: string ): Histogram { const opts: { description?: string; unit?: string } = {}; if (description !== undefined) opts.description = description; if (unit !== undefined) opts.unit = unit; return meter.createHistogram(name, opts); } /** * Create an observable (asynchronous) gauge instrument on the given meter. * * Observable gauges report the current value of a resource at collection time * (e.g. current queue depth, active connections). The callback is registered * separately via the `ObservableGauge.addCallback` API. * * @param meter - OTel `Meter` instance. * @param name - Instrument name. * @param description - Optional description. * @returns An OTel `ObservableGauge` instrument. * * @example * ```ts * const gauge = createGauge(meter, "system.memory.usage", "Current memory usage in bytes"); * gauge.addCallback((result) => { * result.observe(process.memoryUsage().heapUsed, { type: "heap" }); * }); * ``` */ export function createGauge( meter: Meter, name: string, description?: string ): ObservableGauge { return meter.createObservableGauge( name, description !== undefined ? { description } : {} ); } /** * Record the elapsed duration from a start timestamp to now. * * Computes `Date.now() - startMs` and records the result on `histogram`. * This pattern avoids repeating the subtraction at every call site and * centralises the choice of `Date.now()` as the wall-clock source. * * @param histogram - The histogram instrument to record on. * @param startMs - Start timestamp in milliseconds (from `Date.now()`). * @param attributes - Optional attributes to attach to the observation. * * @example * ```ts * const start = Date.now(); * await processOrder(order); * recordDuration(latencyHistogram, start, { "order.type": order.type }); * ``` */ export function recordDuration( histogram: Histogram, startMs: number, attributes?: Attributes ): void { histogram.record(Date.now() - startMs, attributes); }