import { opentelemetry } from './opentelemetry'; /** * @see https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels */ const METRIC_REGEXP = new RegExp( `^${process.env.TELEMETRY_METRIC_REGEXP || '[a-zA-Z_:][a-zA-Z0-9_:]*'}$`, ); const meters = new Map(); const counters = new Map(); let defaultMeter: opentelemetry.api.Meter | null = null; export function getDefaultMeterName(name?: string): string { return ( name ?? process.env.OTEL_SERVICE_NAME ?? process.env.TELEMETRY_SERVICE_NAME ?? 'service' ); } export function isValidMetric(metric: string): boolean { return METRIC_REGEXP.test(metric); } export function hasMeter(name?: string) { return meters.has(getDefaultMeterName(name)); } /** * @deprecated Avoid manipulating the meter directly. Prefer * using metrics.createCounter() or metrics.createHistogram() */ export function getMeter( name?: string, version?: string, options?: opentelemetry.api.MeterOptions, ): opentelemetry.api.Meter { const _name = getDefaultMeterName(name); if (meters.has(_name)) { return meters.get(_name)!; } const meter = opentelemetry.api.metrics.getMeter(_name, version, options); meters.set(_name, meter); if (defaultMeter === null) { defaultMeter = meter; } return meter; } /** * @deprecated Prefer using metrics.createCounter() */ export function getMetricCounter( metric: string, options?: opentelemetry.api.MetricOptions, ): opentelemetry.api.Counter { if (counters.has(metric)) { return counters.get(metric)!; } const counter = defaultMeter!.createCounter(metric, options); counters.set(metric, counter); return counter; } /** * @deprecated Prefer using metrics.metric() */ export function metric( metric: string, context: Record = {}, options: opentelemetry.api.MetricOptions = {}, increment = 1, meterName = getDefaultMeterName(), ) { if (hasMeter(meterName) === false) { getMeter(); } if (isValidMetric(metric) === false) { throw new Error('Invalid metric format'); } return getMetricCounter(metric, options).add(increment, context); }