autotel
Version:
Write Once, Observe Anywhere
217 lines (214 loc) • 7.67 kB
JavaScript
;
var api = require('@opentelemetry/api');
var async_hooks = require('async_hooks');
// src/trace-context.ts
var contextStorage = new async_hooks.AsyncLocalStorage();
function getContextStorage() {
return contextStorage;
}
function getActiveContextWithBaggage() {
const stored = contextStorage.getStore()?.value;
return stored ?? api.context.active();
}
function enterOrRun(storage, value) {
const existingStore = storage.getStore();
if (existingStore) {
existingStore.value = value;
return;
}
const boxedValue = { value };
try {
storage.enterWith(boxedValue);
} catch {
storage.run(boxedValue, () => {
});
}
}
function updateActiveContext(newContext) {
enterOrRun(contextStorage, newContext);
const contextWithManager = api.context;
const manager = contextWithManager._getContextManager?.();
if (!manager) return;
const asyncLocal = manager._asyncLocalStorage ?? void 0;
if (asyncLocal?.enterWith) {
asyncLocal.enterWith(newContext);
return;
}
if (typeof manager.with === "function") {
manager.with(newContext, () => {
});
}
}
function createTraceContext(span) {
const spanContext = span.spanContext();
const existingStored = contextStorage.getStore()?.value;
if (!existingStored) {
const activeContext = api.context.active();
enterOrRun(contextStorage, activeContext);
}
const baggageHelpers = {
getBaggage(key) {
const activeCtx = api.context.active();
let baggage = api.propagation.getBaggage(activeCtx);
if (!baggage) {
const storedContext = contextStorage.getStore()?.value;
if (storedContext) {
baggage = api.propagation.getBaggage(storedContext);
}
}
return baggage?.getEntry(key)?.value;
},
setBaggage(key, value) {
const activeCtx = api.context.active();
const storedContext = contextStorage.getStore()?.value;
const currentContext = storedContext ?? activeCtx;
const baggage = api.propagation.getBaggage(currentContext) ?? api.propagation.createBaggage();
const updated = baggage.setEntry(key, { value });
const newContext = api.propagation.setBaggage(currentContext, updated);
updateActiveContext(newContext);
return value;
},
deleteBaggage(key) {
const activeCtx = api.context.active();
const storedContext = contextStorage.getStore()?.value;
const currentContext = storedContext ?? activeCtx;
const baggage = api.propagation.getBaggage(currentContext);
if (baggage) {
const updated = baggage.removeEntry(key);
const newContext = api.propagation.setBaggage(currentContext, updated);
updateActiveContext(newContext);
}
},
getAllBaggage() {
const activeCtx = api.context.active();
let baggage = api.propagation.getBaggage(activeCtx);
if (!baggage) {
const storedContext = contextStorage.getStore()?.value;
if (storedContext) {
baggage = api.propagation.getBaggage(storedContext);
}
}
if (!baggage) {
return /* @__PURE__ */ new Map();
}
const entries = /* @__PURE__ */ new Map();
for (const [key, entry] of baggage.getAllEntries()) {
entries.set(key, entry);
}
return entries;
},
// Typed baggage helpers (used by defineBaggageSchema)
getTypedBaggage: ((namespace) => {
const activeCtx = api.context.active();
let baggage = api.propagation.getBaggage(activeCtx);
if (!baggage) {
const storedContext = contextStorage.getStore()?.value;
if (storedContext) {
baggage = api.propagation.getBaggage(storedContext);
}
}
if (!baggage) return;
const prefix = namespace ? `${namespace}.` : "";
const result = {};
for (const [key, entry] of baggage.getAllEntries()) {
if (namespace && key.startsWith(prefix)) {
const fieldName = key.slice(prefix.length);
result[fieldName] = entry.value;
} else if (!namespace) {
result[key] = entry.value;
}
}
return Object.keys(result).length > 0 ? result : void 0;
}),
setTypedBaggage: ((namespace, value) => {
const activeCtx = api.context.active();
const storedContext = contextStorage.getStore()?.value;
const currentContext = storedContext ?? activeCtx;
let baggage = api.propagation.getBaggage(currentContext) ?? api.propagation.createBaggage();
const prefix = namespace ? `${namespace}.` : "";
for (const [key, val] of Object.entries(value)) {
if (val !== void 0) {
const baggageKey = `${prefix}${key}`;
baggage = baggage.setEntry(baggageKey, { value: String(val) });
}
}
const newContext = api.propagation.setBaggage(currentContext, baggage);
updateActiveContext(newContext);
})
};
return {
traceId: spanContext.traceId,
spanId: spanContext.spanId,
correlationId: spanContext.traceId.slice(0, 16),
setAttribute: span.setAttribute.bind(span),
setAttributes: span.setAttributes.bind(span),
setStatus: span.setStatus.bind(span),
recordException: span.recordException.bind(span),
addEvent: span.addEvent.bind(span),
addLink: span.addLink.bind(span),
addLinks: span.addLinks.bind(span),
updateName: span.updateName.bind(span),
isRecording: span.isRecording.bind(span),
...baggageHelpers
};
}
function defineBaggageSchema(namespace) {
return {
/**
* Get typed baggage from context
* @param ctx - Trace context
* @returns Partial baggage object or undefined if no baggage is set
*/
get: (ctx) => {
if (!ctx.getTypedBaggage) return void 0;
return ctx.getTypedBaggage(namespace);
},
/**
* Set typed baggage in context
*
* Note: For proper scoping across async boundaries, use the `with` method instead
*
* @param ctx - Trace context
* @param value - Partial baggage object to set
*/
set: (ctx, value) => {
if (!ctx.setTypedBaggage) return;
ctx.setTypedBaggage(namespace, value);
},
/**
* Run a function with typed baggage properly scoped
*
* This is the recommended way to set baggage as it ensures proper
* scoping across async boundaries.
*
* @param ctx - Trace context (can be omitted, will use active context)
* @param value - Partial baggage object to set
* @param fn - Function to execute with the baggage
*/
with: (ctxOrValue, valueOrFn, maybeFn) => {
const value = maybeFn ? valueOrFn : ctxOrValue;
const fn = maybeFn || valueOrFn;
const prefix = namespace ? `${namespace}.` : "";
const flatBaggage = {};
for (const [key, val] of Object.entries(value)) {
if (val !== void 0) {
flatBaggage[`${prefix}${key}`] = String(val);
}
}
const currentContext = api.context.active();
let baggage = api.propagation.getBaggage(currentContext) ?? api.propagation.createBaggage();
for (const [key, val] of Object.entries(flatBaggage)) {
baggage = baggage.setEntry(key, { value: val });
}
const newContext = api.propagation.setBaggage(currentContext, baggage);
return api.context.with(newContext, fn);
}
};
}
exports.createTraceContext = createTraceContext;
exports.defineBaggageSchema = defineBaggageSchema;
exports.enterOrRun = enterOrRun;
exports.getActiveContextWithBaggage = getActiveContextWithBaggage;
exports.getContextStorage = getContextStorage;
//# sourceMappingURL=chunk-HZ3FYBJG.cjs.map
//# sourceMappingURL=chunk-HZ3FYBJG.cjs.map