|
| 1 | +import { logs } from '@opentelemetry/api-logs'; |
| 2 | +import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'; |
| 3 | +import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; |
| 4 | +import { Resource } from '@opentelemetry/resources'; |
| 5 | +import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'; |
| 6 | +import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; |
| 7 | + |
| 8 | +/** |
| 9 | + * Create a LoggerProvider with OTLP exporter |
| 10 | + * @param {Object} config - Configuration object |
| 11 | + * @param {Object} config.resource - Resource attributes |
| 12 | + * @param {string} config.resource.serviceName - Service name |
| 13 | + * @param {string} config.resource.serviceVersion - Service version |
| 14 | + * @param {string} config.resource.serviceNamespace - Service namespace |
| 15 | + * @param {Object} config.exporter - Exporter configuration |
| 16 | + * @param {string} config.exporter.url - OTLP endpoint URL |
| 17 | + * @returns {LoggerProvider} The logger provider instance |
| 18 | + */ |
| 19 | +export const createLoggerProviderImpl = (config) => { |
| 20 | + const resource = new Resource({ |
| 21 | + [ATTR_SERVICE_NAME]: config.resource.serviceName, |
| 22 | + [ATTR_SERVICE_VERSION]: config.resource.serviceVersion, |
| 23 | + 'service.namespace': config.resource.serviceNamespace, // Use string literal for namespace |
| 24 | + }); |
| 25 | + |
| 26 | + const logExporter = new OTLPLogExporter({ |
| 27 | + url: config.exporter.url, |
| 28 | + }); |
| 29 | + |
| 30 | + const loggerProvider = new LoggerProvider({ |
| 31 | + resource, |
| 32 | + logRecordProcessors: [new BatchLogRecordProcessor(logExporter)] |
| 33 | + }); |
| 34 | + |
| 35 | + return loggerProvider; |
| 36 | +}; |
| 37 | + |
| 38 | +/** |
| 39 | + * Register the logger provider globally |
| 40 | + * @param {LoggerProvider} provider - The logger provider to register |
| 41 | + * @returns {void} |
| 42 | + */ |
| 43 | +export const registerLoggerProviderImpl = (provider) => { |
| 44 | + logs.setGlobalLoggerProvider(provider); |
| 45 | +}; |
| 46 | + |
| 47 | +/** |
| 48 | + * Create and enable Pino instrumentation to send logs to OpenTelemetry |
| 49 | + * This must be called BEFORE creating any Pino loggers |
| 50 | + * @returns {PinoInstrumentation} The instrumentation instance |
| 51 | + */ |
| 52 | +export const createPinoInstrumentationImpl = () => { |
| 53 | + const instrumentation = new PinoInstrumentation({ |
| 54 | + logHook: (span, record, level) => { |
| 55 | + // Optionally correlate logs with active span |
| 56 | + if (span) { |
| 57 | + record['trace_id'] = span.spanContext().traceId; |
| 58 | + record['span_id'] = span.spanContext().spanId; |
| 59 | + record['trace_flags'] = span.spanContext().traceFlags; |
| 60 | + } |
| 61 | + }, |
| 62 | + }); |
| 63 | + |
| 64 | + instrumentation.enable(); |
| 65 | + return instrumentation; |
| 66 | +}; |
| 67 | + |
| 68 | +/** |
| 69 | + * Hook up an existing Pino logger to OpenTelemetry |
| 70 | + * Note: This is for already-created loggers. Ideally use instrumentation before logger creation. |
| 71 | + * @param {Object} logger - Pino logger instance |
| 72 | + * @returns {void} |
| 73 | + */ |
| 74 | +export const hookPinoToOtelImpl = (logger) => { |
| 75 | + // The instrumentation should handle this automatically when enabled before logger creation |
| 76 | + // This function exists for compatibility but the instrumentation approach is preferred |
| 77 | + console.warn('hookPinoToOtelImpl called - prefer enabling instrumentation before logger creation'); |
| 78 | +}; |
0 commit comments