// OpenTelemetry Node SDK bootstrap for FarmaClic backend. // Started as a side-effect import from server.js (ESM). // // Env vars (set by docker-compose): // OTEL_SERVICE_NAME — default: farmaclic-backend // OTEL_EXPORTER_OTLP_ENDPOINT — OTLP gRPC endpoint (e.g. http://alloy:4317) // // Exports traces to the shared Grafana Alloy collector, where they are // routed to Tempo. import { NodeSDK } from '@opentelemetry/sdk-node'; import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'; import * as resources from '@opentelemetry/resources'; import { ATTR_SERVICE_NAME, ATTR_SERVICE_NAMESPACE } from '@opentelemetry/semantic-conventions'; import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; const serviceName = process.env.OTEL_SERVICE_NAME || 'farmaclic-backend'; const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317'; const resource = typeof resources.resourceFromAttributes === 'function' ? resources.resourceFromAttributes({ [ATTR_SERVICE_NAME]: serviceName, [ATTR_SERVICE_NAMESPACE]: 'farmaclic', }) : new resources.Resource({ [ATTR_SERVICE_NAME]: serviceName, [ATTR_SERVICE_NAMESPACE]: 'farmaclic', }); const sdk = new NodeSDK({ resource, traceExporter: new OTLPTraceExporter({ url: otlpEndpoint }), instrumentations: [ getNodeAutoInstrumentations({ // Disable fs by default — it is noisy and rarely useful. '@opentelemetry/instrumentation-fs': { enabled: false }, '@opentelemetry/instrumentation-dns': { enabled: false }, }), new PinoInstrumentation(), ], }); if (process.env.NODE_ENV !== 'test') { sdk.start(); } const shutdown = async () => { try { if (process.env.NODE_ENV !== 'test') { await sdk.shutdown(); } } catch (err) { // eslint-disable-next-line no-console console.error('OpenTelemetry shutdown failed', err); } }; process.on('SIGTERM', shutdown); process.on('SIGINT', shutdown);