autotel-cloudflare
Version:
The #1 OpenTelemetry package for Cloudflare Workers - complete bindings coverage, native CF OTel integration, advanced sampling
333 lines (331 loc) • 11 kB
JavaScript
import { wrap } from './chunk-O4IYKWPJ.js';
import { context, trace, propagation, SpanKind, SpanStatusCode } from '@opentelemetry/api';
import { createInitialiser, setConfig } from 'autotel-edge';
var coldStarts = /* @__PURE__ */ new WeakMap();
function isColdStart(doClass) {
if (!coldStarts.has(doClass)) {
coldStarts.set(doClass, true);
return true;
}
return false;
}
function instrumentDOFetch(fetchFn, id, doClass) {
return async function instrumentedFetch(request) {
const tracer = trace.getTracer("autotel-edge");
const parentContext = propagation.extract(
context.active(),
request.headers
);
const url = new URL(request.url);
const spanName = `DO ${id.name || id.toString()}: ${request.method} ${url.pathname}`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.SERVER,
attributes: {
"http.request.method": request.method,
"url.full": request.url,
"do.id": id.toString(),
"do.id.name": id.name || "",
"faas.trigger": "http",
"faas.coldstart": isColdStart(doClass)
}
},
parentContext,
async (span) => {
try {
const response = await fetchFn.call(this, request);
span.setAttributes({
"http.response.status_code": response.status
});
if (response.ok) {
span.setStatus({ code: SpanStatusCode.OK });
} else {
span.setStatus({ code: SpanStatusCode.ERROR });
}
return response;
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : String(error)
});
throw error;
} finally {
span.end();
}
}
);
};
}
function instrumentDOAlarm(alarmFn, id, doClass) {
return async function instrumentedAlarm() {
const tracer = trace.getTracer("autotel-edge");
const spanName = `DO ${id.name || id.toString()}: alarm`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.INTERNAL,
attributes: {
"do.id": id.toString(),
"do.id.name": id.name || "",
"faas.trigger": "timer",
"faas.coldstart": isColdStart(doClass)
}
},
async (span) => {
try {
await alarmFn.call(this);
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : String(error)
});
throw error;
} finally {
span.end();
}
}
);
};
}
function instrumentDOInstance(doInstance, state, _env, doClass) {
const instanceHandler = {
get(target, prop) {
const value = Reflect.get(target, prop);
if (prop === "fetch" && typeof value === "function") {
return instrumentDOFetch(value.bind(target), state.id, doClass);
}
if (prop === "alarm" && typeof value === "function") {
return instrumentDOAlarm(value.bind(target), state.id, doClass);
}
if (typeof value === "function") {
return value.bind(target);
}
return value;
}
};
return wrap(doInstance, instanceHandler);
}
function instrumentDO(doClass, config) {
const initialiser = createInitialiser(config);
const classHandler = {
construct(target, [state, env]) {
const trigger = {
id: state.id.toString(),
name: state.id.name
};
const doConfig = initialiser(env, trigger);
const context$1 = setConfig(doConfig);
const doInstance = context.with(context$1, () => {
return new target(state, env);
});
return instrumentDOInstance(doInstance, state, env, doClass);
}
};
return wrap(doClass, classHandler);
}
var coldStarts2 = /* @__PURE__ */ new WeakMap();
function isColdStart2(workflowClass) {
if (!coldStarts2.has(workflowClass)) {
coldStarts2.set(workflowClass, true);
return true;
}
return false;
}
function instrumentWorkflowStep(step, workflowName) {
const stepHandler = {
get(target, prop) {
const value = Reflect.get(target, prop);
if (prop === "do" && typeof value === "function") {
return new Proxy(value, {
apply: (fnTarget, thisArg, args) => {
const [stepName] = args;
const tracer = trace.getTracer("autotel-edge");
return tracer.startActiveSpan(
`Workflow ${workflowName}: ${stepName}`,
{
kind: SpanKind.INTERNAL,
attributes: {
"workflow.step.name": stepName,
"workflow.name": workflowName
}
},
async (span) => {
try {
const result = await Reflect.apply(fnTarget, thisArg, args);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : String(error)
});
throw error;
} finally {
span.end();
}
}
);
}
});
}
if (prop === "sleep" && typeof value === "function") {
return new Proxy(value, {
apply: (fnTarget, thisArg, args) => {
const [sleepName, duration] = args;
const tracer = trace.getTracer("autotel-edge");
return tracer.startActiveSpan(
`Workflow ${workflowName}: sleep ${sleepName}`,
{
kind: SpanKind.INTERNAL,
attributes: {
"workflow.sleep.name": sleepName,
"workflow.sleep.duration": String(duration),
"workflow.name": workflowName
}
},
async (span) => {
try {
const result = await Reflect.apply(fnTarget, thisArg, args);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : String(error)
});
throw error;
} finally {
span.end();
}
}
);
}
});
}
if (prop === "sleepUntil" && typeof value === "function") {
return new Proxy(value, {
apply: (fnTarget, thisArg, args) => {
const [sleepName, timestamp] = args;
const tracer = trace.getTracer("autotel-edge");
const wakeAt = timestamp instanceof Date ? timestamp.toISOString() : new Date(timestamp).toISOString();
return tracer.startActiveSpan(
`Workflow ${workflowName}: sleepUntil ${sleepName}`,
{
kind: SpanKind.INTERNAL,
attributes: {
"workflow.sleep.name": sleepName,
"workflow.sleep.until": wakeAt,
"workflow.name": workflowName
}
},
async (span) => {
try {
const result = await Reflect.apply(fnTarget, thisArg, args);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : String(error)
});
throw error;
} finally {
span.end();
}
}
);
}
});
}
if (typeof value === "function") {
return value.bind(target);
}
return value;
}
};
return wrap(step, stepHandler);
}
function instrumentWorkflowRun(runFn, workflowName, workflowClass) {
return async function instrumentedRun(event, step) {
const tracer = trace.getTracer("autotel-edge");
const instrumentedStep = instrumentWorkflowStep(step, workflowName);
const spanName = `Workflow ${workflowName}: run`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.INTERNAL,
attributes: {
"workflow.name": workflowName,
"workflow.instance_id": event.instanceId,
"faas.trigger": "workflow",
"faas.coldstart": isColdStart2(workflowClass)
}
},
async (span) => {
try {
const result = await runFn.call(this, event, instrumentedStep);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : String(error)
});
throw error;
} finally {
span.end();
}
}
);
};
}
function instrumentWorkflowInstance(workflowInstance, workflowName, workflowClass) {
const instanceHandler = {
get(target, prop) {
const value = Reflect.get(target, prop);
if (prop === "run" && typeof value === "function") {
return instrumentWorkflowRun(
value.bind(target),
workflowName,
workflowClass
);
}
if (typeof value === "function") {
return value.bind(target);
}
return value;
}
};
return wrap(workflowInstance, instanceHandler);
}
function instrumentWorkflow(workflowClass, workflowName, config) {
const initialiser = createInitialiser(config);
const classHandler = {
construct(target, args) {
const env = args[args.length - 1] || {};
const trigger = { type: "workflow", name: workflowName };
const workflowConfig = initialiser(env, trigger);
const context$1 = setConfig(workflowConfig);
const workflowInstance = context.with(context$1, () => {
return new target(...args);
});
return instrumentWorkflowInstance(
workflowInstance,
workflowName,
workflowClass
);
}
};
return wrap(workflowClass, classHandler);
}
export { instrumentDO, instrumentWorkflow };
//# sourceMappingURL=chunk-MIDMNKDC.js.map
//# sourceMappingURL=chunk-MIDMNKDC.js.map