autotel
Version:
Write Once, Observe Anywhere
257 lines (255 loc) • 7.69 kB
JavaScript
import { trace } from './chunk-HPUGKUMZ.js';
import './chunk-B3ZHLLMP.js';
import './chunk-WD4RP6IV.js';
import './chunk-S4OFEXLA.js';
import './chunk-BBBWDIYQ.js';
import './chunk-W35FVJBC.js';
import './chunk-3SDILILG.js';
import './chunk-A4E5AQFK.js';
import './chunk-WGWSHJ2N.js';
import './chunk-GYR5K654.js';
import './chunk-TDNKIHKT.js';
import './chunk-6UQRVUN3.js';
import './chunk-3QXBFGKP.js';
import './chunk-33WTKH7X.js';
import './chunk-DPSA4QLA.js';
import './chunk-55ER2KD5.js';
import './chunk-J5QENANM.js';
import './chunk-HA2WBOGQ.js';
import './chunk-DGUM43GV.js';
import { SpanKind, trace as trace$1 } from '@opentelemetry/api';
var InMemoryTraceContextStore = class {
constructor(options = {}) {
this.options = options;
const cleanupMs = options.cleanupIntervalMs ?? 6e4;
if (cleanupMs > 0) {
this.cleanupInterval = setInterval(() => this.cleanup(), cleanupMs);
if (this.cleanupInterval.unref) {
this.cleanupInterval.unref();
}
}
}
options;
store = /* @__PURE__ */ new Map();
cleanupInterval = null;
async save(key, context) {
this.store.set(key, context);
}
async load(key) {
const context = this.store.get(key);
if (!context) {
return null;
}
if (context.ttlMs) {
const age = Date.now() - context.parkedAt;
if (age > context.ttlMs) {
this.store.delete(key);
return null;
}
}
return context;
}
async delete(key) {
this.store.delete(key);
}
/**
* Get number of stored contexts (for testing)
*/
get size() {
return this.store.size;
}
/**
* Clear all stored contexts (for testing)
*/
clear() {
this.store.clear();
}
/**
* Stop the cleanup interval
*/
destroy() {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
this.cleanupInterval = null;
}
}
cleanup() {
const now = Date.now();
for (const [key, context] of this.store.entries()) {
if (context.ttlMs) {
const age = now - context.parkedAt;
if (age > context.ttlMs) {
this.store.delete(key);
}
}
}
}
};
function createParkingLot(config) {
const {
store,
defaultTTLMs = 24 * 60 * 60 * 1e3,
// 24 hours
keyPrefix = "parkingLot:",
autoDeleteOnRetrieve = true,
onMiss
} = config;
function getCurrentSpanContext() {
const activeSpan = trace$1.getActiveSpan();
if (!activeSpan) {
return null;
}
return activeSpan.spanContext();
}
function prefixKey(key) {
return `${keyPrefix}${key}`;
}
const parkingLot = {
async park(correlationKey, metadata) {
const spanContext = getCurrentSpanContext();
const fullKey = prefixKey(correlationKey);
const storedContext = {
traceId: spanContext?.traceId ?? "",
spanId: spanContext?.spanId ?? "",
traceFlags: spanContext?.traceFlags ?? 0,
parkedAt: Date.now(),
ttlMs: defaultTTLMs,
metadata
};
await store.save(fullKey, storedContext);
const activeSpan = trace$1.getActiveSpan();
if (activeSpan) {
activeSpan.addEvent("trace_context_parked", {
"parking_lot.correlation_key": correlationKey,
"parking_lot.ttl_ms": defaultTTLMs,
...metadata && Object.fromEntries(
Object.entries(metadata).map(([k, v]) => [
`parking_lot.metadata.${k}`,
v
])
)
});
}
return correlationKey;
},
async retrieve(correlationKey) {
const fullKey = prefixKey(correlationKey);
const storedContext = await store.load(fullKey);
if (!storedContext) {
onMiss?.(correlationKey);
return null;
}
if (autoDeleteOnRetrieve) {
await store.delete(fullKey);
}
return storedContext;
},
traceCallback(callbackConfig) {
return (fnFactory) => {
return trace(
{
name: callbackConfig.name,
spanKind: SpanKind.SERVER
},
(baseCtx) => {
return async (...args) => {
const correlationKey = callbackConfig.correlationKeyFrom(args);
const parkedContext = await parkingLot.retrieve(correlationKey);
const elapsedMs = parkedContext ? Date.now() - parkedContext.parkedAt : null;
baseCtx.setAttribute(
"parking_lot.correlation_key",
correlationKey
);
if (parkedContext) {
baseCtx.setAttribute("parking_lot.elapsed_ms", elapsedMs);
baseCtx.setAttribute(
"parking_lot.original_trace_id",
parkedContext.traceId
);
baseCtx.setAttribute(
"parking_lot.original_span_id",
parkedContext.spanId
);
if (parkedContext.metadata) {
for (const [key, value] of Object.entries(
parkedContext.metadata
)) {
baseCtx.setAttribute(`parking_lot.metadata.${key}`, value);
}
}
const link = parkingLot.createLink(parkedContext);
baseCtx.addLinks([link]);
baseCtx.addEvent("parked_context_retrieved", {
"parking_lot.correlation_key": correlationKey,
"parking_lot.elapsed_ms": elapsedMs,
"parking_lot.original_trace_id": parkedContext.traceId
});
} else {
baseCtx.setAttribute("parking_lot.context_found", false);
if (callbackConfig.requireParkedContext) {
const error = new Error(
`Required parked context not found for key: ${correlationKey}`
);
baseCtx.recordException(error);
throw error;
}
}
if (callbackConfig.attributes) {
for (const [key, value] of Object.entries(
callbackConfig.attributes
)) {
baseCtx.setAttribute(key, value);
}
}
const callbackCtx = {
...baseCtx,
parkedContext,
elapsedMs,
correlationKey
};
const userFn = fnFactory(callbackCtx);
return userFn(...args);
};
}
);
};
},
createLink(storedContext) {
return {
context: {
traceId: storedContext.traceId,
spanId: storedContext.spanId,
traceFlags: storedContext.traceFlags,
isRemote: true
},
attributes: {
"link.type": "parking_lot",
"parking_lot.parked_at": storedContext.parkedAt,
...storedContext.metadata && {
"parking_lot.has_metadata": true
}
}
};
},
async exists(correlationKey) {
const fullKey = prefixKey(correlationKey);
const context = await store.load(fullKey);
return context !== null;
}
};
return parkingLot;
}
function createCorrelationKey(...parts) {
return parts.map(String).join(":");
}
function toSpanContext(storedContext) {
return {
traceId: storedContext.traceId,
spanId: storedContext.spanId,
traceFlags: storedContext.traceFlags,
isRemote: true
};
}
export { InMemoryTraceContextStore, createCorrelationKey, createParkingLot, toSpanContext };
//# sourceMappingURL=webhook.js.map
//# sourceMappingURL=webhook.js.map