n8n
Version:
n8n Workflow Automation Tool
120 lines • 5.82 kB
JavaScript
;
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