autotel-cloudflare
Version:
The #1 OpenTelemetry package for Cloudflare Workers - complete bindings coverage, native CF OTel integration, advanced sampling
1,030 lines (1,027 loc) • 37.2 kB
JavaScript
import { wrap } from './chunk-O4IYKWPJ.js';
import { propagation, SpanKind, SpanStatusCode, context, trace } from '@opentelemetry/api';
import { createInitialiser, setConfig } from 'autotel-edge';
function getTracer() {
return trace.getTracer("autotel-cloudflare-actors");
}
function instrumentActorStorage(storage, actorInstance, actorClass) {
if (!storage || typeof storage !== "object") {
return storage;
}
const actorClassName = actorClass.name || "Actor";
const actorName = actorInstance.name || actorClassName;
const storageHandler = {
get(target, prop) {
const value = Reflect.get(target, prop);
if (prop === "exec" && typeof value === "function") {
return function instrumentedExec(query, ...params) {
const tracer = getTracer();
const spanName = `Actor ${actorName}: storage.exec`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"db.system": "sqlite",
"db.operation": "exec",
"db.statement": query,
"db.statement.params_count": params.length
}
},
(span) => {
try {
const result = value.call(target, query, ...params);
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 === "query" && typeof value === "function") {
return function instrumentedQuery(query, ...params) {
const tracer = getTracer();
const spanName = `Actor ${actorName}: storage.query`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"db.system": "sqlite",
"db.operation": "query",
"db.statement": query,
"db.statement.params_count": params.length
}
},
(span) => {
try {
const result = value.call(target, query, ...params);
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 === "get" && typeof value === "function") {
return async function instrumentedGet(key) {
const tracer = getTracer();
const spanName = `Actor ${actorName}: storage.get`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"db.system": "durable_object_storage",
"db.operation": "get",
"db.key": key
}
},
async (span) => {
try {
const result = await value.call(target, key);
span.setAttributes({
"db.result.found": result !== null && result !== void 0
});
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 === "put" && typeof value === "function") {
return async function instrumentedPut(key, val) {
const tracer = getTracer();
const spanName = `Actor ${actorName}: storage.put`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"db.system": "durable_object_storage",
"db.operation": "put",
"db.key": key,
"db.value_type": typeof val
}
},
async (span) => {
try {
await value.call(target, key, val);
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();
}
}
);
};
}
if (prop === "delete" && typeof value === "function") {
return async function instrumentedDelete(key) {
const tracer = getTracer();
const spanName = `Actor ${actorName}: storage.delete`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"db.system": "durable_object_storage",
"db.operation": "delete",
"db.key": key
}
},
async (span) => {
try {
const result = await value.call(target, key);
span.setAttributes({
"db.result.deleted": result
});
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(storage, storageHandler);
}
function getTracer2() {
return trace.getTracer("autotel-cloudflare-actors");
}
function instrumentActorAlarms(alarms, actorInstance, actorClass) {
if (!alarms || typeof alarms !== "object") {
return alarms;
}
const actorClassName = actorClass.name || "Actor";
const actorName = actorInstance.name || actorClassName;
const alarmsHandler = {
get(target, prop) {
const value = Reflect.get(target, prop);
if (prop === "set" && typeof value === "function") {
return async function instrumentedSet(...args) {
const tracer = getTracer2();
const spanName = `Actor ${actorName}: alarms.set`;
const alarmAttributes = {
"actor.name": actorName,
"actor.class": actorClassName,
"alarm.operation": "set"
};
if (args.length > 0) {
const firstArg = args[0];
if (typeof firstArg === "number") {
alarmAttributes["alarm.delay_ms"] = firstArg;
} else if (firstArg instanceof Date) {
alarmAttributes["alarm.scheduled_time"] = firstArg.toISOString();
} else if (typeof firstArg === "string") {
alarmAttributes["alarm.cron"] = firstArg;
}
}
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: alarmAttributes
},
async (span) => {
try {
const result = await value.apply(target, 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 === "setMultiple" && typeof value === "function") {
return async function instrumentedSetMultiple(alarmDefs) {
const tracer = getTracer2();
const spanName = `Actor ${actorName}: alarms.setMultiple`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"alarm.operation": "setMultiple",
"alarm.count": Array.isArray(alarmDefs) ? alarmDefs.length : 0
}
},
async (span) => {
try {
const result = await value.call(target, alarmDefs);
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 === "cancel" && typeof value === "function") {
return async function instrumentedCancel(alarmId) {
const tracer = getTracer2();
const spanName = `Actor ${actorName}: alarms.cancel`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"alarm.operation": "cancel",
"alarm.id": alarmId
}
},
async (span) => {
try {
const result = await value.call(target, alarmId);
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 === "cancelAll" && typeof value === "function") {
return async function instrumentedCancelAll() {
const tracer = getTracer2();
const spanName = `Actor ${actorName}: alarms.cancelAll`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"alarm.operation": "cancelAll"
}
},
async (span) => {
try {
const result = await value.call(target);
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(alarms, alarmsHandler);
}
function getTracer3() {
return trace.getTracer("autotel-cloudflare-actors");
}
function instrumentActorSockets(sockets, actorInstance, actorClass) {
if (!sockets || typeof sockets !== "object") {
return sockets;
}
const actorClassName = actorClass.name || "Actor";
const actorName = actorInstance.name || actorClassName;
const socketsHandler = {
get(target, prop) {
const value = Reflect.get(target, prop);
if (prop === "acceptWebSocket" && typeof value === "function") {
return function instrumentedAcceptWebSocket(request) {
const tracer = getTracer3();
const spanName = `Actor ${actorName}: sockets.acceptWebSocket`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.SERVER,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"websocket.operation": "accept",
"url.full": request.url
}
},
(span) => {
try {
const result = value.call(target, request);
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 === "broadcast" && typeof value === "function") {
return function instrumentedBroadcast(message) {
const tracer = getTracer3();
const spanName = `Actor ${actorName}: sockets.broadcast`;
tracer.startActiveSpan(
spanName,
{
kind: SpanKind.PRODUCER,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"websocket.operation": "broadcast",
"websocket.message.type": typeof message,
"websocket.message.size": typeof message === "string" ? message.length : message instanceof ArrayBuffer ? message.byteLength : 0
}
},
(span) => {
try {
value.call(target, message);
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();
}
}
);
};
}
if (prop === "send" && typeof value === "function") {
return function instrumentedSend(ws, message) {
const tracer = getTracer3();
const spanName = `Actor ${actorName}: sockets.send`;
tracer.startActiveSpan(
spanName,
{
kind: SpanKind.PRODUCER,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"websocket.operation": "send",
"websocket.message.type": typeof message,
"websocket.message.size": typeof message === "string" ? message.length : message instanceof ArrayBuffer ? message.byteLength : 0
}
},
(span) => {
try {
value.call(target, ws, message);
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();
}
}
);
};
}
if (prop === "getConnections" && typeof value === "function") {
return function instrumentedGetConnections() {
const tracer = getTracer3();
const spanName = `Actor ${actorName}: sockets.getConnections`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.CLIENT,
attributes: {
"actor.name": actorName,
"actor.class": actorClassName,
"websocket.operation": "getConnections"
}
},
(span) => {
try {
const result = value.call(target);
if (Array.isArray(result)) {
span.setAttribute("websocket.connections.count", result.length);
}
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(sockets, socketsHandler);
}
// src/actors/instrument-actor.ts
var coldStarts = /* @__PURE__ */ new WeakMap();
function isColdStart(actorClass) {
if (!coldStarts.has(actorClass)) {
coldStarts.set(actorClass, true);
return true;
}
return false;
}
function getTracer4() {
return trace.getTracer("autotel-cloudflare-actors");
}
function defaultSpanNameFormatter(actorName, actorClass, lifecycle) {
const displayName = actorName || actorClass;
return `Actor ${displayName}: ${lifecycle}`;
}
function createActorAttributes(actorInstance, actorClass, lifecycle) {
return {
"actor.name": actorInstance.name || "unknown",
"actor.class": actorClass.name || "Actor",
"actor.lifecycle": lifecycle,
"actor.coldstart": isColdStart(actorClass),
...actorInstance.identifier && { "actor.identifier": actorInstance.identifier }
};
}
function instrumentOnInit(originalMethod, actorInstance, actorClass, options) {
return async function instrumentedOnInit() {
const tracer = getTracer4();
const actorClassName = actorClass.name || "Actor";
const spanName = options.spanNameFormatter ? options.spanNameFormatter(actorInstance.name || "", "init") : defaultSpanNameFormatter(actorInstance.name || "", actorClassName, "init");
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.INTERNAL,
attributes: createActorAttributes(actorInstance, actorClass, "init")
},
async (span) => {
try {
await originalMethod.call(actorInstance);
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 instrumentOnRequest(originalMethod, actorInstance, actorClass, options) {
return async function instrumentedOnRequest(request) {
const tracer = getTracer4();
const parentContext = propagation.extract(context.active(), request.headers);
const url = new URL(request.url);
const actorClassName = actorClass.name || "Actor";
const spanName = options.spanNameFormatter ? options.spanNameFormatter(actorInstance.name || "", "request") : `Actor ${actorInstance.name || actorClassName}: ${request.method} ${url.pathname}`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.SERVER,
attributes: {
...createActorAttributes(actorInstance, actorClass, "request"),
"http.request.method": request.method,
"url.full": request.url,
"url.path": url.pathname,
"url.query": url.search
}
},
parentContext,
async (span) => {
try {
const response = await originalMethod.call(actorInstance, 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 instrumentOnAlarm(originalMethod, actorInstance, actorClass, options) {
return async function instrumentedOnAlarm(alarmInfo) {
const tracer = getTracer4();
const actorClassName = actorClass.name || "Actor";
const spanName = options.spanNameFormatter ? options.spanNameFormatter(actorInstance.name || "", "alarm") : defaultSpanNameFormatter(actorInstance.name || "", actorClassName, "alarm");
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.INTERNAL,
attributes: {
...createActorAttributes(actorInstance, actorClass, "alarm"),
"faas.trigger": "timer"
}
},
async (span) => {
try {
await originalMethod.call(actorInstance, alarmInfo);
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 instrumentOnPersist(originalMethod, actorInstance, actorClass, options) {
if (!options.capturePersistEvents) {
return originalMethod;
}
return function instrumentedOnPersist(key, value) {
const tracer = getTracer4();
const actorClassName = actorClass.name || "Actor";
const spanName = options.spanNameFormatter ? options.spanNameFormatter(actorInstance.name || "", "persist") : `Actor ${actorInstance.name || actorClassName}: persist ${key}`;
tracer.startActiveSpan(
spanName,
{
kind: SpanKind.INTERNAL,
attributes: {
...createActorAttributes(actorInstance, actorClass, "persist"),
"actor.persist.key": key,
"actor.persist.value_type": typeof value
}
},
(span) => {
try {
originalMethod.call(actorInstance, key, value);
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 instrumentWebSocketConnect(originalMethod, actorInstance, actorClass, options) {
return function instrumentedWebSocketConnect(ws, request) {
const tracer = getTracer4();
const actorClassName = actorClass.name || "Actor";
const spanName = options.spanNameFormatter ? options.spanNameFormatter(actorInstance.name || "", "websocket.connect") : defaultSpanNameFormatter(actorInstance.name || "", actorClassName, "websocket.connect");
tracer.startActiveSpan(
spanName,
{
kind: SpanKind.SERVER,
attributes: {
...createActorAttributes(actorInstance, actorClass, "websocket.connect"),
"url.full": request.url
}
},
(span) => {
try {
originalMethod.call(actorInstance, ws, request);
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 instrumentWebSocketMessage(originalMethod, actorInstance, actorClass, options) {
return function instrumentedWebSocketMessage(ws, message) {
const tracer = getTracer4();
const actorClassName = actorClass.name || "Actor";
const spanName = options.spanNameFormatter ? options.spanNameFormatter(actorInstance.name || "", "websocket.message") : defaultSpanNameFormatter(actorInstance.name || "", actorClassName, "websocket.message");
tracer.startActiveSpan(
spanName,
{
kind: SpanKind.SERVER,
attributes: {
...createActorAttributes(actorInstance, actorClass, "websocket.message"),
"websocket.message.type": typeof message,
"websocket.message.size": typeof message === "string" ? message.length : message instanceof ArrayBuffer ? message.byteLength : 0
}
},
(span) => {
try {
originalMethod.call(actorInstance, ws, message);
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 instrumentWebSocketDisconnect(originalMethod, actorInstance, actorClass, options) {
return function instrumentedWebSocketDisconnect(ws) {
const tracer = getTracer4();
const actorClassName = actorClass.name || "Actor";
const spanName = options.spanNameFormatter ? options.spanNameFormatter(actorInstance.name || "", "websocket.disconnect") : defaultSpanNameFormatter(actorInstance.name || "", actorClassName, "websocket.disconnect");
tracer.startActiveSpan(
spanName,
{
kind: SpanKind.SERVER,
attributes: createActorAttributes(actorInstance, actorClass, "websocket.disconnect")
},
(span) => {
try {
originalMethod.call(actorInstance, ws);
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 instrumentActorInstance(actorInstance, _state, _env, actorClass, options) {
const instanceHandler = {
get(target, prop) {
const value = Reflect.get(target, prop);
if (prop === "onInit" && typeof value === "function") {
return instrumentOnInit(value.bind(target), target, actorClass, options);
}
if (prop === "onRequest" && typeof value === "function") {
return instrumentOnRequest(value.bind(target), target, actorClass, options);
}
if (prop === "onAlarm" && typeof value === "function") {
return instrumentOnAlarm(value.bind(target), target, actorClass, options);
}
if (prop === "onPersist" && typeof value === "function") {
return instrumentOnPersist(value.bind(target), target, actorClass, options);
}
if (prop === "onWebSocketConnect" && typeof value === "function") {
return instrumentWebSocketConnect(value.bind(target), target, actorClass, options);
}
if (prop === "onWebSocketMessage" && typeof value === "function") {
return instrumentWebSocketMessage(value.bind(target), target, actorClass, options);
}
if (prop === "onWebSocketDisconnect" && typeof value === "function") {
return instrumentWebSocketDisconnect(value.bind(target), target, actorClass, options);
}
if (prop === "storage" && value && options.instrumentStorage !== false) {
return instrumentActorStorage(value, target, actorClass);
}
if (prop === "alarms" && value && options.instrumentAlarms !== false) {
return instrumentActorAlarms(value, target, actorClass);
}
if (prop === "sockets" && value && options.instrumentSockets !== false) {
return instrumentActorSockets(value, target, actorClass);
}
if (typeof value === "function") {
return value.bind(target);
}
return value;
}
};
return wrap(actorInstance, instanceHandler);
}
function instrumentActor(actorClass, config) {
const initialiser = createInitialiser(config);
const defaultOptions = {
instrumentStorage: true,
instrumentAlarms: true,
instrumentSockets: true,
capturePersistEvents: true
};
const classHandler = {
construct(target, [state, env]) {
const resolvedConfig = typeof config === "function" ? config(env, { id: state.id.toString(), name: state.id.name }) : config;
const actorOptions = resolvedConfig && typeof resolvedConfig === "object" && "actors" in resolvedConfig ? resolvedConfig.actors : void 0;
const options = {
...defaultOptions,
...actorOptions
};
const trigger = {
id: state.id.toString(),
name: state.id.name
};
const telemetryConfig = initialiser(env, trigger);
const context$1 = setConfig(telemetryConfig);
const actorInstance = context.with(context$1, () => {
return new target(state, env);
});
return instrumentActorInstance(actorInstance, state, env, actorClass, options);
}
};
return wrap(actorClass, classHandler);
}
function getTracer5() {
return trace.getTracer("autotel-cloudflare-actors");
}
function tracedHandler(actorClass, config) {
const initialiser = createInitialiser(config);
return {
async fetch(request, env, _ctx) {
const telemetryConfig = initialiser(env, { type: "http" });
const configContext = setConfig(telemetryConfig);
const parentContext = propagation.extract(configContext, request.headers);
const tracer = getTracer5();
const url = new URL(request.url);
const actorClassName = actorClass.name || "Actor";
let actorName;
try {
if (actorClass.nameFromRequest) {
actorName = await actorClass.nameFromRequest(request);
}
} catch {
actorName = void 0;
}
const spanName = `${actorClassName} handler: ${request.method} ${url.pathname}`;
return tracer.startActiveSpan(
spanName,
{
kind: SpanKind.SERVER,
attributes: {
"http.request.method": request.method,
"url.full": request.url,
"url.path": url.pathname,
"url.query": url.search,
"actor.class": actorClassName,
...actorName && { "actor.name": actorName },
"faas.trigger": "http"
}
},
parentContext,
async (span) => {
try {
const envObj = env;
const bindingName = Object.keys(envObj).find((key) => {
const binding = env.__DURABLE_OBJECT_BINDINGS;
return key === actorClassName || binding?.[key]?.class_name === actorClassName;
});
if (!bindingName) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: `No Durable Object binding found for ${actorClassName}`
});
return Response.json(
{
error: "Configuration Error",
message: `No Durable Object binding found for actor class ${actorClassName}`
},
{ status: 500, headers: { "Content-Type": "application/json" } }
);
}
const namespace = envObj[bindingName];
const idString = actorName || "default";
const locationHint = actorClass.configuration?.(request)?.locationHint;
const stub = namespace.getByName(idString, { locationHint });
if ("setName" in stub && typeof stub.setName === "function") {
stub.setName(idString);
}
const headers = new Headers(request.headers);
propagation.inject(context.active(), headers);
const tracedRequest = new Request(request.url, {
method: request.method,
headers,
body: request.body,
redirect: request.redirect
});
const response = await stub.fetch(tracedRequest);
span.setAttributes({
"http.response.status_code": response.status,
"actor.name": idString
});
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)
});
return Response.json(
{
error: "Internal Server Error",
message: error instanceof Error ? error.message : "Unknown error"
},
{ status: 500, headers: { "Content-Type": "application/json" } }
);
} finally {
span.end();
}
}
);
}
};
}
function wrapHandler(originalHandler, config) {
const initialiser = createInitialiser(config);
return {
async fetch(request, env, ctx) {
const telemetryConfig = initialiser(env, { type: "http" });
const configContext = setConfig(telemetryConfig);
const parentContext = propagation.extract(configContext, request.headers);
const tracer = getTracer5();
const url = new URL(request.url);
return tracer.startActiveSpan(
`Worker: ${request.method} ${url.pathname}`,
{
kind: SpanKind.SERVER,
attributes: {
"http.request.method": request.method,
"url.full": request.url,
"url.path": url.pathname,
"url.query": url.search,
"faas.trigger": "http"
}
},
parentContext,
async (span) => {
try {
const headers = new Headers(request.headers);
propagation.inject(context.active(), headers);
const tracedRequest = new Request(request.url, {
method: request.method,
headers,
body: request.body,
redirect: request.redirect
});
const response = await originalHandler.fetch(tracedRequest, env, ctx);
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();
}
}
);
}
};
}
export { instrumentActor, instrumentActorAlarms, instrumentActorSockets, instrumentActorStorage, tracedHandler, wrapHandler };
//# sourceMappingURL=actors.js.map
//# sourceMappingURL=actors.js.map