UNPKG

n8n

Version:

n8n Workflow Automation Tool

120 lines 5.82 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var OtelService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.OtelService = void 0; const backend_common_1 = require("@n8n/backend-common"); const di_1 = require("@n8n/di"); const api_1 = require("@opentelemetry/api"); const exporter_trace_otlp_proto_1 = require("@opentelemetry/exporter-trace-otlp-proto"); const resources_1 = require("@opentelemetry/resources"); const sdk_node_1 = require("@opentelemetry/sdk-node"); const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node"); const n8n_core_1 = require("n8n-core"); const constants_1 = require("../../constants"); const otel_config_1 = require("./otel.config"); const otel_constants_1 = require("./otel.constants"); let OtelService = OtelService_1 = class OtelService { constructor(config, instanceSettings, logger) { this.config = config; this.instanceSettings = instanceSettings; this.logger = logger; this.hasLoggedStartupConnectivityFailure = false; } init() { if (!this.config.enabled) return; this.configureDiagnosticsLogger(); const otlpTracesUrl = this.buildOtlpTracesUrl(this.config.exporterEndpoint, this.config.exporterTracingPath); const otlpHeaders = this.parseOtlpHeaders(this.config.exporterHeaders); this.sdk = new sdk_node_1.NodeSDK({ resource: (0, resources_1.resourceFromAttributes)({ [otel_constants_1.ATTR.OTEL_SERVICE_NAME]: this.config.exporterServiceName, [otel_constants_1.ATTR.OTEL_SERVICE_VERSION]: constants_1.N8N_VERSION, [otel_constants_1.ATTR.INSTANCE_ID]: this.instanceSettings.instanceId, [otel_constants_1.ATTR.INSTANCE_ROLE]: this.instanceSettings.instanceType, }), traceExporter: new exporter_trace_otlp_proto_1.OTLPTraceExporter({ url: otlpTracesUrl, headers: otlpHeaders, }), sampler: new sdk_trace_node_1.TraceIdRatioBasedSampler(this.config.tracesSampleRate), }); this.sdk.start(); void this.checkEndpointReachability(otlpTracesUrl); } async shutdown() { await this.sdk?.shutdown(); } parseOtlpHeaders(headersToSplit) { const headers = {}; for (const pair of headersToSplit.split(',')) { const trimmedPair = pair.trim(); if (!trimmedPair) continue; if (!trimmedPair.includes('=')) { this.logger.warn(`Skipping invalid OTEL exporter header "${trimmedPair}": missing "=" separator. Expected format: "key=value".`); continue; } const [key, ...rest] = trimmedPair.split('='); const trimmedKey = key.trim(); if (!trimmedKey) { this.logger.warn(`Skipping invalid OTEL exporter header "${trimmedPair}": empty key. Expected format: "key=value".`); continue; } headers[trimmedKey] = rest.join('=').trim(); } return headers; } configureDiagnosticsLogger() { if (OtelService_1.isDiagnosticsLoggerConfigured) return; const diagnosticsLogger = { error: (...args) => this.logger.error('OpenTelemetry diagnostics error', { args }), warn: (...args) => this.logger.warn('OpenTelemetry diagnostics warning', { args }), info: (...args) => this.logger.info('OpenTelemetry diagnostics info', { args }), debug: (...args) => this.logger.debug('OpenTelemetry diagnostics debug', { args }), verbose: (...args) => this.logger.debug('OpenTelemetry diagnostics verbose', { args }), }; api_1.diag.setLogger(diagnosticsLogger, api_1.DiagLogLevel.WARN); OtelService_1.isDiagnosticsLoggerConfigured = true; } buildOtlpTracesUrl(endpoint, path) { const exporterEndpointWithoutTrailingSlash = endpoint.replace(/\/+$/, ''); return `${exporterEndpointWithoutTrailingSlash}${path}`; } async checkEndpointReachability(url) { try { await fetch(url, { method: 'HEAD', signal: AbortSignal.timeout(this.config.startupConnectivityTimeoutMs), }); } catch (error) { if (this.hasLoggedStartupConnectivityFailure) return; this.hasLoggedStartupConnectivityFailure = true; this.logger.error('Failed to connect to OpenTelemetry OTLP endpoint during startup', { endpoint: url, error: error instanceof Error ? error.message : String(error), }); } } }; exports.OtelService = OtelService; OtelService.isDiagnosticsLoggerConfigured = false; exports.OtelService = OtelService = OtelService_1 = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [otel_config_1.OtelConfig, n8n_core_1.InstanceSettings, backend_common_1.Logger]) ], OtelService); //# sourceMappingURL=otel.service.js.map