autotel-cloudflare 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +432 -0
- package/dist/actors.d.ts +248 -0
- package/dist/actors.js +1030 -0
- package/dist/actors.js.map +1 -0
- package/dist/agents.d.ts +219 -0
- package/dist/agents.js +276 -0
- package/dist/agents.js.map +1 -0
- package/dist/bindings.d.ts +40 -0
- package/dist/bindings.js +4 -0
- package/dist/bindings.js.map +1 -0
- package/dist/chunk-JDPN3HND.js +520 -0
- package/dist/chunk-JDPN3HND.js.map +1 -0
- package/dist/chunk-QXFYTHQF.js +298 -0
- package/dist/chunk-QXFYTHQF.js.map +1 -0
- package/dist/chunk-SKKRPS5K.js +50 -0
- package/dist/chunk-SKKRPS5K.js.map +1 -0
- package/dist/events.d.ts +1 -0
- package/dist/events.js +3 -0
- package/dist/events.js.map +1 -0
- package/dist/handlers.d.ts +121 -0
- package/dist/handlers.js +4 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +144 -0
- package/dist/index.js +576 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +3 -0
- package/dist/logger.js.map +1 -0
- package/dist/sampling.d.ts +4 -0
- package/dist/sampling.js +3 -0
- package/dist/sampling.js.map +1 -0
- package/dist/testing.d.ts +1 -0
- package/dist/testing.js +3 -0
- package/dist/testing.js.map +1 -0
- package/package.json +107 -0
- package/src/actors/alarms.ts +225 -0
- package/src/actors/index.ts +36 -0
- package/src/actors/instrument-actor.test.ts +179 -0
- package/src/actors/instrument-actor.ts +574 -0
- package/src/actors/sockets.ts +217 -0
- package/src/actors/storage.ts +263 -0
- package/src/actors/traced-handler.ts +300 -0
- package/src/actors/types.ts +98 -0
- package/src/actors.ts +50 -0
- package/src/agents/index.ts +42 -0
- package/src/agents/otel-observability.test.ts +329 -0
- package/src/agents/otel-observability.ts +465 -0
- package/src/agents/types.ts +167 -0
- package/src/agents.ts +76 -0
- package/src/bindings/bindings.ts +621 -0
- package/src/bindings/common.ts +75 -0
- package/src/bindings/index.ts +12 -0
- package/src/bindings.ts +6 -0
- package/src/events.ts +6 -0
- package/src/global/cache.test.ts +292 -0
- package/src/global/cache.ts +164 -0
- package/src/global/fetch.test.ts +344 -0
- package/src/global/fetch.ts +134 -0
- package/src/global/index.ts +7 -0
- package/src/handlers/durable-objects.test.ts +524 -0
- package/src/handlers/durable-objects.ts +250 -0
- package/src/handlers/index.ts +6 -0
- package/src/handlers/workflows.ts +318 -0
- package/src/handlers.ts +6 -0
- package/src/index.ts +57 -0
- package/src/logger.ts +6 -0
- package/src/sampling.ts +6 -0
- package/src/testing.ts +6 -0
- package/src/wrappers/index.ts +8 -0
- package/src/wrappers/instrument.integration.test.ts +468 -0
- package/src/wrappers/instrument.ts +643 -0
- package/src/wrappers/wrap-do.ts +34 -0
- package/src/wrappers/wrap-module.ts +37 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { wrap } from './chunk-SKKRPS5K.js';
|
|
2
|
+
import { context, trace, propagation, SpanKind, SpanStatusCode } from '@opentelemetry/api';
|
|
3
|
+
import { createInitialiser, setConfig } from 'autotel-edge';
|
|
4
|
+
|
|
5
|
+
var coldStarts = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
function isColdStart(doClass) {
|
|
7
|
+
if (!coldStarts.has(doClass)) {
|
|
8
|
+
coldStarts.set(doClass, true);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
function instrumentDOFetch(fetchFn, id, doClass) {
|
|
14
|
+
return async function instrumentedFetch(request) {
|
|
15
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
16
|
+
const parentContext = propagation.extract(
|
|
17
|
+
context.active(),
|
|
18
|
+
request.headers
|
|
19
|
+
);
|
|
20
|
+
const url = new URL(request.url);
|
|
21
|
+
const spanName = `DO ${id.name || id.toString()}: ${request.method} ${url.pathname}`;
|
|
22
|
+
return tracer.startActiveSpan(
|
|
23
|
+
spanName,
|
|
24
|
+
{
|
|
25
|
+
kind: SpanKind.SERVER,
|
|
26
|
+
attributes: {
|
|
27
|
+
"http.request.method": request.method,
|
|
28
|
+
"url.full": request.url,
|
|
29
|
+
"do.id": id.toString(),
|
|
30
|
+
"do.id.name": id.name || "",
|
|
31
|
+
"faas.trigger": "http",
|
|
32
|
+
"faas.coldstart": isColdStart(doClass)
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
parentContext,
|
|
36
|
+
async (span) => {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetchFn.call(this, request);
|
|
39
|
+
span.setAttributes({
|
|
40
|
+
"http.response.status_code": response.status
|
|
41
|
+
});
|
|
42
|
+
if (response.ok) {
|
|
43
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
44
|
+
} else {
|
|
45
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
46
|
+
}
|
|
47
|
+
return response;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
span.recordException(error);
|
|
50
|
+
span.setStatus({
|
|
51
|
+
code: SpanStatusCode.ERROR,
|
|
52
|
+
message: error instanceof Error ? error.message : String(error)
|
|
53
|
+
});
|
|
54
|
+
throw error;
|
|
55
|
+
} finally {
|
|
56
|
+
span.end();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function instrumentDOAlarm(alarmFn, id, doClass) {
|
|
63
|
+
return async function instrumentedAlarm() {
|
|
64
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
65
|
+
const spanName = `DO ${id.name || id.toString()}: alarm`;
|
|
66
|
+
return tracer.startActiveSpan(
|
|
67
|
+
spanName,
|
|
68
|
+
{
|
|
69
|
+
kind: SpanKind.INTERNAL,
|
|
70
|
+
attributes: {
|
|
71
|
+
"do.id": id.toString(),
|
|
72
|
+
"do.id.name": id.name || "",
|
|
73
|
+
"faas.trigger": "timer",
|
|
74
|
+
"faas.coldstart": isColdStart(doClass)
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async (span) => {
|
|
78
|
+
try {
|
|
79
|
+
await alarmFn.call(this);
|
|
80
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
81
|
+
} catch (error) {
|
|
82
|
+
span.recordException(error);
|
|
83
|
+
span.setStatus({
|
|
84
|
+
code: SpanStatusCode.ERROR,
|
|
85
|
+
message: error instanceof Error ? error.message : String(error)
|
|
86
|
+
});
|
|
87
|
+
throw error;
|
|
88
|
+
} finally {
|
|
89
|
+
span.end();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function instrumentDOInstance(doInstance, state, _env, doClass) {
|
|
96
|
+
const instanceHandler = {
|
|
97
|
+
get(target, prop) {
|
|
98
|
+
const value = Reflect.get(target, prop);
|
|
99
|
+
if (prop === "fetch" && typeof value === "function") {
|
|
100
|
+
return instrumentDOFetch(value.bind(target), state.id, doClass);
|
|
101
|
+
}
|
|
102
|
+
if (prop === "alarm" && typeof value === "function") {
|
|
103
|
+
return instrumentDOAlarm(value.bind(target), state.id, doClass);
|
|
104
|
+
}
|
|
105
|
+
if (typeof value === "function") {
|
|
106
|
+
return value.bind(target);
|
|
107
|
+
}
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return wrap(doInstance, instanceHandler);
|
|
112
|
+
}
|
|
113
|
+
function instrumentDO(doClass, config) {
|
|
114
|
+
const initialiser = createInitialiser(config);
|
|
115
|
+
const classHandler = {
|
|
116
|
+
construct(target, [state, env]) {
|
|
117
|
+
const trigger = {
|
|
118
|
+
id: state.id.toString(),
|
|
119
|
+
name: state.id.name
|
|
120
|
+
};
|
|
121
|
+
const doConfig = initialiser(env, trigger);
|
|
122
|
+
const context$1 = setConfig(doConfig);
|
|
123
|
+
const doInstance = context.with(context$1, () => {
|
|
124
|
+
return new target(state, env);
|
|
125
|
+
});
|
|
126
|
+
return instrumentDOInstance(doInstance, state, env, doClass);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
return wrap(doClass, classHandler);
|
|
130
|
+
}
|
|
131
|
+
var coldStarts2 = /* @__PURE__ */ new WeakMap();
|
|
132
|
+
function isColdStart2(workflowClass) {
|
|
133
|
+
if (!coldStarts2.has(workflowClass)) {
|
|
134
|
+
coldStarts2.set(workflowClass, true);
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
function instrumentWorkflowStep(step, workflowName) {
|
|
140
|
+
const stepHandler = {
|
|
141
|
+
get(target, prop) {
|
|
142
|
+
const value = Reflect.get(target, prop);
|
|
143
|
+
if (prop === "do" && typeof value === "function") {
|
|
144
|
+
return new Proxy(value, {
|
|
145
|
+
apply: (fnTarget, thisArg, args) => {
|
|
146
|
+
const [stepName] = args;
|
|
147
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
148
|
+
return tracer.startActiveSpan(
|
|
149
|
+
`Workflow ${workflowName}: ${stepName}`,
|
|
150
|
+
{
|
|
151
|
+
kind: SpanKind.INTERNAL,
|
|
152
|
+
attributes: {
|
|
153
|
+
"workflow.step.name": stepName,
|
|
154
|
+
"workflow.name": workflowName
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
async (span) => {
|
|
158
|
+
try {
|
|
159
|
+
const result = await Reflect.apply(fnTarget, thisArg, args);
|
|
160
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
161
|
+
return result;
|
|
162
|
+
} catch (error) {
|
|
163
|
+
span.recordException(error);
|
|
164
|
+
span.setStatus({
|
|
165
|
+
code: SpanStatusCode.ERROR,
|
|
166
|
+
message: error instanceof Error ? error.message : String(error)
|
|
167
|
+
});
|
|
168
|
+
throw error;
|
|
169
|
+
} finally {
|
|
170
|
+
span.end();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
if (prop === "sleep" && typeof value === "function") {
|
|
178
|
+
return new Proxy(value, {
|
|
179
|
+
apply: (fnTarget, thisArg, args) => {
|
|
180
|
+
const [sleepName, duration] = args;
|
|
181
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
182
|
+
return tracer.startActiveSpan(
|
|
183
|
+
`Workflow ${workflowName}: sleep ${sleepName}`,
|
|
184
|
+
{
|
|
185
|
+
kind: SpanKind.INTERNAL,
|
|
186
|
+
attributes: {
|
|
187
|
+
"workflow.sleep.name": sleepName,
|
|
188
|
+
"workflow.sleep.duration": String(duration),
|
|
189
|
+
"workflow.name": workflowName
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
async (span) => {
|
|
193
|
+
try {
|
|
194
|
+
const result = await Reflect.apply(fnTarget, thisArg, args);
|
|
195
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
196
|
+
return result;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
span.recordException(error);
|
|
199
|
+
span.setStatus({
|
|
200
|
+
code: SpanStatusCode.ERROR,
|
|
201
|
+
message: error instanceof Error ? error.message : String(error)
|
|
202
|
+
});
|
|
203
|
+
throw error;
|
|
204
|
+
} finally {
|
|
205
|
+
span.end();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
if (typeof value === "function") {
|
|
213
|
+
return value.bind(target);
|
|
214
|
+
}
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
return wrap(step, stepHandler);
|
|
219
|
+
}
|
|
220
|
+
function instrumentWorkflowRun(runFn, workflowName, workflowClass) {
|
|
221
|
+
return async function instrumentedRun(event, step) {
|
|
222
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
223
|
+
const instrumentedStep = instrumentWorkflowStep(step, workflowName);
|
|
224
|
+
const spanName = `Workflow ${workflowName}: run`;
|
|
225
|
+
return tracer.startActiveSpan(
|
|
226
|
+
spanName,
|
|
227
|
+
{
|
|
228
|
+
kind: SpanKind.INTERNAL,
|
|
229
|
+
attributes: {
|
|
230
|
+
"workflow.name": workflowName,
|
|
231
|
+
"faas.trigger": "workflow",
|
|
232
|
+
"faas.coldstart": isColdStart2(workflowClass),
|
|
233
|
+
// Add workflow event attributes if available
|
|
234
|
+
...event?.workflowId && { "workflow.id": event.workflowId },
|
|
235
|
+
...event?.runId && { "workflow.run_id": event.runId }
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
async (span) => {
|
|
239
|
+
try {
|
|
240
|
+
await runFn.call(this, event, instrumentedStep);
|
|
241
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
242
|
+
} catch (error) {
|
|
243
|
+
span.recordException(error);
|
|
244
|
+
span.setStatus({
|
|
245
|
+
code: SpanStatusCode.ERROR,
|
|
246
|
+
message: error instanceof Error ? error.message : String(error)
|
|
247
|
+
});
|
|
248
|
+
throw error;
|
|
249
|
+
} finally {
|
|
250
|
+
span.end();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function instrumentWorkflowInstance(workflowInstance, workflowName, workflowClass) {
|
|
257
|
+
const instanceHandler = {
|
|
258
|
+
get(target, prop) {
|
|
259
|
+
const value = Reflect.get(target, prop);
|
|
260
|
+
if (prop === "run" && typeof value === "function") {
|
|
261
|
+
return instrumentWorkflowRun(
|
|
262
|
+
value.bind(target),
|
|
263
|
+
workflowName,
|
|
264
|
+
workflowClass
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
if (typeof value === "function") {
|
|
268
|
+
return value.bind(target);
|
|
269
|
+
}
|
|
270
|
+
return value;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
return wrap(workflowInstance, instanceHandler);
|
|
274
|
+
}
|
|
275
|
+
function instrumentWorkflow(workflowClass, workflowName, config) {
|
|
276
|
+
const initialiser = createInitialiser(config);
|
|
277
|
+
const classHandler = {
|
|
278
|
+
construct(target, args) {
|
|
279
|
+
const env = args[args.length - 1] || {};
|
|
280
|
+
const trigger = new Request("https://workflow.local/run");
|
|
281
|
+
const workflowConfig = initialiser(env, trigger);
|
|
282
|
+
const context$1 = setConfig(workflowConfig);
|
|
283
|
+
const workflowInstance = context.with(context$1, () => {
|
|
284
|
+
return new target(...args);
|
|
285
|
+
});
|
|
286
|
+
return instrumentWorkflowInstance(
|
|
287
|
+
workflowInstance,
|
|
288
|
+
workflowName,
|
|
289
|
+
workflowClass
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
return wrap(workflowClass, classHandler);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export { instrumentDO, instrumentWorkflow };
|
|
297
|
+
//# sourceMappingURL=chunk-QXFYTHQF.js.map
|
|
298
|
+
//# sourceMappingURL=chunk-QXFYTHQF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/handlers/durable-objects.ts","../src/handlers/workflows.ts"],"names":["api_context","context","coldStarts","isColdStart","trace","SpanKind","SpanStatusCode","createInitialiser","setConfig"],"mappings":"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","file":"chunk-QXFYTHQF.js","sourcesContent":["/**\n * Durable Objects instrumentation for Cloudflare Workers\n * \n * Note: This file uses Cloudflare Workers types (DurableObjectId, DurableObjectState, etc.)\n * which are globally available via @cloudflare/workers-types when listed in tsconfig.json.\n * These types are devDependencies only - they're not runtime dependencies.\n * At runtime, Cloudflare Workers runtime provides the actual implementations.\n */\n\nimport {\n trace,\n context as api_context,\n propagation,\n SpanStatusCode,\n SpanKind,\n} from '@opentelemetry/api';\nimport type { ConfigurationOption } from 'autotel-edge';\nimport { createInitialiser, setConfig, WorkerTracer } from 'autotel-edge';\nimport { wrap } from '../bindings/common';\n\n// Durable Object types\ntype DOFetchFn = (request: Request) => Response | Promise<Response>;\ntype DOAlarmFn = () => void | Promise<void>;\n\n/**\n * Track cold starts per DO class\n */\nconst coldStarts = new WeakMap<any, boolean>();\n\nfunction isColdStart(doClass: any): boolean {\n if (!coldStarts.has(doClass)) {\n coldStarts.set(doClass, true);\n return true;\n }\n return false;\n}\n\n/**\n * Instrument a Durable Object fetch method\n */\nfunction instrumentDOFetch(\n fetchFn: DOFetchFn,\n id: DurableObjectId,\n doClass: any,\n): DOFetchFn {\n return async function instrumentedFetch(\n this: any,\n request: Request,\n ): Promise<Response> {\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n // Extract parent context from request headers\n const parentContext = propagation.extract(\n api_context.active(),\n request.headers,\n );\n\n const url = new URL(request.url);\n const spanName = `DO ${id.name || id.toString()}: ${request.method} ${url.pathname}`;\n\n return tracer.startActiveSpan(\n spanName,\n {\n kind: SpanKind.SERVER,\n attributes: {\n 'http.request.method': request.method,\n 'url.full': request.url,\n 'do.id': id.toString(),\n 'do.id.name': id.name || '',\n 'faas.trigger': 'http',\n 'faas.coldstart': isColdStart(doClass),\n },\n },\n parentContext,\n async (span) => {\n try {\n const response = await fetchFn.call(this, request);\n\n span.setAttributes({\n 'http.response.status_code': response.status,\n });\n\n if (response.ok) {\n span.setStatus({ code: SpanStatusCode.OK });\n } else {\n span.setStatus({ code: SpanStatusCode.ERROR });\n }\n\n return response;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n };\n}\n\n/**\n * Instrument a Durable Object alarm method\n */\nfunction instrumentDOAlarm(\n alarmFn: DOAlarmFn,\n id: DurableObjectId,\n doClass: any,\n): DOAlarmFn {\n return async function instrumentedAlarm(this: any): Promise<void> {\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n const spanName = `DO ${id.name || id.toString()}: alarm`;\n\n return tracer.startActiveSpan(\n spanName,\n {\n kind: SpanKind.INTERNAL,\n attributes: {\n 'do.id': id.toString(),\n 'do.id.name': id.name || '',\n 'faas.trigger': 'timer',\n 'faas.coldstart': isColdStart(doClass),\n },\n },\n async (span) => {\n try {\n await alarmFn.call(this);\n span.setStatus({ code: SpanStatusCode.OK });\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n };\n}\n\n/**\n * Instrument a Durable Object instance\n */\nfunction instrumentDOInstance(\n doInstance: any,\n state: DurableObjectState,\n _env: any,\n doClass: any,\n): any {\n const instanceHandler: ProxyHandler<any> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'fetch' && typeof value === 'function') {\n return instrumentDOFetch(value.bind(target), state.id, doClass);\n }\n\n if (prop === 'alarm' && typeof value === 'function') {\n return instrumentDOAlarm(value.bind(target), state.id, doClass);\n }\n\n // Bind other methods to the target\n if (typeof value === 'function') {\n return value.bind(target);\n }\n\n return value;\n },\n };\n\n return wrap(doInstance, instanceHandler);\n}\n\n/**\n * Instrument a Durable Object class\n *\n * This wraps the DO class to automatically trace all fetch and alarm calls,\n * as well as initialize the telemetry configuration.\n *\n * **Usage:**\n * ```typescript\n * import { DurableObject } from 'cloudflare:workers'\n * import { instrumentDO } from 'autotel-edge'\n *\n * export class Counter extends DurableObject<Env> {\n * async fetch(request: Request) {\n * // Your DO logic here\n * return new Response('OK')\n * }\n * }\n *\n * // Wrap the class before exporting\n * export const CounterDO = instrumentDO(Counter, (env: Env) => ({\n * exporter: {\n * url: env.OTLP_ENDPOINT,\n * headers: { 'x-api-key': env.API_KEY }\n * },\n * service: {\n * name: 'my-durable-object',\n * version: '1.0.0'\n * }\n * }))\n * ```\n *\n * **What you get:**\n * - π― Automatic spans for fetch() calls with HTTP attributes\n * - β° Automatic spans for alarm() calls\n * - π₯Ά Cold start tracking\n * - π Context propagation from incoming requests\n * - β‘ Automatic span lifecycle management\n *\n * @param doClass - The Durable Object class to instrument\n * @param config - Configuration or configuration function\n * @returns Instrumented Durable Object class\n */\nexport function instrumentDO<C extends new (state: DurableObjectState, env: any) => any>(\n doClass: C,\n config: ConfigurationOption,\n): C {\n const initialiser = createInitialiser(config);\n\n const classHandler: ProxyHandler<C> = {\n construct(target, [state, env]: [DurableObjectState, any]) {\n // Initialize config for this DO instance\n const trigger = {\n id: state.id.toString(),\n name: state.id.name,\n };\n const doConfig = initialiser(env, trigger);\n const context = setConfig(doConfig);\n\n // Create the DO instance within the config context\n const doInstance = api_context.with(context, () => {\n return new target(state, env);\n });\n\n // Instrument the instance\n return instrumentDOInstance(doInstance, state, env, doClass);\n },\n };\n\n return wrap(doClass, classHandler);\n}\n","/**\n * Cloudflare Workflows instrumentation for autotel-edge\n *\n * Instruments WorkflowEntrypoint classes to automatically trace workflow execution,\n * step operations, retries, and sleeps.\n *\n * Based on Cloudflare Workflows API:\n * https://developers.cloudflare.com/workflows/\n */\n\nimport {\n trace,\n context as api_context,\n SpanStatusCode,\n SpanKind,\n} from '@opentelemetry/api';\nimport type { ConfigurationOption } from 'autotel-edge';\nimport { createInitialiser, setConfig, WorkerTracer } from 'autotel-edge';\nimport { wrap } from '../bindings/common';\n\n// Workflow types (these would come from @cloudflare/workers-types when available)\ntype WorkflowEvent = any;\ntype WorkflowStep = any;\n\ntype WorkflowRunFn = (\n event: WorkflowEvent,\n step: WorkflowStep,\n) => Promise<void> | void;\n\n/**\n * Track cold starts per Workflow class\n */\nconst coldStarts = new WeakMap<any, boolean>();\n\nfunction isColdStart(workflowClass: any): boolean {\n if (!coldStarts.has(workflowClass)) {\n coldStarts.set(workflowClass, true);\n return true;\n }\n return false;\n}\n\n/**\n * Proxy the step object to instrument step.do() calls\n */\nfunction instrumentWorkflowStep(\n step: WorkflowStep,\n workflowName: string,\n): WorkflowStep {\n const stepHandler: ProxyHandler<WorkflowStep> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n // Instrument step.do() to create spans for each workflow step\n if (prop === 'do' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, thisArg, args) => {\n const [stepName] = args as [string, () => Promise<any>];\n\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `Workflow ${workflowName}: ${stepName}`,\n {\n kind: SpanKind.INTERNAL,\n attributes: {\n 'workflow.step.name': stepName,\n 'workflow.name': workflowName,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, thisArg, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message:\n error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n // Instrument step.sleep() to track workflow delays\n if (prop === 'sleep' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, thisArg, args) => {\n const [sleepName, duration] = args as [string, string | number];\n\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `Workflow ${workflowName}: sleep ${sleepName}`,\n {\n kind: SpanKind.INTERNAL,\n attributes: {\n 'workflow.sleep.name': sleepName,\n 'workflow.sleep.duration': String(duration),\n 'workflow.name': workflowName,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, thisArg, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message:\n error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n // Pass through other step methods\n if (typeof value === 'function') {\n return value.bind(target);\n }\n\n return value;\n },\n };\n\n return wrap(step, stepHandler);\n}\n\n/**\n * Instrument a Workflow run method\n */\nfunction instrumentWorkflowRun(\n runFn: WorkflowRunFn,\n workflowName: string,\n workflowClass: any,\n): WorkflowRunFn {\n return async function instrumentedRun(\n this: any,\n event: WorkflowEvent,\n step: WorkflowStep,\n ): Promise<void> {\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n // Instrument the step object to track individual operations\n const instrumentedStep = instrumentWorkflowStep(step, workflowName);\n\n const spanName = `Workflow ${workflowName}: run`;\n\n return tracer.startActiveSpan(\n spanName,\n {\n kind: SpanKind.INTERNAL,\n attributes: {\n 'workflow.name': workflowName,\n 'faas.trigger': 'workflow',\n 'faas.coldstart': isColdStart(workflowClass),\n // Add workflow event attributes if available\n ...(event?.workflowId && { 'workflow.id': event.workflowId }),\n ...(event?.runId && { 'workflow.run_id': event.runId }),\n },\n },\n async (span) => {\n try {\n await runFn.call(this, event, instrumentedStep);\n span.setStatus({ code: SpanStatusCode.OK });\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n };\n}\n\n/**\n * Instrument a Workflow instance\n */\nfunction instrumentWorkflowInstance(\n workflowInstance: any,\n workflowName: string,\n workflowClass: any,\n): any {\n const instanceHandler: ProxyHandler<any> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'run' && typeof value === 'function') {\n return instrumentWorkflowRun(\n value.bind(target),\n workflowName,\n workflowClass,\n );\n }\n\n // Bind other methods to the target\n if (typeof value === 'function') {\n return value.bind(target);\n }\n\n return value;\n },\n };\n\n return wrap(workflowInstance, instanceHandler);\n}\n\n/**\n * Instrument a Cloudflare Workflow class\n *\n * This wraps the WorkflowEntrypoint class to automatically trace workflow execution,\n * step operations, retries, and sleeps.\n *\n * **Usage:**\n * ```typescript\n * import { WorkflowEntrypoint } from 'cloudflare:workers'\n * import { instrumentWorkflow } from 'autotel-edge'\n *\n * export class CheckoutWorkflow extends WorkflowEntrypoint {\n * async run(event, step) {\n * await step.do('submit payment', async () => {\n * return await submitToPaymentProcessor(event.params.payment)\n * })\n *\n * await step.sleep('wait for feedback', '2 days')\n *\n * await step.do('send feedback email', sendFeedbackEmail)\n * }\n * }\n *\n * // Wrap the class before exporting\n * export const CheckoutWorkflowInstrumented = instrumentWorkflow(\n * CheckoutWorkflow,\n * 'checkout-workflow',\n * (env: Env) => ({\n * exporter: {\n * url: env.OTLP_ENDPOINT,\n * headers: { 'x-api-key': env.API_KEY }\n * },\n * service: {\n * name: 'checkout-workflow',\n * version: '1.0.0'\n * }\n * })\n * )\n * ```\n *\n * **What you get:**\n * - π― Automatic spans for workflow.run() execution\n * - π Automatic spans for each step.do() operation\n * - βΈοΈ Automatic spans for step.sleep() operations\n * - π Automatic retry tracking (via step.do retries)\n * - π₯Ά Cold start tracking\n * - β‘ Automatic span lifecycle management\n *\n * @param workflowClass - The WorkflowEntrypoint class to instrument\n * @param workflowName - The name of the workflow (used in span names)\n * @param config - Configuration or configuration function\n * @returns Instrumented Workflow class\n */\nexport function instrumentWorkflow<\n C extends new (...args: any[]) => any,\n>(\n workflowClass: C,\n workflowName: string,\n config: ConfigurationOption,\n): C {\n const initialiser = createInitialiser(config);\n\n const classHandler: ProxyHandler<C> = {\n construct(target, args: any[]) {\n // Extract env from constructor args (typically last arg)\n const env = args[args.length - 1] || {};\n\n // Initialize config for this workflow instance\n // Use Request as trigger type since workflows don't have a standard Trigger type yet\n const trigger = new Request('https://workflow.local/run');\n const workflowConfig = initialiser(env, trigger);\n const context = setConfig(workflowConfig);\n\n // Create the workflow instance within the config context\n const workflowInstance = api_context.with(context, () => {\n return new target(...args);\n });\n\n // Instrument the instance\n return instrumentWorkflowInstance(\n workflowInstance,\n workflowName,\n workflowClass,\n );\n },\n };\n\n return wrap(workflowClass, classHandler);\n}\n\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/bindings/common.ts
|
|
2
|
+
var PromiseTracker = class {
|
|
3
|
+
promises = [];
|
|
4
|
+
track(promise) {
|
|
5
|
+
this.promises.push(promise);
|
|
6
|
+
}
|
|
7
|
+
async wait() {
|
|
8
|
+
await Promise.allSettled(this.promises);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
function proxyExecutionContext(ctx) {
|
|
12
|
+
const tracker = new PromiseTracker();
|
|
13
|
+
const proxied = new Proxy(ctx, {
|
|
14
|
+
get(target, prop) {
|
|
15
|
+
if (prop === "waitUntil") {
|
|
16
|
+
return (promise) => {
|
|
17
|
+
tracker.track(promise);
|
|
18
|
+
return target.waitUntil(promise);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return Reflect.get(target, prop);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return { ctx: proxied, tracker };
|
|
25
|
+
}
|
|
26
|
+
var unwrapSymbol = Symbol("unwrap");
|
|
27
|
+
function isWrapped(item) {
|
|
28
|
+
return item && !!item[unwrapSymbol];
|
|
29
|
+
}
|
|
30
|
+
function unwrap(item) {
|
|
31
|
+
if (item && isWrapped(item)) {
|
|
32
|
+
return item[unwrapSymbol];
|
|
33
|
+
} else {
|
|
34
|
+
return item;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function wrap(item, handler) {
|
|
38
|
+
const proxy = new Proxy(item, handler);
|
|
39
|
+
Object.defineProperty(proxy, unwrapSymbol, {
|
|
40
|
+
value: item,
|
|
41
|
+
writable: false,
|
|
42
|
+
enumerable: false,
|
|
43
|
+
configurable: false
|
|
44
|
+
});
|
|
45
|
+
return proxy;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { proxyExecutionContext, unwrap, wrap };
|
|
49
|
+
//# sourceMappingURL=chunk-SKKRPS5K.js.map
|
|
50
|
+
//# sourceMappingURL=chunk-SKKRPS5K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bindings/common.ts"],"names":[],"mappings":";AAOO,IAAM,iBAAN,MAAqB;AAAA,EAClB,WAA+B,EAAC;AAAA,EAExC,MAAM,OAAA,EAAiC;AACrC,IAAA,IAAA,CAAK,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,EAC5B;AAAA,EAEA,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,QAAQ,CAAA;AAAA,EACxC;AACF,CAAA;AAKO,SAAS,sBAAsB,GAAA,EAGpC;AACA,EAAA,MAAM,OAAA,GAAU,IAAI,cAAA,EAAe;AAEnC,EAAA,MAAM,OAAA,GAAU,IAAI,KAAA,CAAM,GAAA,EAAK;AAAA,IAC7B,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,IAAI,SAAS,WAAA,EAAa;AACxB,QAAA,OAAO,CAAC,OAAA,KAA8B;AACpC,UAAA,OAAA,CAAQ,MAAM,OAAO,CAAA;AACrB,UAAA,OAAO,MAAA,CAAO,UAAU,OAAO,CAAA;AAAA,QACjC,CAAA;AAAA,MACF;AACA,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA;AAAA,IACjC;AAAA,GACD,CAAA;AAED,EAAA,OAAO,EAAE,GAAA,EAAK,OAAA,EAAS,OAAA,EAAQ;AACjC;AAKA,IAAM,YAAA,GAAe,OAAO,QAAQ,CAAA;AAI7B,SAAS,UAAa,IAAA,EAA6B;AACxD,EAAA,OAAO,IAAA,IAAQ,CAAC,CAAE,IAAA,CAAoB,YAAY,CAAA;AACpD;AAEO,SAAS,OAAyB,IAAA,EAAY;AACnD,EAAA,IAAI,IAAA,IAAQ,SAAA,CAAU,IAAI,CAAA,EAAG;AAC3B,IAAA,OAAO,KAAK,YAAY,CAAA;AAAA,EAC1B,CAAA,MAAO;AACL,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,IAAA,CACd,MACA,OAAA,EACY;AACZ,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,IAAA,EAAM,OAAO,CAAA;AACrC,EAAA,MAAA,CAAO,cAAA,CAAe,OAAO,YAAA,EAAc;AAAA,IACzC,KAAA,EAAO,IAAA;AAAA,IACP,QAAA,EAAU,KAAA;AAAA,IACV,UAAA,EAAY,KAAA;AAAA,IACZ,YAAA,EAAc;AAAA,GACf,CAAA;AACD,EAAA,OAAO,KAAA;AACT","file":"chunk-SKKRPS5K.js","sourcesContent":["/**\n * Common instrumentation utilities\n */\n\n/**\n * Promise tracker for waitUntil\n */\nexport class PromiseTracker {\n private promises: Promise<unknown>[] = [];\n\n track(promise: Promise<unknown>): void {\n this.promises.push(promise);\n }\n\n async wait(): Promise<void> {\n await Promise.allSettled(this.promises);\n }\n}\n\n/**\n * Proxy ExecutionContext to track waitUntil promises\n */\nexport function proxyExecutionContext(ctx: ExecutionContext): {\n ctx: ExecutionContext;\n tracker: PromiseTracker;\n} {\n const tracker = new PromiseTracker();\n\n const proxied = new Proxy(ctx, {\n get(target, prop) {\n if (prop === 'waitUntil') {\n return (promise: Promise<unknown>) => {\n tracker.track(promise);\n return target.waitUntil(promise);\n };\n }\n return Reflect.get(target, prop);\n },\n });\n\n return { ctx: proxied, tracker };\n}\n\n/**\n * Helper to wrap/unwrap proxied objects\n */\nconst unwrapSymbol = Symbol('unwrap');\n\ntype Wrapped<T> = { [unwrapSymbol]: T } & T;\n\nexport function isWrapped<T>(item: T): item is Wrapped<T> {\n return item && !!(item as Wrapped<T>)[unwrapSymbol];\n}\n\nexport function unwrap<T extends object>(item: T): T {\n if (item && isWrapped(item)) {\n return item[unwrapSymbol];\n } else {\n return item;\n }\n}\n\nexport function wrap<T extends object>(\n item: T,\n handler: ProxyHandler<T>,\n): Wrapped<T> {\n const proxy = new Proxy(item, handler) as Wrapped<T>;\n Object.defineProperty(proxy, unwrapSymbol, {\n value: item,\n writable: false,\n enumerable: false,\n configurable: false,\n });\n return proxy;\n}\n"]}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from 'autotel-edge/events';
|
package/dist/events.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"events.js","sourcesContent":[]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { ConfigurationOption } from 'autotel-edge';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Durable Objects instrumentation for Cloudflare Workers
|
|
5
|
+
*
|
|
6
|
+
* Note: This file uses Cloudflare Workers types (DurableObjectId, DurableObjectState, etc.)
|
|
7
|
+
* which are globally available via @cloudflare/workers-types when listed in tsconfig.json.
|
|
8
|
+
* These types are devDependencies only - they're not runtime dependencies.
|
|
9
|
+
* At runtime, Cloudflare Workers runtime provides the actual implementations.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Instrument a Durable Object class
|
|
14
|
+
*
|
|
15
|
+
* This wraps the DO class to automatically trace all fetch and alarm calls,
|
|
16
|
+
* as well as initialize the telemetry configuration.
|
|
17
|
+
*
|
|
18
|
+
* **Usage:**
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { DurableObject } from 'cloudflare:workers'
|
|
21
|
+
* import { instrumentDO } from 'autotel-edge'
|
|
22
|
+
*
|
|
23
|
+
* export class Counter extends DurableObject<Env> {
|
|
24
|
+
* async fetch(request: Request) {
|
|
25
|
+
* // Your DO logic here
|
|
26
|
+
* return new Response('OK')
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* // Wrap the class before exporting
|
|
31
|
+
* export const CounterDO = instrumentDO(Counter, (env: Env) => ({
|
|
32
|
+
* exporter: {
|
|
33
|
+
* url: env.OTLP_ENDPOINT,
|
|
34
|
+
* headers: { 'x-api-key': env.API_KEY }
|
|
35
|
+
* },
|
|
36
|
+
* service: {
|
|
37
|
+
* name: 'my-durable-object',
|
|
38
|
+
* version: '1.0.0'
|
|
39
|
+
* }
|
|
40
|
+
* }))
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* **What you get:**
|
|
44
|
+
* - π― Automatic spans for fetch() calls with HTTP attributes
|
|
45
|
+
* - β° Automatic spans for alarm() calls
|
|
46
|
+
* - π₯Ά Cold start tracking
|
|
47
|
+
* - π Context propagation from incoming requests
|
|
48
|
+
* - β‘ Automatic span lifecycle management
|
|
49
|
+
*
|
|
50
|
+
* @param doClass - The Durable Object class to instrument
|
|
51
|
+
* @param config - Configuration or configuration function
|
|
52
|
+
* @returns Instrumented Durable Object class
|
|
53
|
+
*/
|
|
54
|
+
declare function instrumentDO<C extends new (state: DurableObjectState, env: any) => any>(doClass: C, config: ConfigurationOption): C;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Cloudflare Workflows instrumentation for autotel-edge
|
|
58
|
+
*
|
|
59
|
+
* Instruments WorkflowEntrypoint classes to automatically trace workflow execution,
|
|
60
|
+
* step operations, retries, and sleeps.
|
|
61
|
+
*
|
|
62
|
+
* Based on Cloudflare Workflows API:
|
|
63
|
+
* https://developers.cloudflare.com/workflows/
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Instrument a Cloudflare Workflow class
|
|
68
|
+
*
|
|
69
|
+
* This wraps the WorkflowEntrypoint class to automatically trace workflow execution,
|
|
70
|
+
* step operations, retries, and sleeps.
|
|
71
|
+
*
|
|
72
|
+
* **Usage:**
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import { WorkflowEntrypoint } from 'cloudflare:workers'
|
|
75
|
+
* import { instrumentWorkflow } from 'autotel-edge'
|
|
76
|
+
*
|
|
77
|
+
* export class CheckoutWorkflow extends WorkflowEntrypoint {
|
|
78
|
+
* async run(event, step) {
|
|
79
|
+
* await step.do('submit payment', async () => {
|
|
80
|
+
* return await submitToPaymentProcessor(event.params.payment)
|
|
81
|
+
* })
|
|
82
|
+
*
|
|
83
|
+
* await step.sleep('wait for feedback', '2 days')
|
|
84
|
+
*
|
|
85
|
+
* await step.do('send feedback email', sendFeedbackEmail)
|
|
86
|
+
* }
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* // Wrap the class before exporting
|
|
90
|
+
* export const CheckoutWorkflowInstrumented = instrumentWorkflow(
|
|
91
|
+
* CheckoutWorkflow,
|
|
92
|
+
* 'checkout-workflow',
|
|
93
|
+
* (env: Env) => ({
|
|
94
|
+
* exporter: {
|
|
95
|
+
* url: env.OTLP_ENDPOINT,
|
|
96
|
+
* headers: { 'x-api-key': env.API_KEY }
|
|
97
|
+
* },
|
|
98
|
+
* service: {
|
|
99
|
+
* name: 'checkout-workflow',
|
|
100
|
+
* version: '1.0.0'
|
|
101
|
+
* }
|
|
102
|
+
* })
|
|
103
|
+
* )
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* **What you get:**
|
|
107
|
+
* - π― Automatic spans for workflow.run() execution
|
|
108
|
+
* - π Automatic spans for each step.do() operation
|
|
109
|
+
* - βΈοΈ Automatic spans for step.sleep() operations
|
|
110
|
+
* - π Automatic retry tracking (via step.do retries)
|
|
111
|
+
* - π₯Ά Cold start tracking
|
|
112
|
+
* - β‘ Automatic span lifecycle management
|
|
113
|
+
*
|
|
114
|
+
* @param workflowClass - The WorkflowEntrypoint class to instrument
|
|
115
|
+
* @param workflowName - The name of the workflow (used in span names)
|
|
116
|
+
* @param config - Configuration or configuration function
|
|
117
|
+
* @returns Instrumented Workflow class
|
|
118
|
+
*/
|
|
119
|
+
declare function instrumentWorkflow<C extends new (...args: any[]) => any>(workflowClass: C, workflowName: string, config: ConfigurationOption): C;
|
|
120
|
+
|
|
121
|
+
export { instrumentDO, instrumentWorkflow };
|
package/dist/handlers.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"handlers.js"}
|