autotel
Version:
Write Once, Observe Anywhere
312 lines (309 loc) • 9.49 kB
JavaScript
;
var chunkUY3UYPBZ_cjs = require('./chunk-UY3UYPBZ.cjs');
require('./chunk-FU6R566Y.cjs');
var chunkESLWRGAG_cjs = require('./chunk-ESLWRGAG.cjs');
require('./chunk-YREV3LGG.cjs');
require('./chunk-JEQ2X3Z6.cjs');
var api = require('@opentelemetry/api');
function createTraceCollector() {
const spans = [];
const createMockSpan = (name, startTime) => {
const spanData = {
name,
startTime,
attributes: {},
status: { code: api.SpanStatusCode.OK }
};
const spanContextData = {
traceId: "1234567890abcdef1234567890abcdef",
// 128-bit trace ID (32 hex chars)
spanId: "1234567890abcdef",
// 64-bit span ID (16 hex chars)
traceFlags: 1,
isRemote: false
};
const mockSpan = {
spanContext: () => spanContextData,
setStatus(status) {
spanData.status = status;
return this;
},
setAttributes(attributes) {
spanData.attributes = { ...spanData.attributes, ...attributes };
return this;
},
setAttribute(key, value) {
spanData.attributes = spanData.attributes || {};
spanData.attributes[key] = value;
return this;
},
addEvent(name2, attributesOrStartTime, startTime2) {
return this;
},
addLink(link) {
return this;
},
addLinks(links) {
return this;
},
updateName(newName) {
spanData.name = newName;
return this;
},
isRecording() {
return true;
},
recordException(exception, time) {
},
end(endTimeArg) {
const endTime = performance.now();
spans.push({
name: spanData.name,
status: spanData.status,
attributes: spanData.attributes || {},
startTime: spanData.startTime,
endTime,
duration: endTime - spanData.startTime
});
}
};
return mockSpan;
};
const mockTracer = {
startSpan(name, options, ctx) {
const startTime = performance.now();
return createMockSpan(name, startTime);
},
startActiveSpan(name, optionsOrFn, contextOrFn, fn) {
const callback = (() => {
if (typeof optionsOrFn === "function") {
return optionsOrFn;
}
if (typeof contextOrFn === "function") {
return contextOrFn;
}
if (fn) {
return fn;
}
throw new Error("startActiveSpan requires a callback");
})();
const startTime = performance.now();
const mockSpan = createMockSpan(name, startTime);
const ctx = api.trace.setSpan(api.context.active(), mockSpan);
return api.context.with(ctx, () => callback(mockSpan));
}
};
chunkESLWRGAG_cjs.configure({ tracer: mockTracer });
return {
getSpans() {
return [...spans];
},
getSpansByName(name) {
return spans.filter((span) => span.name === name);
},
getSpansByAttributes(attributes) {
return spans.filter((span) => {
return Object.entries(attributes).every(
([key, value]) => span.attributes[key] === value
);
});
},
clear() {
spans.length = 0;
},
recordSpan(span) {
spans.push(span);
}
};
}
function assertTraceCreated(collector, operationName, options) {
const spans = collector.getSpansByName(operationName);
if (options?.minCount !== void 0 && spans.length < options.minCount) {
throw new Error(
`Expected at least ${options.minCount} traces for ${operationName}, got ${spans.length}`
);
}
if (options?.maxCount !== void 0 && spans.length > options.maxCount) {
throw new Error(
`Expected at most ${options.maxCount} traces for ${operationName}, got ${spans.length}`
);
}
if (spans.length === 0) {
throw new Error(`No traces found for operation: ${operationName}`);
}
if (options?.status !== void 0) {
const matchingSpans = spans.filter(
(span) => span.status.code === options.status
);
if (matchingSpans.length === 0) {
throw new Error(
`No traces with status ${options.status} found for ${operationName}`
);
}
}
if (options?.attributes) {
const matchingSpans = spans.filter((span) => {
return Object.entries(options.attributes).every(
([key, value]) => span.attributes[key] === value
);
});
if (matchingSpans.length === 0) {
throw new Error(
`No traces with attributes ${JSON.stringify(options.attributes)} found for ${operationName}`
);
}
}
}
function assertNoErrors(collector) {
const errorSpans = collector.getSpans().filter((span) => span.status.code === api.SpanStatusCode.ERROR);
if (errorSpans.length > 0) {
const errorSummary = errorSpans.map((span) => `${span.name}: ${span.status.message}`).join("\n");
throw new Error(`Found ${errorSpans.length} error spans:
${errorSummary}`);
}
}
function assertTraceSucceeded(collector, operationName) {
assertTraceCreated(collector, operationName, { status: api.SpanStatusCode.OK });
}
function assertTraceFailed(collector, operationName, errorMessage) {
const spans = collector.getSpansByName(operationName);
if (spans.length === 0) {
throw new Error(`No traces found for operation: ${operationName}`);
}
const errorSpans = spans.filter(
(span) => span.status.code === api.SpanStatusCode.ERROR
);
if (errorSpans.length === 0) {
throw new Error(`No error traces found for operation: ${operationName}`);
}
if (errorMessage) {
const matchingSpans = errorSpans.filter(
(span) => span.status.message === errorMessage
);
if (matchingSpans.length === 0) {
throw new Error(
`No error traces with message "${errorMessage}" found for ${operationName}`
);
}
}
}
function createMockLogger() {
const logs = [];
const createLogMethod = (level) => {
return (objOrMsg, msg) => {
if (typeof objOrMsg === "string") {
logs.push({
level,
message: objOrMsg,
extra: void 0
});
} else {
logs.push({
level,
message: msg || "",
extra: objOrMsg
});
}
};
};
return {
info: createLogMethod("info"),
warn: createLogMethod("warn"),
debug: createLogMethod("debug"),
error(objOrMsg, msg) {
if (typeof objOrMsg === "string") {
logs.push({
level: "error",
message: objOrMsg,
extra: void 0,
error: void 0
});
return;
}
const { err, ...rest } = objOrMsg;
logs.push({
level: "error",
message: msg || "",
error: err instanceof Error ? err : void 0,
extra: err !== void 0 && !(err instanceof Error) ? { err, ...rest } : rest
});
},
getLogs() {
return [...logs];
},
getLogsByLevel(level) {
return logs.filter((log) => log.level === level);
},
getLogsByMessage(message) {
return logs.filter((log) => log.message.includes(message));
},
clear() {
logs.length = 0;
}
};
}
function assertNoErrorsLogged(logger) {
const errorLogs = logger.getLogsByLevel("error");
if (errorLogs.length > 0) {
const errorSummary = errorLogs.map(
(log) => `${log.message}${log.error ? ": " + log.error.message : ""}`
).join("\n");
throw new Error(`Found ${errorLogs.length} error logs:
${errorSummary}`);
}
}
async function waitForTrace(collector, operationName, timeoutMs = 5e3) {
const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) {
const spans = collector.getSpansByName(operationName);
if (spans.length > 0) {
return;
}
await new Promise((resolve) => setTimeout(resolve, 10));
}
throw new Error(
`Timeout waiting for trace ${operationName} after ${timeoutMs}ms`
);
}
function getTraceDuration(collector, operationName) {
const spans = collector.getSpansByName(operationName);
if (spans.length === 0) {
return void 0;
}
return spans[0]?.duration;
}
function assertTraceDuration(collector, operationName, maxDurationMs) {
const duration = getTraceDuration(collector, operationName);
if (duration === void 0) {
throw new Error(`No trace found for operation: ${operationName}`);
}
if (duration > maxDurationMs) {
throw new Error(
`Operation ${operationName} took ${duration.toFixed(2)}ms, exceeding ${maxDurationMs}ms threshold`
);
}
}
Object.defineProperty(exports, "assertEventTracked", {
enumerable: true,
get: function () { return chunkUY3UYPBZ_cjs.assertEventTracked; }
});
Object.defineProperty(exports, "assertOutcomeTracked", {
enumerable: true,
get: function () { return chunkUY3UYPBZ_cjs.assertOutcomeTracked; }
});
Object.defineProperty(exports, "createEventCollector", {
enumerable: true,
get: function () { return chunkUY3UYPBZ_cjs.createEventCollector; }
});
exports.assertNoErrors = assertNoErrors;
exports.assertNoErrorsLogged = assertNoErrorsLogged;
exports.assertTraceCreated = assertTraceCreated;
exports.assertTraceDuration = assertTraceDuration;
exports.assertTraceFailed = assertTraceFailed;
exports.assertTraceSucceeded = assertTraceSucceeded;
exports.createMockLogger = createMockLogger;
exports.createTraceCollector = createTraceCollector;
exports.getTraceDuration = getTraceDuration;
exports.waitForTrace = waitForTrace;
//# sourceMappingURL=testing.cjs.map
//# sourceMappingURL=testing.cjs.map