autotel
Version:
Write Once, Observe Anywhere
1,193 lines (1,189 loc) • 40.7 kB
JavaScript
'use strict';
var chunkNCSMD3TK_cjs = require('./chunk-NCSMD3TK.cjs');
var chunkVQTCQKHQ_cjs = require('./chunk-VQTCQKHQ.cjs');
var chunkKKGM42RQ_cjs = require('./chunk-KKGM42RQ.cjs');
var chunkBPO2PQ3T_cjs = require('./chunk-BPO2PQ3T.cjs');
var chunkVH77IPJN_cjs = require('./chunk-VH77IPJN.cjs');
var chunkESLWRGAG_cjs = require('./chunk-ESLWRGAG.cjs');
var api = require('@opentelemetry/api');
var fs = require('fs');
var url = require('url');
var inferenceCache = /* @__PURE__ */ new Map();
var MAX_CACHE_SIZE = 50;
function captureStackTrace() {
const originalStackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 10;
const err = new Error("Stack trace capture");
const stack = err.stack || "";
Error.stackTraceLimit = originalStackTraceLimit;
return stack;
}
function parseCallLocation(stack) {
const lines = stack.split("\n");
let skippedExternalFrame = false;
for (const line of lines) {
if (line.includes("variable-name-inference.ts") || line.includes("variable-name-inference.js") || line.includes("functional.ts") || line.includes("functional.js")) {
continue;
}
const match = line.match(/at\s+(?:.*\s+)?\(?([^:]+):(\d+):(\d+)\)?/) || line.match(/^.*?([^:]+):(\d+):(\d+)/);
if (match) {
let filePath = match[1].trim();
if (filePath.startsWith("file://")) {
try {
filePath = url.fileURLToPath(filePath);
} catch {
continue;
}
}
if (!skippedExternalFrame) {
skippedExternalFrame = true;
continue;
}
return {
file: filePath,
line: Number.parseInt(match[2], 10),
column: Number.parseInt(match[3], 10)
};
}
}
return void 0;
}
function readSourceLine(filePath, lineNumber) {
try {
if (typeof fs.readFileSync !== "function") {
return void 0;
}
const content = fs.readFileSync(filePath, "utf8");
const lines = content.split("\n");
return lines[lineNumber - 1];
} catch {
return void 0;
}
}
function extractVariableName(sourceLine) {
const trimmed = sourceLine.trim();
const patterns = [
// export const varName = anyFunction(
/export\s+const\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
// const varName = anyFunction(
/const\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
// export let varName = anyFunction(
/export\s+let\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
// let varName = anyFunction(
/let\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
// export var varName = anyFunction(
/export\s+var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
// var varName = anyFunction(
/var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/
];
for (const pattern of patterns) {
const match = trimmed.match(pattern);
if (match && match[1]) {
return match[1];
}
}
return void 0;
}
function cacheInference(key, value) {
if (inferenceCache.size >= MAX_CACHE_SIZE) {
const firstKey = inferenceCache.keys().next().value;
if (firstKey) {
inferenceCache.delete(firstKey);
}
}
inferenceCache.set(key, value);
}
function inferVariableNameFromCallStack() {
try {
const stack = captureStackTrace();
const callLocation = parseCallLocation(stack);
if (!callLocation) {
return void 0;
}
const cacheKey = `${callLocation.file}:${callLocation.line}`;
if (inferenceCache.has(cacheKey)) {
return inferenceCache.get(cacheKey);
}
const sourceLine = readSourceLine(callLocation.file, callLocation.line);
if (!sourceLine) {
return void 0;
}
const variableName = extractVariableName(sourceLine);
cacheInference(cacheKey, variableName);
return variableName;
} catch {
return void 0;
}
}
// src/functional.ts
var FACTORY_NAME_HINTS = /* @__PURE__ */ new Set([
"ctx",
"_ctx",
"context",
"tracecontext",
"tracectx"
]);
var TRACE_FACTORY_SET = /* @__PURE__ */ new WeakSet();
var SINGLE_LINE_COMMENT_REGEX = /\/\/.*$/gm;
var MULTI_LINE_COMMENT_REGEX = /\/\*[\s\S]*?\*\//gm;
var PARAM_TOKEN_SANITIZE_REGEX = new RegExp(String.raw`[{}\[\]\s]`, "g");
function markAsTraceFactory(fn) {
TRACE_FACTORY_SET.add(fn);
}
function hasFactoryMark(fn) {
return TRACE_FACTORY_SET.has(fn);
}
function sanitizeParameterToken(token) {
const [firstToken] = token.split("=");
return (firstToken ?? "").replaceAll(PARAM_TOKEN_SANITIZE_REGEX, "").trim();
}
function getFirstParameterToken(fn) {
let source = Function.prototype.toString.call(fn);
source = source.replaceAll(MULTI_LINE_COMMENT_REGEX, "").replaceAll(SINGLE_LINE_COMMENT_REGEX, "").trim();
const arrowMatch = source.match(
/^(?:async\s*)?(?:\(([^)]*)\)|([^=()]+))\s*=>/
);
if (arrowMatch) {
const params = (arrowMatch[1] ?? arrowMatch[2] ?? "").split(",");
const first = params[0]?.trim();
if (first) {
return sanitizeParameterToken(first);
}
return null;
}
const functionMatch = source.match(/^[^(]*\(([^)]*)\)/);
if (functionMatch) {
const params = functionMatch[1]?.split(",");
const first = params?.[0]?.trim();
if (first) {
return sanitizeParameterToken(first);
}
}
return null;
}
function looksLikeTraceFactory(fn) {
if (hasFactoryMark(fn)) {
return true;
}
if (fn.length === 0) {
if (!isAsyncFunction(fn)) {
try {
const result = fn();
return typeof result === "function";
} catch {
return false;
}
}
return false;
}
const firstParam = getFirstParameterToken(fn);
if (!firstParam) {
return false;
}
const normalized = firstParam.toLowerCase();
if (FACTORY_NAME_HINTS.has(normalized) || normalized.startsWith("ctx") || normalized.startsWith("_ctx") || normalized.startsWith("trace") || normalized.endsWith("ctx") || // Match baseCtx, spanCtx, etc.
normalized.includes("context")) {
return true;
}
return false;
}
function isFactoryReturningFunction(fnWithCtx) {
if (isAsyncFunction(fnWithCtx)) {
return false;
}
try {
const result = fnWithCtx(createDummyCtx());
return typeof result === "function";
} catch {
return false;
}
}
function isTraceFactoryFunction(fn) {
if (typeof fn !== "function") {
return false;
}
if (hasFactoryMark(fn)) {
return true;
}
if (looksLikeTraceFactory(fn)) {
markAsTraceFactory(fn);
return true;
}
return false;
}
function ensureTraceFactory(fnOrFactory) {
if (isTraceFactoryFunction(fnOrFactory)) {
return fnOrFactory;
}
const plainFn = fnOrFactory;
const factory = (ctx2) => {
return plainFn;
};
markAsTraceFactory(factory);
return factory;
}
function wrapFactoryWithTracing(fnOrFactory, options, variableName) {
const factory = ensureTraceFactory(fnOrFactory);
const sampleFn = factory(createDummyCtx());
const innerFunctionName = inferFunctionName(
sampleFn
);
const callStackVariableName = innerFunctionName ? void 0 : inferVariableNameFromCallStack();
const factoryName = inferFunctionName(factory);
const effectiveVariableName = variableName || innerFunctionName || callStackVariableName || factoryName;
const useAsyncWrapper = isAsyncFunction(sampleFn);
if (useAsyncWrapper) {
return wrapWithTracing(
factory,
options,
effectiveVariableName
);
}
return wrapWithTracingSync(
factory,
options,
effectiveVariableName
);
}
var MAX_ERROR_MESSAGE_LENGTH = 500;
function createDummyCtx() {
return {
traceId: "",
spanId: "",
correlationId: "",
setAttribute: () => {
},
setAttributes: () => {
},
setStatus: () => {
},
recordException: () => {
},
addEvent: () => {
},
addLink: () => {
},
addLinks: () => {
},
updateName: () => {
},
isRecording: () => false,
getBaggage: () => {
},
setBaggage: () => "",
deleteBaggage: () => {
},
getAllBaggage: () => /* @__PURE__ */ new Map()
};
}
function isAsyncFunction(fn) {
return typeof fn === "function" && fn.constructor?.name === "AsyncFunction";
}
var INSTRUMENTED_SYMBOL = /* @__PURE__ */ Symbol.for("autotel.functional.instrumented");
function hasInstrumentationFlag(value) {
return (typeof value === "function" || typeof value === "object") && value !== null && Boolean(value[INSTRUMENTED_SYMBOL]);
}
function truncateErrorMessage(message) {
if (message.length <= MAX_ERROR_MESSAGE_LENGTH) {
return message;
}
return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;
}
function inferFunctionName(fn) {
const displayName = fn.displayName;
if (displayName) {
return displayName;
}
if (fn.name && fn.name !== "anonymous" && fn.name !== "") {
return fn.name;
}
const source = Function.prototype.toString.call(fn);
const match = source.match(/function\s+([^(\s]+)/);
if (match && match[1] && match[1] !== "anonymous") {
return match[1];
}
return void 0;
}
function getSpanName(options, fn, variableName) {
if (options.name) {
return options.name;
}
let fnName = variableName || inferFunctionName(fn);
fnName = fnName || "anonymous";
if (options.serviceName) {
return `${options.serviceName}.${fnName}`;
}
if (fnName && fnName !== "anonymous") {
return fnName;
}
return "unknown";
}
function shouldSkip(key, fn, skip) {
if (key.startsWith("_")) {
return true;
}
if (!skip || skip.length === 0) {
return false;
}
for (const rule of skip) {
if (typeof rule === "string" && key === rule) {
return true;
} else if (rule instanceof RegExp && rule.test(key)) {
return true;
} else if (typeof rule === "function" && rule(key, fn)) {
return true;
}
}
return false;
}
function getCtxValue() {
const activeSpan = api.trace.getActiveSpan();
if (!activeSpan) return null;
return chunkKKGM42RQ_cjs.createTraceContext(activeSpan);
}
var ctx = new Proxy(
{},
{
get(_target, prop) {
const ctxValue = getCtxValue();
if (!ctxValue) {
return;
}
return ctxValue[prop];
},
has(_target, prop) {
const ctxValue = getCtxValue();
if (!ctxValue) {
return false;
}
return prop in ctxValue;
},
ownKeys() {
const ctxValue = getCtxValue();
if (!ctxValue) {
return [];
}
return Object.keys(ctxValue);
},
getOwnPropertyDescriptor(_target, prop) {
const ctxValue = getCtxValue();
if (!ctxValue) {
return;
}
return Object.getOwnPropertyDescriptor(ctxValue, prop);
}
}
);
function wrapWithTracing(fnFactory, options, variableName) {
if (hasInstrumentationFlag(fnFactory)) ;
const config = chunkESLWRGAG_cjs.getConfig();
const tracer = config.tracer;
const meter = config.meter;
const sampler = options.sampler || new chunkVH77IPJN_cjs.AlwaysSampler();
const tempFn = fnFactory(createDummyCtx());
const spanName = getSpanName(options, tempFn, variableName);
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
description: `Call count for ${spanName}`,
unit: "1"
}) : void 0;
const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
description: `Duration for ${spanName}`,
unit: "ms"
}) : void 0;
const wrappedFunction = async function wrappedFunction2(...args) {
const samplingContext = {
operationName: spanName,
args,
metadata: {}
};
const shouldSample = sampler.shouldSample(samplingContext);
const needsTailSampling = "needsTailSampling" in sampler && typeof sampler.needsTailSampling === "function" ? sampler.needsTailSampling() : false;
if (!shouldSample && !needsTailSampling) {
const fn = fnFactory(createDummyCtx());
return await fn.call(this, ...args);
}
const startTime = performance.now();
const isRootSpan = options.startNewRoot || api.trace.getActiveSpan() === void 0;
const shouldAutoFlush = options.flushOnRootSpanEnd ?? chunkBPO2PQ3T_cjs.getConfig()?.flushOnRootSpanEnd ?? true;
const shouldAutoFlushSpans = chunkBPO2PQ3T_cjs.getConfig()?.forceFlushOnShutdown ?? false;
const flushIfNeeded = async () => {
if (!shouldAutoFlush || !isRootSpan) return;
try {
const queue = chunkKKGM42RQ_cjs.getEventQueue();
if (queue && queue.size() > 0) {
await queue.flush();
}
if (shouldAutoFlushSpans) {
const sdk = chunkBPO2PQ3T_cjs.getSdk();
if (sdk) {
try {
const sdkAny = sdk;
if (typeof sdkAny.getTracerProvider === "function") {
const tracerProvider = sdkAny.getTracerProvider();
if (tracerProvider && typeof tracerProvider.forceFlush === "function") {
await tracerProvider.forceFlush();
}
}
} catch {
}
}
}
} catch (error) {
const initConfig = chunkBPO2PQ3T_cjs.getConfig();
const logger = initConfig?.logger;
if (logger?.error) {
logger.error(
{
err: error instanceof Error ? error : void 0
},
`[autotel] Auto-flush failed${error instanceof Error ? "" : `: ${String(error)}`}`
);
}
}
};
const spanOptions = {};
if (options.startNewRoot) {
spanOptions.root = true;
}
if (options.spanKind !== void 0) {
spanOptions.kind = options.spanKind;
}
const parentContext = chunkKKGM42RQ_cjs.getActiveContextWithBaggage();
return tracer.startActiveSpan(
spanName,
spanOptions,
parentContext,
async (span2) => {
return chunkVQTCQKHQ_cjs.runInOperationContext(spanName, async () => {
let shouldKeepSpan = true;
chunkNCSMD3TK_cjs.setSpanName(span2, spanName);
const initialContext = api.context.active();
const contextStorage = chunkKKGM42RQ_cjs.getContextStorage();
if (!contextStorage.getStore()) {
chunkKKGM42RQ_cjs.enterOrRun(contextStorage, initialContext);
}
const ctxValue = chunkKKGM42RQ_cjs.createTraceContext(span2);
const fn = fnFactory(ctxValue);
const argsAttributes = options.attributesFromArgs ? options.attributesFromArgs(args) : {};
const handleTailSampling = (success, duration, error) => {
if (needsTailSampling && "shouldKeepTrace" in sampler && typeof sampler.shouldKeepTrace === "function") {
shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
success,
duration,
error
});
span2.setAttribute(chunkVH77IPJN_cjs.AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
span2.setAttribute(chunkVH77IPJN_cjs.AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
}
};
const onSuccess = async (result) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "success"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "success"
});
const resultAttributes = options.attributesFromResult ? options.attributesFromResult(result) : {};
span2.setStatus({ code: api.SpanStatusCode.OK });
span2.setAttributes({
...argsAttributes,
...resultAttributes,
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": true
});
handleTailSampling(true, duration);
span2.end();
await flushIfNeeded();
return result;
};
const onError = async (error) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "error"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "error"
});
const errorMessage = error instanceof Error ? error.message : "Unknown error";
const truncatedMessage = truncateErrorMessage(errorMessage);
span2.setStatus({
code: api.SpanStatusCode.ERROR,
message: truncatedMessage
});
span2.setAttributes({
...argsAttributes,
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": false,
error: true,
"exception.type": error instanceof Error ? error.constructor.name : "Error",
"exception.message": truncatedMessage
});
if (error instanceof Error && error.stack) {
span2.setAttribute(
"exception.stack",
error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH)
);
}
span2.recordException(
error instanceof Error ? error : new Error(String(error))
);
handleTailSampling(false, duration, error);
span2.end();
await flushIfNeeded();
throw error;
};
try {
callCounter?.add(1, {
operation: spanName,
status: "started"
});
const executeWithContext = async () => {
const currentContext = chunkKKGM42RQ_cjs.getActiveContextWithBaggage();
return api.context.with(currentContext, async () => {
return fn.call(this, ...args);
});
};
const result = await executeWithContext();
return await onSuccess(result);
} catch (error) {
await onError(error);
throw error;
}
});
}
);
};
wrappedFunction[INSTRUMENTED_SYMBOL] = true;
Object.defineProperty(wrappedFunction, "name", {
value: tempFn.name || "trace",
configurable: true
});
return wrappedFunction;
}
function wrapWithTracingSync(fnFactory, options, variableName) {
if (hasInstrumentationFlag(fnFactory)) ;
const config = chunkESLWRGAG_cjs.getConfig();
const tracer = config.tracer;
const meter = config.meter;
const sampler = options.sampler || new chunkVH77IPJN_cjs.AlwaysSampler();
const tempFn = fnFactory(createDummyCtx());
const spanName = getSpanName(options, tempFn, variableName);
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
description: `Call count for ${spanName}`,
unit: "1"
}) : void 0;
const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
description: `Duration for ${spanName}`,
unit: "ms"
}) : void 0;
function wrappedFunction(...args) {
const samplingContext = {
operationName: spanName,
args,
metadata: {}
};
const shouldSample = sampler.shouldSample(samplingContext);
const needsTailSampling = "needsTailSampling" in sampler && typeof sampler.needsTailSampling === "function" ? sampler.needsTailSampling() : false;
if (!shouldSample && !needsTailSampling) {
const fn = fnFactory(createDummyCtx());
return fn.call(this, ...args);
}
const startTime = performance.now();
const isRootSpan = options.startNewRoot || api.trace.getActiveSpan() === void 0;
const shouldAutoFlush = options.flushOnRootSpanEnd ?? chunkBPO2PQ3T_cjs.getConfig()?.flushOnRootSpanEnd ?? true;
const shouldAutoFlushSpans = chunkBPO2PQ3T_cjs.getConfig()?.forceFlushOnShutdown ?? false;
const flushIfNeeded = () => {
if (!shouldAutoFlush || !isRootSpan) return;
const queue = chunkKKGM42RQ_cjs.getEventQueue();
if (queue && queue.size() > 0) {
void queue.flush().catch((error) => {
const initConfig = chunkBPO2PQ3T_cjs.getConfig();
const logger = initConfig?.logger;
if (logger?.error) {
logger.error(
{
err: error instanceof Error ? error : void 0
},
`[autotel] Auto-flush failed${error instanceof Error ? "" : `: ${String(error)}`}`
);
}
});
}
if (shouldAutoFlushSpans) {
const sdk = chunkBPO2PQ3T_cjs.getSdk();
if (sdk) {
try {
const sdkAny = sdk;
if (typeof sdkAny.getTracerProvider === "function") {
const tracerProvider = sdkAny.getTracerProvider();
if (tracerProvider && typeof tracerProvider.forceFlush === "function") {
void tracerProvider.forceFlush().catch((error) => {
const initConfig = chunkBPO2PQ3T_cjs.getConfig();
const logger = initConfig?.logger;
if (logger?.error) {
logger.error(
{
err: error instanceof Error ? error : void 0
},
`[autotel] Span flush failed${error instanceof Error ? "" : `: ${String(error)}`}`
);
}
});
}
}
} catch {
}
}
}
};
const spanOptions = {};
if (options.startNewRoot) {
spanOptions.root = true;
}
if (options.spanKind !== void 0) {
spanOptions.kind = options.spanKind;
}
const parentContext = chunkKKGM42RQ_cjs.getActiveContextWithBaggage();
return tracer.startActiveSpan(
spanName,
spanOptions,
parentContext,
(span2) => {
return chunkVQTCQKHQ_cjs.runInOperationContext(spanName, () => {
let shouldKeepSpan = true;
chunkNCSMD3TK_cjs.setSpanName(span2, spanName);
const ctxValue = chunkKKGM42RQ_cjs.createTraceContext(span2);
const fn = fnFactory(ctxValue);
const argsAttributes = options.attributesFromArgs ? options.attributesFromArgs(args) : {};
const handleTailSampling = (success, duration, error) => {
if (needsTailSampling && "shouldKeepTrace" in sampler && typeof sampler.shouldKeepTrace === "function") {
shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
success,
duration,
error
});
span2.setAttribute(chunkVH77IPJN_cjs.AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
span2.setAttribute(chunkVH77IPJN_cjs.AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
}
};
const onSuccess = (result) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "success"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "success"
});
const resultAttributes = options.attributesFromResult ? options.attributesFromResult(result) : {};
span2.setStatus({ code: api.SpanStatusCode.OK });
span2.setAttributes({
...argsAttributes,
...resultAttributes,
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": true
});
handleTailSampling(true, duration);
span2.end();
void flushIfNeeded();
return result;
};
const onError = (error) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "error"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "error"
});
const errorMessage = error instanceof Error ? error.message : "Unknown error";
const truncatedMessage = truncateErrorMessage(errorMessage);
span2.setStatus({
code: api.SpanStatusCode.ERROR,
message: truncatedMessage
});
span2.setAttributes({
...argsAttributes,
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": false,
error: true,
"exception.type": error instanceof Error ? error.constructor.name : "Error",
"exception.message": truncatedMessage
});
span2.recordException(
error instanceof Error ? error : new Error(String(error))
);
handleTailSampling(false, duration, error);
span2.end();
void flushIfNeeded();
throw error;
};
try {
callCounter?.add(1, {
operation: spanName,
status: "started"
});
const result = fn.call(this, ...args);
if (result instanceof Promise) {
return result.then(onSuccess, onError);
}
return onSuccess(result);
} catch (error) {
return onError(error);
}
});
}
);
}
wrappedFunction[INSTRUMENTED_SYMBOL] = true;
Object.defineProperty(wrappedFunction, "name", {
value: tempFn.name || "trace",
configurable: true
});
return wrappedFunction;
}
function executeImmediately(fn, options) {
const config = chunkESLWRGAG_cjs.getConfig();
const tracer = config.tracer;
const meter = config.meter;
const sampler = options.sampler || new chunkVH77IPJN_cjs.AlwaysSampler();
const spanName = options.name || "anonymous";
const samplingContext = {
operationName: spanName,
args: [],
metadata: {}
};
const shouldSample = sampler.shouldSample(samplingContext);
const needsTailSampling = "needsTailSampling" in sampler && typeof sampler.needsTailSampling === "function" ? sampler.needsTailSampling() : false;
if (!shouldSample && !needsTailSampling) {
return fn(createDummyCtx());
}
const startTime = performance.now();
const isRootSpan = options.startNewRoot || api.trace.getActiveSpan() === void 0;
const shouldAutoFlush = options.flushOnRootSpanEnd ?? chunkBPO2PQ3T_cjs.getConfig()?.flushOnRootSpanEnd ?? true;
const shouldAutoFlushSpans = chunkBPO2PQ3T_cjs.getConfig()?.forceFlushOnShutdown ?? false;
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
description: `Call count for ${spanName}`,
unit: "1"
}) : void 0;
const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
description: `Duration for ${spanName}`,
unit: "ms"
}) : void 0;
const flushIfNeeded = async () => {
if (!shouldAutoFlush || !isRootSpan) return;
try {
const queue = chunkKKGM42RQ_cjs.getEventQueue();
if (queue && queue.size() > 0) {
await queue.flush();
}
if (shouldAutoFlushSpans) {
const sdk = chunkBPO2PQ3T_cjs.getSdk();
if (sdk) {
try {
const sdkAny = sdk;
if (typeof sdkAny.getTracerProvider === "function") {
const tracerProvider = sdkAny.getTracerProvider();
if (tracerProvider && typeof tracerProvider.forceFlush === "function") {
await tracerProvider.forceFlush();
}
}
} catch {
}
}
}
} catch (error) {
const initConfig = chunkBPO2PQ3T_cjs.getConfig();
const logger = initConfig?.logger;
if (logger?.error) {
logger.error(
{
err: error instanceof Error ? error : void 0
},
`[autotel] Auto-flush failed${error instanceof Error ? "" : `: ${String(error)}`}`
);
}
}
};
const spanOptions = {};
if (options.startNewRoot) {
spanOptions.root = true;
}
if (options.spanKind !== void 0) {
spanOptions.kind = options.spanKind;
}
const parentContext = chunkKKGM42RQ_cjs.getActiveContextWithBaggage();
return tracer.startActiveSpan(
spanName,
spanOptions,
parentContext,
(span2) => {
return chunkVQTCQKHQ_cjs.runInOperationContext(spanName, () => {
let shouldKeepSpan = true;
chunkNCSMD3TK_cjs.setSpanName(span2, spanName);
const ctxValue = chunkKKGM42RQ_cjs.createTraceContext(span2);
const handleTailSampling = (success, duration, error) => {
if (needsTailSampling && "shouldKeepTrace" in sampler && typeof sampler.shouldKeepTrace === "function") {
shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
success,
duration,
error
});
span2.setAttribute(chunkVH77IPJN_cjs.AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
span2.setAttribute(chunkVH77IPJN_cjs.AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
}
};
const onSuccessSync = (result) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "success"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "success"
});
span2.setStatus({ code: api.SpanStatusCode.OK });
span2.setAttributes({
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": true
});
handleTailSampling(true, duration);
span2.end();
void flushIfNeeded();
return result;
};
const onErrorSync = (error) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "error"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "error"
});
const errorMessage = error instanceof Error ? error.message : "Unknown error";
const truncatedMessage = truncateErrorMessage(errorMessage);
span2.setStatus({
code: api.SpanStatusCode.ERROR,
message: truncatedMessage
});
span2.setAttributes({
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": false,
error: true,
"exception.type": error instanceof Error ? error.constructor.name : "Error",
"exception.message": truncatedMessage
});
if (error instanceof Error && error.stack) {
span2.setAttribute(
"exception.stack",
error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH)
);
}
span2.recordException(
error instanceof Error ? error : new Error(String(error))
);
handleTailSampling(false, duration, error);
span2.end();
void flushIfNeeded();
throw error;
};
const onSuccessAsync = async (result) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "success"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "success"
});
span2.setStatus({ code: api.SpanStatusCode.OK });
span2.setAttributes({
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": true
});
handleTailSampling(true, duration);
span2.end();
await flushIfNeeded();
return result;
};
const onErrorAsync = async (error) => {
const duration = performance.now() - startTime;
callCounter?.add(1, {
operation: spanName,
status: "error"
});
durationHistogram?.record(duration, {
operation: spanName,
status: "error"
});
const errorMessage = error instanceof Error ? error.message : "Unknown error";
const truncatedMessage = truncateErrorMessage(errorMessage);
span2.setStatus({
code: api.SpanStatusCode.ERROR,
message: truncatedMessage
});
span2.setAttributes({
"operation.name": spanName,
"code.function": spanName,
"operation.duration": duration,
"operation.success": false,
error: true,
"exception.type": error instanceof Error ? error.constructor.name : "Error",
"exception.message": truncatedMessage
});
if (error instanceof Error && error.stack) {
span2.setAttribute(
"exception.stack",
error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH)
);
}
span2.recordException(
error instanceof Error ? error : new Error(String(error))
);
handleTailSampling(false, duration, error);
span2.end();
await flushIfNeeded();
throw error;
};
try {
callCounter?.add(1, {
operation: spanName,
status: "started"
});
const result = fn(ctxValue);
if (result instanceof Promise) {
return result.then(onSuccessAsync, onErrorAsync);
}
return onSuccessSync(result);
} catch (error) {
return onErrorSync(error);
}
});
}
);
}
function trace(fnOrNameOrOptions, maybeFn) {
if (typeof fnOrNameOrOptions === "function") {
if (looksLikeTraceFactory(fnOrNameOrOptions) && !isFactoryReturningFunction(
fnOrNameOrOptions
)) {
return executeImmediately(
fnOrNameOrOptions,
{}
);
}
return wrapFactoryWithTracing(
fnOrNameOrOptions,
{}
);
}
if (typeof fnOrNameOrOptions === "string") {
if (!maybeFn) {
throw new Error("trace(name, fn): fn is required");
}
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) {
return executeImmediately(
maybeFn,
{ name: fnOrNameOrOptions }
);
}
return wrapFactoryWithTracing(
maybeFn,
{ name: fnOrNameOrOptions }
);
}
if (!maybeFn) {
throw new Error("trace(options, fn): fn is required");
}
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) {
return executeImmediately(
maybeFn,
fnOrNameOrOptions
);
}
return wrapFactoryWithTracing(
maybeFn,
fnOrNameOrOptions
);
}
function withTracing(options = {}) {
return (fnFactory) => wrapFactoryWithTracing(fnFactory, options);
}
function instrument(options) {
const { functions, ...tracingOptions } = options;
const instrumented = {};
for (const key of Object.keys(functions)) {
const typedKey = key;
const fn = functions[typedKey];
if (!fn || typeof fn !== "function") {
instrumented[typedKey] = fn;
continue;
}
if (shouldSkip(key, fn, tracingOptions.skip)) {
instrumented[typedKey] = fn;
continue;
}
const fnOptions = {
...tracingOptions,
...tracingOptions.overrides?.[key],
// If no explicit name, use key as function name
name: tracingOptions.overrides?.[key]?.name
};
const boundFn = fn.bind(functions);
const fnFactory = (ctx2) => {
return boundFn;
};
instrumented[typedKey] = wrapFactoryWithTracing(
fnFactory,
fnOptions,
key
);
}
return instrumented;
}
function span(nameOrOptions, fn) {
const options = typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions;
const config = chunkESLWRGAG_cjs.getConfig();
const tracer = config.tracer;
const { name, attributes } = options;
const executeSpan = (span2) => {
return chunkVQTCQKHQ_cjs.runInOperationContext(name, () => {
try {
if (attributes) {
for (const [key, value] of Object.entries(attributes)) {
span2.setAttribute(key, value);
}
}
const result2 = fn(span2);
if (result2 instanceof Promise) {
return result2.then((resolved) => {
span2.setStatus({ code: api.SpanStatusCode.OK });
span2.end();
return resolved;
}).catch((error) => {
const errorMessage = error instanceof Error ? error.message.slice(0, MAX_ERROR_MESSAGE_LENGTH) : String(error).slice(0, MAX_ERROR_MESSAGE_LENGTH);
span2.setAttribute("error.message", errorMessage);
span2.setStatus({
code: api.SpanStatusCode.ERROR,
message: errorMessage
});
span2.recordException(
error instanceof Error ? error : new Error(String(error))
);
span2.end();
throw error;
});
} else {
span2.setStatus({ code: api.SpanStatusCode.OK });
span2.end();
return result2;
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message.slice(0, MAX_ERROR_MESSAGE_LENGTH) : String(error).slice(0, MAX_ERROR_MESSAGE_LENGTH);
span2.setAttribute("error.message", errorMessage);
span2.setStatus({
code: api.SpanStatusCode.ERROR,
message: errorMessage
});
span2.recordException(
error instanceof Error ? error : new Error(String(error))
);
span2.end();
throw error;
}
});
};
const parentContext = chunkKKGM42RQ_cjs.getActiveContextWithBaggage();
const result = tracer.startActiveSpan(name, {}, parentContext, executeSpan);
if (result instanceof Promise) {
return result;
}
return result;
}
async function withNewContext(options) {
const { fn } = options;
const config = chunkESLWRGAG_cjs.getConfig();
const tracer = config.tracer;
return tracer.startActiveSpan("root", { root: true }, async (span2) => {
try {
const result = await fn();
span2.setStatus({ code: api.SpanStatusCode.OK });
return result;
} catch (error) {
span2.recordException(
error instanceof Error ? error : new Error(String(error))
);
span2.setStatus({ code: api.SpanStatusCode.ERROR });
throw error;
} finally {
span2.end();
}
});
}
function withBaggage(options) {
const { baggage: baggageEntries, fn } = options;
const currentContext = api.context.active();
let updatedBaggage = api.propagation.getBaggage(currentContext) ?? api.propagation.createBaggage();
for (const [key, value] of Object.entries(baggageEntries)) {
updatedBaggage = updatedBaggage.setEntry(key, { value });
}
const newContext = api.propagation.setBaggage(currentContext, updatedBaggage);
const ctxStorage = chunkKKGM42RQ_cjs.getContextStorage();
const previousStored = ctxStorage.getStore();
const baggageEnrichedStored = previousStored ? { value: api.propagation.setBaggage(previousStored.value, updatedBaggage) } : { value: newContext };
const result = previousStored ? ctxStorage.run(baggageEnrichedStored, () => api.context.with(newContext, fn)) : api.context.with(newContext, fn);
if (result instanceof Promise) {
return result.then(
(value) => {
if (previousStored) {
return ctxStorage.run(previousStored, () => value);
}
return value;
},
(error) => {
if (previousStored) {
return ctxStorage.run(previousStored, () => {
throw error;
});
}
throw error;
}
);
}
return result;
}
exports.ctx = ctx;
exports.instrument = instrument;
exports.span = span;
exports.trace = trace;
exports.withBaggage = withBaggage;
exports.withNewContext = withNewContext;
exports.withTracing = withTracing;
//# sourceMappingURL=chunk-TY4NXDYR.cjs.map
//# sourceMappingURL=chunk-TY4NXDYR.cjs.map