autotel
Version:
Write Once, Observe Anywhere
1,045 lines (1,036 loc) • 35.9 kB
JavaScript
'use strict';
var chunkOC6X2VIN_cjs = require('./chunk-OC6X2VIN.cjs');
var chunkCEAQK2QY_cjs = require('./chunk-CEAQK2QY.cjs');
var chunkZNMBW67B_cjs = require('./chunk-ZNMBW67B.cjs');
var chunkIOYFAFHJ_cjs = require('./chunk-IOYFAFHJ.cjs');
var chunkCMNGGTQL_cjs = require('./chunk-CMNGGTQL.cjs');
var chunkCU6IDACR_cjs = require('./chunk-CU6IDACR.cjs');
var chunk6S5RUKU3_cjs = require('./chunk-6S5RUKU3.cjs');
var chunkYS6C2YJE_cjs = require('./chunk-YS6C2YJE.cjs');
var chunkVH77IPJN_cjs = require('./chunk-VH77IPJN.cjs');
var api = require('@opentelemetry/api');
var sdkNode = require('@opentelemetry/sdk-node');
var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
var resources = require('@opentelemetry/resources');
var semanticConventions = require('@opentelemetry/semantic-conventions');
var sdkMetrics = require('@opentelemetry/sdk-metrics');
var exporterMetricsOtlpHttp = require('@opentelemetry/exporter-metrics-otlp-http');
var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
var exporterLogsOtlpHttp = require('@opentelemetry/exporter-logs-otlp-http');
var sdkLogs = require('@opentelemetry/sdk-logs');
var BaggageSpanProcessor = class {
prefix;
constructor(options = {}) {
this.prefix = options.prefix ?? "baggage.";
}
onStart(span, parentContext) {
let baggage = api.propagation.getBaggage(parentContext);
if (!baggage) {
baggage = api.propagation.getBaggage(api.context.active());
}
if (!baggage) {
try {
const { getActiveContextWithBaggage } = chunkYS6C2YJE_cjs.requireModule("./trace-context");
const storedContext = getActiveContextWithBaggage();
baggage = api.propagation.getBaggage(storedContext);
} catch {
}
}
if (!baggage) return;
for (const [key, entry] of baggage.getAllEntries()) {
span.setAttribute(`${this.prefix}${key}`, entry.value);
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onEnd(_span) {
}
async shutdown() {
}
async forceFlush() {
}
};
// src/redact-values.ts
function createStringRedactor(config2) {
const resolved = typeof config2 === "string" ? chunkCMNGGTQL_cjs.REDACTOR_PRESETS[config2] : config2;
const valuePatterns = resolved.valuePatterns ?? [];
const defaultReplacement = resolved.replacement ?? "[REDACTED]";
return (value) => {
let result = value;
for (const { pattern, replacement } of valuePatterns) {
pattern.lastIndex = 0;
result = result.replaceAll(pattern, replacement ?? defaultReplacement);
}
return result;
};
}
// src/posthog-logs.ts
var RedactingLogRecordProcessor = class {
constructor(wrapped, redact) {
this.wrapped = wrapped;
this.redact = redact;
}
wrapped;
redact;
onEmit(logRecord, context) {
if (logRecord.body && typeof logRecord.body === "string") {
logRecord.body = this.redact(logRecord.body);
}
if (logRecord.attributes) {
for (const [key, value] of Object.entries(logRecord.attributes)) {
if (typeof value === "string") {
logRecord.attributes[key] = this.redact(value);
} else if (Array.isArray(value)) {
logRecord.attributes[key] = value.map(
(item) => typeof item === "string" ? this.redact(item) : item
);
}
}
}
this.wrapped.onEmit(logRecord, context);
}
shutdown() {
return this.wrapped.shutdown();
}
forceFlush() {
return this.wrapped.forceFlush();
}
};
function buildPostHogLogProcessors(config2, stringRedactor) {
const url = config2?.url || process.env.POSTHOG_LOGS_URL;
if (!url) return [];
const sdkLogs = chunkYS6C2YJE_cjs.safeRequire("@opentelemetry/sdk-logs");
const exporterModule = chunkYS6C2YJE_cjs.safeRequire("@opentelemetry/exporter-logs-otlp-http");
if (!sdkLogs || !exporterModule) return [];
const exporter = new exporterModule.OTLPLogExporter({ url });
let processor = new sdkLogs.BatchLogRecordProcessor(
exporter
);
if (stringRedactor) {
processor = new RedactingLogRecordProcessor(processor, stringRedactor);
}
return [processor];
}
function isValidUrl(urlString) {
try {
const url = new URL(urlString);
return url.protocol === "http:" || url.protocol === "https:";
} catch {
return false;
}
}
function resolveOtelEnv() {
const env = {};
if (process.env.OTEL_SERVICE_NAME) {
const value = process.env.OTEL_SERVICE_NAME.trim();
if (value) {
env.OTEL_SERVICE_NAME = value;
}
}
if (process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {
const value = process.env.OTEL_EXPORTER_OTLP_ENDPOINT.trim();
if (value && isValidUrl(value)) {
env.OTEL_EXPORTER_OTLP_ENDPOINT = value;
}
}
if (process.env.OTEL_EXPORTER_OTLP_HEADERS) {
const value = process.env.OTEL_EXPORTER_OTLP_HEADERS.trim();
if (value) {
env.OTEL_EXPORTER_OTLP_HEADERS = value;
}
}
if (process.env.OTEL_RESOURCE_ATTRIBUTES) {
const value = process.env.OTEL_RESOURCE_ATTRIBUTES.trim();
if (value) {
env.OTEL_RESOURCE_ATTRIBUTES = value;
}
}
if (process.env.OTEL_EXPORTER_OTLP_PROTOCOL) {
const value = process.env.OTEL_EXPORTER_OTLP_PROTOCOL.trim().toLowerCase();
if (value === "http" || value === "grpc") {
env.OTEL_EXPORTER_OTLP_PROTOCOL = value;
}
}
if (process.env.OTEL_TRACES_SAMPLER) {
const value = process.env.OTEL_TRACES_SAMPLER.trim();
if (value) {
env.OTEL_TRACES_SAMPLER = value;
}
}
if (process.env.OTEL_TRACES_SAMPLER_ARG) {
const value = process.env.OTEL_TRACES_SAMPLER_ARG.trim();
if (value) {
env.OTEL_TRACES_SAMPLER_ARG = value;
}
}
return env;
}
function parseRatioSamplerArg(samplerName, samplerArg) {
if (samplerArg === void 0) {
return 1;
}
const ratio = Number(samplerArg);
if (!Number.isFinite(ratio) || ratio < 0 || ratio > 1) {
console.error(
`[autotel] Invalid OTEL_TRACES_SAMPLER_ARG="${samplerArg}" for ${samplerName}. Expected a number in [0..1]. Falling back to 1.0.`
);
return 1;
}
return ratio;
}
function warnOnUnusedSamplerArg(samplerName, samplerArg) {
if (samplerArg !== void 0) {
console.error(
`[autotel] OTEL_TRACES_SAMPLER_ARG is not used by OTEL_TRACES_SAMPLER="${samplerName}". Ignoring value "${samplerArg}".`
);
}
}
function createSamplerFromEnv(env) {
const samplerName = env.OTEL_TRACES_SAMPLER;
if (!samplerName) {
return void 0;
}
switch (samplerName) {
case "always_on":
warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);
return new sdkTraceBase.AlwaysOnSampler();
case "always_off":
warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);
return new sdkTraceBase.AlwaysOffSampler();
case "traceidratio":
return new sdkTraceBase.TraceIdRatioBasedSampler(
parseRatioSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG)
);
case "parentbased_always_on":
warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);
return new sdkTraceBase.ParentBasedSampler({ root: new sdkTraceBase.AlwaysOnSampler() });
case "parentbased_always_off":
warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);
return new sdkTraceBase.ParentBasedSampler({ root: new sdkTraceBase.AlwaysOffSampler() });
case "parentbased_traceidratio":
return new sdkTraceBase.ParentBasedSampler({
root: new sdkTraceBase.TraceIdRatioBasedSampler(
parseRatioSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG)
)
});
case "jaeger_remote":
case "parentbased_jaeger_remote":
case "xray":
console.error(
`[autotel] OTEL_TRACES_SAMPLER="${samplerName}" is not supported yet by autotel. Falling back to the next sampler source.`
);
return void 0;
default:
console.error(
`[autotel] Unknown OTEL_TRACES_SAMPLER="${samplerName}". Falling back to the next sampler source.`
);
return void 0;
}
}
function parseResourceAttributes(input) {
if (!input || input.trim() === "") {
return {};
}
const attributes = {};
const pairs = input.split(",");
for (const pair of pairs) {
const trimmedPair = pair.trim();
if (!trimmedPair) continue;
const equalIndex = trimmedPair.indexOf("=");
if (equalIndex === -1) {
continue;
}
const key = trimmedPair.slice(0, equalIndex).trim();
const value = trimmedPair.slice(equalIndex + 1).trim();
if (key && value) {
attributes[key] = value;
}
}
return attributes;
}
function parseOtlpHeaders(input) {
if (!input || input.trim() === "") {
return {};
}
const headers = {};
const pairs = input.split(",");
for (const pair of pairs) {
const trimmedPair = pair.trim();
if (!trimmedPair) continue;
const equalIndex = trimmedPair.indexOf("=");
if (equalIndex === -1) {
continue;
}
const key = trimmedPair.slice(0, equalIndex).trim();
const value = trimmedPair.slice(equalIndex + 1).trim();
if (key && value) {
headers[key] = value;
}
}
return headers;
}
function envToConfig(env) {
const config2 = {};
if (env.OTEL_SERVICE_NAME) {
config2.service = env.OTEL_SERVICE_NAME;
}
if (env.OTEL_EXPORTER_OTLP_ENDPOINT) {
config2.endpoint = env.OTEL_EXPORTER_OTLP_ENDPOINT;
}
if (env.OTEL_EXPORTER_OTLP_PROTOCOL) {
config2.protocol = env.OTEL_EXPORTER_OTLP_PROTOCOL;
}
if (env.OTEL_EXPORTER_OTLP_HEADERS) {
config2.headers = parseOtlpHeaders(env.OTEL_EXPORTER_OTLP_HEADERS);
}
const resourceAttrs = parseResourceAttributes(env.OTEL_RESOURCE_ATTRIBUTES);
if (Object.keys(resourceAttrs).length > 0) {
config2.resourceAttributes = resourceAttrs;
}
const sampler = createSamplerFromEnv(env);
if (sampler) {
config2.otelSampler = sampler;
}
return config2;
}
function resolveConfigFromEnv() {
const env = resolveOtelEnv();
return envToConfig(env);
}
// src/devtools.ts
var defaultHost = "127.0.0.1";
var defaultPort = 4318;
function resolveDevtoolsConfig(config2) {
if (!config2) {
return {
enabled: false,
endpoint: void 0,
embedded: false,
host: defaultHost,
port: defaultPort,
verbose: false
};
}
if (config2 === true) {
return {
enabled: true,
endpoint: `http://${defaultHost}:${defaultPort}`,
embedded: false,
host: defaultHost,
port: defaultPort,
verbose: false
};
}
const enabled = config2.enabled ?? true;
const host = config2.host ?? defaultHost;
const port = config2.port ?? defaultPort;
const endpoint = config2.endpoint ?? `http://${host}:${port}`;
return {
enabled,
endpoint: enabled ? endpoint : void 0,
embedded: enabled && (config2.embedded ?? false),
host,
port,
verbose: config2.verbose ?? false
};
}
// src/init.ts
var silentLogger = {
info: () => {
},
warn: () => {
},
error: () => {
},
debug: () => {
}
};
function toOtelSampler(sampler) {
return {
shouldSample(_context, _traceId, spanName, _spanKind, _attributes, links) {
const shouldTrace = sampler.shouldSample({
operationName: spanName,
args: [],
links
});
return {
decision: shouldTrace ? sdkTraceBase.SamplingDecision.RECORD_AND_SAMPLED : sdkTraceBase.SamplingDecision.NOT_RECORD
};
},
toString() {
return `AutotelSamplerAdapter`;
}
};
}
var OTLPTraceExporterGRPC;
var OTLPMetricExporterGRPC;
var OTLPLogExporterGRPC;
function loadGRPCTraceExporter() {
if (OTLPTraceExporterGRPC) return OTLPTraceExporterGRPC;
try {
const grpcModule = chunkYS6C2YJE_cjs.requireModule("@opentelemetry/exporter-trace-otlp-grpc");
OTLPTraceExporterGRPC = grpcModule.OTLPTraceExporter;
return OTLPTraceExporterGRPC;
} catch {
throw new Error(
"gRPC trace exporter not found. Install @opentelemetry/exporter-trace-otlp-grpc"
);
}
}
function loadGRPCMetricExporter() {
if (OTLPMetricExporterGRPC) return OTLPMetricExporterGRPC;
try {
const grpcModule = chunkYS6C2YJE_cjs.requireModule("@opentelemetry/exporter-metrics-otlp-grpc");
OTLPMetricExporterGRPC = grpcModule.OTLPMetricExporter;
return OTLPMetricExporterGRPC;
} catch {
throw new Error(
"gRPC metric exporter not found. Install @opentelemetry/exporter-metrics-otlp-grpc"
);
}
}
function createTraceExporter(protocol, config2) {
if (protocol === "grpc") {
const Exporter = loadGRPCTraceExporter();
return new Exporter(config2);
}
return new exporterTraceOtlpHttp.OTLPTraceExporter(config2);
}
function createMetricExporter(protocol, config2) {
if (protocol === "grpc") {
const Exporter = loadGRPCMetricExporter();
return new Exporter(config2);
}
return new exporterMetricsOtlpHttp.OTLPMetricExporter(config2);
}
function loadGRPCLogExporter() {
if (OTLPLogExporterGRPC) return OTLPLogExporterGRPC;
try {
const grpcModule = chunkYS6C2YJE_cjs.requireModule("@opentelemetry/exporter-logs-otlp-grpc");
OTLPLogExporterGRPC = grpcModule.OTLPLogExporter;
return OTLPLogExporterGRPC;
} catch {
throw new Error(
"gRPC log exporter not found. Install @opentelemetry/exporter-logs-otlp-grpc"
);
}
}
function createLogExporter(protocol, config2) {
if (protocol === "grpc") {
const Exporter = loadGRPCLogExporter();
return new Exporter(config2);
}
return new exporterLogsOtlpHttp.OTLPLogExporter(config2);
}
function resolveProtocol(configProtocol) {
if (configProtocol === "grpc" || configProtocol === "http") {
return configProtocol;
}
const envProtocol = process.env.OTEL_EXPORTER_OTLP_PROTOCOL;
if (envProtocol === "grpc") return "grpc";
if (envProtocol === "http/protobuf" || envProtocol === "http") return "http";
return "http";
}
function formatEndpointUrl(endpoint, signal, protocol) {
if (protocol === "grpc") {
return endpoint.replace(/\/(v1\/)?(traces|metrics|logs)$/, "");
}
if (!endpoint.endsWith(`/v1/${signal}`)) {
return `${endpoint}/v1/${signal}`;
}
return endpoint;
}
var initialized = false;
var locked = false;
var config = null;
var sdk = null;
var warnedOnce = false;
var logger = silentLogger;
var validationConfig = null;
var eventsConfig = null;
var _stringRedactor = null;
var _optionalRequire = chunkYS6C2YJE_cjs.safeRequire;
var _devtoolsClose = null;
var LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
function lockLogger() {
locked = true;
}
function isLoggerLocked() {
return locked;
}
function createSilentLogger() {
return {
info: () => {
},
warn: () => {
},
error: () => {
},
debug: () => {
}
};
}
function wrapLogger(base, silent, minLevel) {
if (silent) return createSilentLogger();
const threshold = LOG_LEVELS[minLevel];
const wrap = (fn, level) => {
if (LOG_LEVELS[level] < threshold) {
return (() => {
});
}
return ((...args) => fn(...args));
};
return {
debug: wrap(base.debug, "debug"),
info: wrap(base.info, "info"),
warn: wrap(base.warn, "warn"),
error: wrap(base.error, "error")
};
}
function detectEnvironmentAttributes() {
const attrs = {};
const commitSha = process.env.COMMIT_SHA || process.env.GITHUB_SHA || process.env.VERCEL_GIT_COMMIT_SHA || process.env.CF_PAGES_COMMIT_SHA || process.env.AWS_CODEPIPELINE_EXECUTION_ID;
if (commitSha) attrs["service.commit.sha"] = commitSha;
const region = process.env.VERCEL_REGION || process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || process.env.FLY_REGION || process.env.CF_REGION || process.env.GOOGLE_CLOUD_REGION;
if (region) attrs["service.region"] = region;
const version = process.env.APP_VERSION || process.env.HEROKU_RELEASE_VERSION || process.env.VERCEL_GIT_COMMIT_REF;
if (version) attrs["service.deploy.version"] = version;
return attrs;
}
function resolveMetricsFlag(configFlag = "auto") {
const envFlag = process.env.AUTOTEL_METRICS;
if (envFlag === "on" || envFlag === "true") return true;
if (envFlag === "off" || envFlag === "false") return false;
if (configFlag === true) return true;
if (configFlag === false) return false;
return true;
}
function resolveLogsFlag(configFlag = "auto") {
const envFlag = process.env.AUTOTEL_LOGS;
if (envFlag === "on" || envFlag === "true") return true;
if (envFlag === "off" || envFlag === "false") return false;
if (configFlag === true) return true;
if (configFlag === false) return false;
return false;
}
function resolveDebugFlag(configFlag) {
const envFlag = process.env.AUTOTEL_DEBUG;
if (envFlag === "pretty") return "pretty";
if (envFlag === "true" || envFlag === "1") return true;
if (envFlag === "false" || envFlag === "0") return false;
return configFlag ?? false;
}
function normalizeOtlpHeaders(headers) {
if (!headers) return void 0;
if (typeof headers !== "string") return headers;
const parsed = {};
for (const pair of headers.split(",")) {
const [key, ...valueParts] = pair.split("=");
if (!key || valueParts.length === 0) continue;
parsed[key.trim()] = valueParts.join("=").trim();
}
return parsed;
}
function init(cfg) {
if (locked) {
return;
}
const envConfig = resolveConfigFromEnv();
const yamlConfig = chunkOC6X2VIN_cjs.loadYamlConfig() ?? {};
const mergedConfig = {
...envConfig,
// Environment variables (lowest priority)
...yamlConfig,
// YAML file (middle priority)
...cfg,
// Explicit config (highest priority)
// Deep merge for resourceAttributes
resourceAttributes: {
...envConfig.resourceAttributes,
...yamlConfig.resourceAttributes,
...detectEnvironmentAttributes(),
...cfg.resourceAttributes
},
// Handle headers merge (can be string or object)
headers: cfg.headers ?? yamlConfig.headers ?? envConfig.headers
};
if (mergedConfig.attributeRedactor !== void 0) {
const normalizedRedactor = chunkCMNGGTQL_cjs.normalizeAttributeRedactorConfig(
mergedConfig.attributeRedactor
);
if (!normalizedRedactor) {
throw new Error("Invalid attributeRedactor config");
}
mergedConfig.attributeRedactor = normalizedRedactor;
}
const devtoolsConfig = resolveDevtoolsConfig(mergedConfig.devtools);
if (devtoolsConfig.enabled && mergedConfig.logs === void 0) {
mergedConfig.logs = true;
}
const silent = mergedConfig.silent ?? false;
const minLevel = mergedConfig.minLevel ?? "info";
const baseLogger = mergedConfig.logger || silentLogger;
logger = wrapLogger(baseLogger, silent, minLevel);
if (initialized) {
logger.warn(
{},
"[autotel] init() called again - last config wins. This may cause unexpected behavior."
);
}
config = mergedConfig;
validationConfig = mergedConfig.validation || null;
eventsConfig = mergedConfig.events || null;
let endpoint = mergedConfig.endpoint ?? devtoolsConfig.endpoint;
const otlpHeaders = normalizeOtlpHeaders(mergedConfig.headers);
const version = mergedConfig.version || detectVersion();
const environment = mergedConfig.environment || process.env.NODE_ENV || "development";
const metricsEnabled = resolveMetricsFlag(mergedConfig.metrics);
const logsEnabled = resolveLogsFlag(mergedConfig.logs);
if (devtoolsConfig.enabled && devtoolsConfig.embedded) {
const devtoolsModule = _optionalRequire("autotel-devtools");
if (devtoolsModule?.createDevtools) {
const devtoolsInstance = devtoolsModule.createDevtools({
port: devtoolsConfig.port,
host: devtoolsConfig.host,
verbose: devtoolsConfig.verbose
});
_devtoolsClose = devtoolsInstance.close;
endpoint = `http://${devtoolsConfig.host}:${devtoolsInstance.port}`;
logger.info(
{},
`[autotel] autotel-devtools embedded server started at ${endpoint}`
);
} else {
logger.warn(
{},
"[autotel] devtools.embedded requested but autotel-devtools is not installed. Falling back to endpoint-only mode."
);
}
}
const hostname = detectHostname();
let resource = resources.resourceFromAttributes({
[semanticConventions.ATTR_SERVICE_NAME]: mergedConfig.service,
[semanticConventions.ATTR_SERVICE_VERSION]: version,
// Support both old and new OpenTelemetry semantic conventions for environment
"deployment.environment": environment,
// Deprecated but widely supported
"deployment.environment.name": environment
// OTel v1.27.0+ standard
});
if (hostname) {
resource = resource.merge(
resources.resourceFromAttributes({
"host.name": hostname,
// OpenTelemetry standard
"datadog.host.name": hostname
// Datadog-specific, highest priority for Datadog
})
);
}
if (mergedConfig.resource) {
resource = resource.merge(mergedConfig.resource);
}
if (mergedConfig.resourceAttributes) {
resource = resource.merge(
resources.resourceFromAttributes(mergedConfig.resourceAttributes)
);
}
const protocol = resolveProtocol(mergedConfig.protocol);
let spanProcessors = [];
if (mergedConfig.spanProcessors && mergedConfig.spanProcessors.length > 0) {
spanProcessors.push(...mergedConfig.spanProcessors);
} else if (mergedConfig.spanExporters && mergedConfig.spanExporters.length > 0) {
for (const exporter of mergedConfig.spanExporters) {
spanProcessors.push(
new chunkCEAQK2QY_cjs.TailSamplingSpanProcessor(new sdkTraceBase.BatchSpanProcessor(exporter))
);
}
} else if (endpoint) {
const traceExporter = createTraceExporter(protocol, {
url: formatEndpointUrl(endpoint, "traces", protocol),
headers: otlpHeaders
});
spanProcessors.push(
new chunkCEAQK2QY_cjs.TailSamplingSpanProcessor(new sdkTraceBase.BatchSpanProcessor(traceExporter))
);
}
if (mergedConfig.baggage) {
const prefix = typeof mergedConfig.baggage === "string" ? mergedConfig.baggage ? `${mergedConfig.baggage}.` : "" : "baggage.";
spanProcessors.push(new BaggageSpanProcessor({ prefix }));
}
const debugMode = resolveDebugFlag(mergedConfig.debug);
if (debugMode === "pretty") {
spanProcessors.push(new sdkTraceBase.SimpleSpanProcessor(new chunkCU6IDACR_cjs.PrettyConsoleExporter()));
} else if (debugMode === true) {
spanProcessors.push(new sdkTraceBase.SimpleSpanProcessor(new sdkTraceBase.ConsoleSpanExporter()));
}
if (mergedConfig.canonicalLogLines?.enabled) {
const canonicalOptions = {
logger: mergedConfig.canonicalLogLines.logger || mergedConfig.logger,
rootSpansOnly: mergedConfig.canonicalLogLines.rootSpansOnly,
minLevel: mergedConfig.canonicalLogLines.minLevel,
messageFormat: mergedConfig.canonicalLogLines.messageFormat,
includeResourceAttributes: mergedConfig.canonicalLogLines.includeResourceAttributes,
shouldEmit: mergedConfig.canonicalLogLines.shouldEmit,
keep: mergedConfig.canonicalLogLines.keep,
drain: mergedConfig.canonicalLogLines.drain,
onDrainError: mergedConfig.canonicalLogLines.onDrainError,
pretty: mergedConfig.canonicalLogLines.pretty
};
spanProcessors.push(new chunk6S5RUKU3_cjs.CanonicalLogLineProcessor(canonicalOptions));
}
if (mergedConfig.attributeRedactor && spanProcessors.length > 0) {
spanProcessors = spanProcessors.map(
(processor) => new chunkCMNGGTQL_cjs.AttributeRedactingProcessor(processor, {
redactor: mergedConfig.attributeRedactor
})
);
}
if (mergedConfig.attributeRedactor) {
_stringRedactor = createStringRedactor(mergedConfig.attributeRedactor);
}
if (_stringRedactor && mergedConfig.subscribers) {
for (const subscriber of mergedConfig.subscribers) {
if ("setStringRedactor" in subscriber && typeof subscriber.setStringRedactor === "function") {
subscriber.setStringRedactor(_stringRedactor);
}
}
}
if (mergedConfig.spanNameNormalizer && spanProcessors.length > 0) {
spanProcessors = spanProcessors.map(
(processor) => new chunkIOYFAFHJ_cjs.SpanNameNormalizingProcessor(processor, {
normalizer: mergedConfig.spanNameNormalizer
})
);
}
if (mergedConfig.spanFilter && spanProcessors.length > 0) {
spanProcessors = spanProcessors.map(
(processor) => new chunkZNMBW67B_cjs.FilteringSpanProcessor(processor, {
filter: mergedConfig.spanFilter
})
);
}
const metricReaders = [];
if (mergedConfig.metricReaders && mergedConfig.metricReaders.length > 0) {
metricReaders.push(...mergedConfig.metricReaders);
} else if (metricsEnabled && endpoint) {
const metricExporter = createMetricExporter(protocol, {
url: formatEndpointUrl(endpoint, "metrics", protocol),
headers: otlpHeaders
});
metricReaders.push(
new sdkMetrics.PeriodicExportingMetricReader({
exporter: metricExporter
})
);
}
let logRecordProcessors;
if (mergedConfig.logRecordProcessors && mergedConfig.logRecordProcessors.length > 0) {
logRecordProcessors = [...mergedConfig.logRecordProcessors];
}
if (logsEnabled && endpoint) {
const logExporter = createLogExporter(protocol, {
url: formatEndpointUrl(endpoint, "logs", protocol),
headers: otlpHeaders
});
let processor = new sdkLogs.BatchLogRecordProcessor(
logExporter
);
if (_stringRedactor) {
processor = new RedactingLogRecordProcessor(processor, _stringRedactor);
}
if (!logRecordProcessors) {
logRecordProcessors = [];
}
logRecordProcessors.push(processor);
logger.info({}, "[autotel] OTLP log exporter configured");
}
const posthogProcessors = buildPostHogLogProcessors(
mergedConfig.posthog,
_stringRedactor
);
if (posthogProcessors.length > 0) {
if (!logRecordProcessors) {
logRecordProcessors = [];
}
logRecordProcessors.push(...posthogProcessors);
logger.info({}, "[autotel] PostHog OTLP logs configured");
}
let finalInstrumentations = mergedConfig.instrumentations ? [...mergedConfig.instrumentations] : [];
if (mergedConfig.autoInstrumentations !== void 0 && mergedConfig.autoInstrumentations !== false) {
const isESM = isESMMode();
if (isESM) {
logger.info(
{},
"[autotel] ESM mode detected. For auto-instrumentation to work:\n 1. Install @opentelemetry/auto-instrumentations-node as a direct dependency\n 2. Import autotel/register FIRST in your instrumentation file\n 3. Use getNodeAutoInstrumentations() directly instead of autoInstrumentations\n See: https://github.com/jagreehal/autotel#esm-setup"
);
}
try {
const manualInstrumentationNames = getInstrumentationNames(
mergedConfig.instrumentations ?? []
);
if (manualInstrumentationNames.size > 0) {
const manualNames = [...manualInstrumentationNames].join(", ");
logger.info(
{},
`[autotel] Detected manual instrumentations (${manualNames}). These will take precedence over auto-instrumentations. Tip: Set autoInstrumentations:false if you want full manual control, or remove manual configs to use auto-instrumentations.`
);
}
const autoInstrumentations = getAutoInstrumentations(
mergedConfig.autoInstrumentations,
manualInstrumentationNames
);
if (autoInstrumentations && autoInstrumentations.length > 0) {
finalInstrumentations = [
...finalInstrumentations,
...autoInstrumentations
];
}
} catch (error) {
logger.warn(
{},
`[autotel] Failed to configure auto-instrumentations: ${error instanceof Error ? error.message : String(error)}`
);
}
}
const autotelSampler = mergedConfig.sampler ?? (mergedConfig.sampling ? chunkVH77IPJN_cjs.resolveSamplingPreset(mergedConfig.sampling) : void 0);
if (autotelSampler) {
mergedConfig.sampler = autotelSampler;
}
const sampler = autotelSampler ? toOtelSampler(autotelSampler) : envConfig.otelSampler ?? toOtelSampler(chunkVH77IPJN_cjs.samplingPresets.production());
const sdkOptions = {
resource,
sampler,
instrumentations: finalInstrumentations
};
if (spanProcessors.length > 0) {
sdkOptions.spanProcessors = spanProcessors;
}
if (metricReaders.length > 0) {
sdkOptions.metricReaders = metricReaders;
}
if (logRecordProcessors && logRecordProcessors.length > 0) {
sdkOptions.logRecordProcessors = logRecordProcessors;
}
sdk = mergedConfig.sdkFactory ? mergedConfig.sdkFactory(sdkOptions) : new sdkNode.NodeSDK(sdkOptions);
if (!sdk) {
throw new Error("[autotel] sdkFactory must return a NodeSDK instance");
}
sdk.start();
if (mergedConfig.openllmetry?.enabled) {
const traceloop = _optionalRequire("@traceloop/node-server-sdk");
if (traceloop) {
const initOptions = {
...mergedConfig.openllmetry.options
};
try {
const tracerProvider = sdk.getTracerProvider();
initOptions.tracerProvider = tracerProvider;
} catch {
}
if (mergedConfig.spanExporters?.[0]) {
initOptions.exporter = mergedConfig.spanExporters[0];
}
if (typeof traceloop.initialize === "function") {
traceloop.initialize(initOptions);
logger.info({}, "[autotel] OpenLLMetry initialized successfully");
} else {
logger.warn(
{},
"[autotel] OpenLLMetry initialize function not found. Check @traceloop/node-server-sdk version."
);
}
} else {
logger.warn(
{},
"[autotel] OpenLLMetry enabled but @traceloop/node-server-sdk is not installed. Install it as a peer dependency to use OpenLLMetry integration."
);
}
}
initialized = true;
}
function getInstrumentationNames(instrumentations) {
const names = /* @__PURE__ */ new Set();
if (!instrumentations) return names;
for (const instrumentation of instrumentations) {
if (instrumentation && typeof instrumentation === "object") {
names.add(instrumentation.constructor.name);
}
}
return names;
}
var INSTRUMENTATION_CLASS_TO_PACKAGE = {
HttpInstrumentation: "@opentelemetry/instrumentation-http",
HttpsInstrumentation: "@opentelemetry/instrumentation-http",
ExpressInstrumentation: "@opentelemetry/instrumentation-express",
FastifyInstrumentation: "@opentelemetry/instrumentation-fastify",
MongoDBInstrumentation: "@opentelemetry/instrumentation-mongodb",
MongooseInstrumentation: "@opentelemetry/instrumentation-mongoose",
PrismaInstrumentation: "@opentelemetry/instrumentation-prisma",
PinoInstrumentation: "@opentelemetry/instrumentation-pino",
WinstonInstrumentation: "@opentelemetry/instrumentation-winston",
RedisInstrumentation: "@opentelemetry/instrumentation-redis",
GraphQLInstrumentation: "@opentelemetry/instrumentation-graphql",
GrpcInstrumentation: "@opentelemetry/instrumentation-grpc",
IORedisInstrumentation: "@opentelemetry/instrumentation-ioredis",
KnexInstrumentation: "@opentelemetry/instrumentation-knex",
NestJsInstrumentation: "@opentelemetry/instrumentation-nestjs-core",
PgInstrumentation: "@opentelemetry/instrumentation-pg",
MySQLInstrumentation: "@opentelemetry/instrumentation-mysql",
MySQL2Instrumentation: "@opentelemetry/instrumentation-mysql2"
};
function isESMMode() {
try {
const fs = chunkYS6C2YJE_cjs.requireModule("node:fs");
try {
const pkg = JSON.parse(
fs.readFileSync(`${process.cwd()}/package.json`, "utf8")
);
return pkg.type === "module";
} catch {
return false;
}
} catch {
return false;
}
}
function loadNodeAutoInstrumentations() {
try {
const mod = chunkYS6C2YJE_cjs.requireModule("@opentelemetry/auto-instrumentations-node");
return mod.getNodeAutoInstrumentations;
} catch {
const isESM = isESMMode();
const baseMessage = "@opentelemetry/auto-instrumentations-node not found.";
if (isESM) {
throw new Error(
`${baseMessage}
ESM Setup Required:
1. Install as a direct dependency: pnpm add /auto-instrumentations-node
2. Create instrumentation.mjs with:
import 'autotel/register'; // MUST be first!
import { init } from 'autotel';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
init({ service: "my-app", instrumentations: getNodeAutoInstrumentations() });
3. Run with: tsx --import ./instrumentation.mjs src/index.ts
See: https://github.com/jagreehal/autotel#esm-setup`
);
}
throw new Error(
`${baseMessage} Install it: pnpm add /auto-instrumentations-node`
);
}
}
function getAutoInstrumentations(integrations, manualInstrumentationNames = /* @__PURE__ */ new Set()) {
if (integrations === false) {
return [];
}
const getNodeAutoInstrumentations = loadNodeAutoInstrumentations();
const exclusionConfig = {};
for (const className of manualInstrumentationNames) {
const packageName = INSTRUMENTATION_CLASS_TO_PACKAGE[className];
if (packageName) {
exclusionConfig[packageName] = { enabled: false };
}
}
if (integrations === true) {
if (Object.keys(exclusionConfig).length > 0) {
return getNodeAutoInstrumentations(exclusionConfig);
}
return getNodeAutoInstrumentations();
}
if (Array.isArray(integrations)) {
const config3 = { ...exclusionConfig };
for (const name of integrations) {
const packageName = `/instrumentation-${name}`;
if (!exclusionConfig[packageName]) {
config3[packageName] = { enabled: true };
}
}
return getNodeAutoInstrumentations(config3);
}
const config2 = {
...exclusionConfig,
...integrations
};
for (const packageName of Object.keys(exclusionConfig)) {
const integrationsKey = Object.keys(integrations).find(
(key) => packageName.includes(key)
);
if (integrationsKey) {
config2[packageName] = { enabled: false };
}
}
return getNodeAutoInstrumentations(config2);
}
function isInitialized() {
return initialized;
}
function getConfig() {
return config;
}
function getLogger() {
return logger;
}
function getValidationConfig() {
return validationConfig;
}
function getEventsConfig() {
return eventsConfig;
}
function warnIfNotInitialized(context) {
if (!initialized && !warnedOnce) {
logger.warn(
{},
`[autotel] ${context} used before init() called. Call init({ service: "..." }) first. See: https://docs.autotel.dev/quickstart`
);
warnedOnce = true;
}
}
function detectVersion() {
try {
const fs = chunkYS6C2YJE_cjs.requireModule("node:fs");
const pkg = JSON.parse(
fs.readFileSync(`${process.cwd()}/package.json`, "utf8")
);
return pkg.version || "1.0.0";
} catch {
return "1.0.0";
}
}
function detectHostname() {
if (process.env.DD_HOSTNAME) {
return process.env.DD_HOSTNAME;
}
if (process.env.HOSTNAME) {
return process.env.HOSTNAME;
}
try {
const os = chunkYS6C2YJE_cjs.requireModule("node:os");
return os.hostname();
} catch {
return void 0;
}
}
async function _closeEmbeddedDevtools() {
if (_devtoolsClose) {
await _devtoolsClose();
_devtoolsClose = null;
}
}
function getSdk() {
return sdk;
}
exports.BaggageSpanProcessor = BaggageSpanProcessor;
exports._closeEmbeddedDevtools = _closeEmbeddedDevtools;
exports.createStringRedactor = createStringRedactor;
exports.getConfig = getConfig;
exports.getEventsConfig = getEventsConfig;
exports.getLogger = getLogger;
exports.getSdk = getSdk;
exports.getValidationConfig = getValidationConfig;
exports.init = init;
exports.isInitialized = isInitialized;
exports.isLoggerLocked = isLoggerLocked;
exports.lockLogger = lockLogger;
exports.warnIfNotInitialized = warnIfNotInitialized;
//# sourceMappingURL=chunk-563EL6O6.cjs.map
//# sourceMappingURL=chunk-563EL6O6.cjs.map