autotel-cloudflare 2.18.18 → 2.19.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/dist/actors.d.ts +54 -89
- package/dist/actors.d.ts.map +1 -0
- package/dist/actors.js +990 -986
- package/dist/actors.js.map +1 -1
- package/dist/agents.d.ts +102 -128
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +275 -259
- package/dist/agents.js.map +1 -1
- package/dist/bindings-C10RI6Il.js +975 -0
- package/dist/bindings-C10RI6Il.js.map +1 -0
- package/dist/bindings-xEZcXo5r.d.ts +149 -0
- package/dist/bindings-xEZcXo5r.d.ts.map +1 -0
- package/dist/bindings.d.ts +2 -139
- package/dist/bindings.js +3 -4
- package/dist/common-DiWH6nmG.js +63 -0
- package/dist/common-DiWH6nmG.js.map +1 -0
- package/dist/events.d.ts +1 -1
- package/dist/events.js +3 -3
- package/dist/execution-logger-BxmgP8jF.js +65 -0
- package/dist/execution-logger-BxmgP8jF.js.map +1 -0
- package/dist/{logger-Cm_73k3-.d.ts → execution-logger-tgQmJeeU.d.ts} +9 -7
- package/dist/execution-logger-tgQmJeeU.d.ts.map +1 -0
- package/dist/handlers-CMg9l_T-.js +378 -0
- package/dist/handlers-CMg9l_T-.js.map +1 -0
- package/dist/handlers-C_VojUeA.d.ts +96 -0
- package/dist/handlers-C_VojUeA.d.ts.map +1 -0
- package/dist/handlers.d.ts +2 -112
- package/dist/handlers.js +3 -4
- package/dist/index.d.ts +20 -99
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +644 -600
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +3 -3
- package/dist/logger.js +5 -4
- package/dist/parse-error.d.ts +2 -1
- package/dist/parse-error.js +3 -3
- package/dist/sampling.d.ts +1 -4
- package/dist/sampling.js +3 -3
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +3 -3
- package/package.json +6 -6
- package/src/bindings/ai.test.ts +1 -1
- package/src/bindings/ai.ts +3 -1
- package/dist/bindings.js.map +0 -1
- package/dist/chunk-KAUHT25H.js +0 -1084
- package/dist/chunk-KAUHT25H.js.map +0 -1
- package/dist/chunk-MIDMNKDC.js +0 -333
- package/dist/chunk-MIDMNKDC.js.map +0 -1
- package/dist/chunk-O4IYKWPJ.js +0 -55
- package/dist/chunk-O4IYKWPJ.js.map +0 -1
- package/dist/chunk-RVVMMPWN.js +0 -63
- package/dist/chunk-RVVMMPWN.js.map +0 -1
- package/dist/events.js.map +0 -1
- package/dist/handlers.js.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/parse-error.js.map +0 -1
- package/dist/sampling.js.map +0 -1
- package/dist/testing.js.map +0 -1
|
@@ -0,0 +1,975 @@
|
|
|
1
|
+
import { a as wrap, r as setAttr, t as isWrapped } from "./common-DiWH6nmG.js";
|
|
2
|
+
import { getActiveConfig } from "autotel-edge";
|
|
3
|
+
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
4
|
+
|
|
5
|
+
//#region src/bindings/ai.ts
|
|
6
|
+
/**
|
|
7
|
+
* Workers AI binding instrumentation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Instrument Workers AI binding
|
|
11
|
+
*/
|
|
12
|
+
function instrumentAI(ai, bindingName) {
|
|
13
|
+
const name = bindingName || "ai";
|
|
14
|
+
return wrap(ai, { get(target, prop) {
|
|
15
|
+
const value = Reflect.get(target, prop);
|
|
16
|
+
if (prop === "run" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
17
|
+
const [model] = args;
|
|
18
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`AI ${name}: run ${model}`, {
|
|
19
|
+
kind: SpanKind.CLIENT,
|
|
20
|
+
attributes: {
|
|
21
|
+
"gen_ai.provider.name": "cloudflare-workers-ai",
|
|
22
|
+
"gen_ai.operation.name": "run",
|
|
23
|
+
"gen_ai.request.model": model
|
|
24
|
+
}
|
|
25
|
+
}, async (span) => {
|
|
26
|
+
try {
|
|
27
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
28
|
+
if (result?.usage?.prompt_tokens !== void 0) setAttr(span, "gen_ai.usage.input_tokens", Number(result.usage.prompt_tokens));
|
|
29
|
+
if (result?.usage?.completion_tokens !== void 0) setAttr(span, "gen_ai.usage.output_tokens", Number(result.usage.completion_tokens));
|
|
30
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
31
|
+
return result;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
span.recordException(error);
|
|
34
|
+
span.setStatus({
|
|
35
|
+
code: SpanStatusCode.ERROR,
|
|
36
|
+
message: error instanceof Error ? error.message : String(error)
|
|
37
|
+
});
|
|
38
|
+
throw error;
|
|
39
|
+
} finally {
|
|
40
|
+
span.end();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
} });
|
|
44
|
+
return value;
|
|
45
|
+
} });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/bindings/vectorize.ts
|
|
50
|
+
/**
|
|
51
|
+
* Vectorize binding instrumentation
|
|
52
|
+
*/
|
|
53
|
+
const TRACED_METHODS = [
|
|
54
|
+
"query",
|
|
55
|
+
"insert",
|
|
56
|
+
"upsert",
|
|
57
|
+
"deleteByIds",
|
|
58
|
+
"getByIds",
|
|
59
|
+
"describe"
|
|
60
|
+
];
|
|
61
|
+
/**
|
|
62
|
+
* Instrument Vectorize index binding
|
|
63
|
+
*/
|
|
64
|
+
function instrumentVectorize(vectorize, indexName) {
|
|
65
|
+
const name = indexName || "vectorize";
|
|
66
|
+
return wrap(vectorize, { get(target, prop) {
|
|
67
|
+
const value = Reflect.get(target, prop);
|
|
68
|
+
if (typeof prop === "string" && TRACED_METHODS.includes(prop) && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
69
|
+
const operation = prop;
|
|
70
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
71
|
+
const attributes = {
|
|
72
|
+
"db.system": "cloudflare-vectorize",
|
|
73
|
+
"db.operation": operation,
|
|
74
|
+
"db.collection.name": name
|
|
75
|
+
};
|
|
76
|
+
if (operation === "query") {
|
|
77
|
+
const queryInput = args[0];
|
|
78
|
+
if (queryInput?.topK !== void 0) attributes["db.vectorize.top_k"] = queryInput.topK;
|
|
79
|
+
}
|
|
80
|
+
if ((operation === "insert" || operation === "upsert") && Array.isArray(args[0])) attributes["db.vectorize.vectors_count"] = args[0].length;
|
|
81
|
+
return tracer.startActiveSpan(`Vectorize ${name}: ${operation}`, {
|
|
82
|
+
kind: SpanKind.CLIENT,
|
|
83
|
+
attributes
|
|
84
|
+
}, async (span) => {
|
|
85
|
+
try {
|
|
86
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
87
|
+
if (operation === "query" && result?.matches) setAttr(span, "db.vectorize.matches_count", result.matches.length);
|
|
88
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
89
|
+
return result;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
span.recordException(error);
|
|
92
|
+
span.setStatus({
|
|
93
|
+
code: SpanStatusCode.ERROR,
|
|
94
|
+
message: error instanceof Error ? error.message : String(error)
|
|
95
|
+
});
|
|
96
|
+
throw error;
|
|
97
|
+
} finally {
|
|
98
|
+
span.end();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
} });
|
|
102
|
+
return value;
|
|
103
|
+
} });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/bindings/hyperdrive.ts
|
|
108
|
+
/**
|
|
109
|
+
* Hyperdrive binding instrumentation
|
|
110
|
+
*/
|
|
111
|
+
/**
|
|
112
|
+
* Instrument Hyperdrive binding
|
|
113
|
+
*/
|
|
114
|
+
function instrumentHyperdrive(hyperdrive, bindingName) {
|
|
115
|
+
const name = bindingName || "hyperdrive";
|
|
116
|
+
return wrap(hyperdrive, { get(target, prop) {
|
|
117
|
+
const value = Reflect.get(target, prop);
|
|
118
|
+
if (prop === "connect" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
119
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
120
|
+
const attributes = {
|
|
121
|
+
"db.system": "cloudflare-hyperdrive",
|
|
122
|
+
"db.operation": "connect"
|
|
123
|
+
};
|
|
124
|
+
try {
|
|
125
|
+
setAttr({ setAttribute: (k, v) => {
|
|
126
|
+
if (v !== void 0 && v !== null) attributes[k] = v;
|
|
127
|
+
} }, "server.address", target.host);
|
|
128
|
+
setAttr({ setAttribute: (k, v) => {
|
|
129
|
+
if (v !== void 0 && v !== null) attributes[k] = v;
|
|
130
|
+
} }, "server.port", target.port);
|
|
131
|
+
setAttr({ setAttribute: (k, v) => {
|
|
132
|
+
if (v !== void 0 && v !== null) attributes[k] = v;
|
|
133
|
+
} }, "db.user", target.user);
|
|
134
|
+
} catch {}
|
|
135
|
+
return tracer.startActiveSpan(`Hyperdrive ${name}: connect`, {
|
|
136
|
+
kind: SpanKind.CLIENT,
|
|
137
|
+
attributes
|
|
138
|
+
}, async (span) => {
|
|
139
|
+
try {
|
|
140
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
141
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
142
|
+
return result;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
span.recordException(error);
|
|
145
|
+
span.setStatus({
|
|
146
|
+
code: SpanStatusCode.ERROR,
|
|
147
|
+
message: error instanceof Error ? error.message : String(error)
|
|
148
|
+
});
|
|
149
|
+
throw error;
|
|
150
|
+
} finally {
|
|
151
|
+
span.end();
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
} });
|
|
155
|
+
return value;
|
|
156
|
+
} });
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/bindings/queue-producer.ts
|
|
161
|
+
/**
|
|
162
|
+
* Queue producer binding instrumentation
|
|
163
|
+
*/
|
|
164
|
+
/**
|
|
165
|
+
* Instrument Queue producer binding
|
|
166
|
+
*/
|
|
167
|
+
function instrumentQueueProducer(queue, queueName) {
|
|
168
|
+
const name = queueName || "queue";
|
|
169
|
+
return wrap(queue, { get(target, prop) {
|
|
170
|
+
const value = Reflect.get(target, prop);
|
|
171
|
+
if (prop === "send" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
172
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`Queue ${name}: send`, {
|
|
173
|
+
kind: SpanKind.PRODUCER,
|
|
174
|
+
attributes: {
|
|
175
|
+
"messaging.system": "cloudflare-queues",
|
|
176
|
+
"messaging.operation.type": "publish",
|
|
177
|
+
"messaging.operation": "send",
|
|
178
|
+
"messaging.destination.name": name
|
|
179
|
+
}
|
|
180
|
+
}, async (span) => {
|
|
181
|
+
try {
|
|
182
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
183
|
+
setAttr(span, "messaging.message.id", result?.messageId);
|
|
184
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
185
|
+
return result;
|
|
186
|
+
} catch (error) {
|
|
187
|
+
span.recordException(error);
|
|
188
|
+
span.setStatus({
|
|
189
|
+
code: SpanStatusCode.ERROR,
|
|
190
|
+
message: error instanceof Error ? error.message : String(error)
|
|
191
|
+
});
|
|
192
|
+
throw error;
|
|
193
|
+
} finally {
|
|
194
|
+
span.end();
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
} });
|
|
198
|
+
if (prop === "sendBatch" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
199
|
+
const [messages] = args;
|
|
200
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`Queue ${name}: sendBatch`, {
|
|
201
|
+
kind: SpanKind.PRODUCER,
|
|
202
|
+
attributes: {
|
|
203
|
+
"messaging.system": "cloudflare-queues",
|
|
204
|
+
"messaging.operation.type": "publish",
|
|
205
|
+
"messaging.operation": "sendBatch",
|
|
206
|
+
"messaging.destination.name": name,
|
|
207
|
+
"messaging.batch.message_count": Array.isArray(messages) ? messages.length : 0
|
|
208
|
+
}
|
|
209
|
+
}, async (span) => {
|
|
210
|
+
try {
|
|
211
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
212
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
213
|
+
return result;
|
|
214
|
+
} catch (error) {
|
|
215
|
+
span.recordException(error);
|
|
216
|
+
span.setStatus({
|
|
217
|
+
code: SpanStatusCode.ERROR,
|
|
218
|
+
message: error instanceof Error ? error.message : String(error)
|
|
219
|
+
});
|
|
220
|
+
throw error;
|
|
221
|
+
} finally {
|
|
222
|
+
span.end();
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
} });
|
|
226
|
+
return value;
|
|
227
|
+
} });
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/bindings/analytics-engine.ts
|
|
232
|
+
/**
|
|
233
|
+
* Analytics Engine binding instrumentation
|
|
234
|
+
*/
|
|
235
|
+
/**
|
|
236
|
+
* Instrument Analytics Engine binding
|
|
237
|
+
*/
|
|
238
|
+
function instrumentAnalyticsEngine(ae, datasetName) {
|
|
239
|
+
const name = datasetName || "analytics-engine";
|
|
240
|
+
return wrap(ae, { get(target, prop) {
|
|
241
|
+
const value = Reflect.get(target, prop);
|
|
242
|
+
if (prop === "writeDataPoint" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
243
|
+
const [dataPoint] = args;
|
|
244
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
245
|
+
const attributes = {
|
|
246
|
+
"analytics.system": "cloudflare-analytics-engine",
|
|
247
|
+
"analytics.operation": "writeDataPoint"
|
|
248
|
+
};
|
|
249
|
+
if (dataPoint) {
|
|
250
|
+
if (dataPoint.indexes) attributes["analytics.indexes_count"] = Array.isArray(dataPoint.indexes) ? dataPoint.indexes.length : 1;
|
|
251
|
+
if (dataPoint.doubles) attributes["analytics.doubles_count"] = dataPoint.doubles.length;
|
|
252
|
+
if (dataPoint.blobs) attributes["analytics.blobs_count"] = dataPoint.blobs.length;
|
|
253
|
+
}
|
|
254
|
+
return tracer.startActiveSpan(`AnalyticsEngine ${name}: writeDataPoint`, {
|
|
255
|
+
kind: SpanKind.CLIENT,
|
|
256
|
+
attributes
|
|
257
|
+
}, (span) => {
|
|
258
|
+
try {
|
|
259
|
+
Reflect.apply(fnTarget, target, args);
|
|
260
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
261
|
+
} catch (error) {
|
|
262
|
+
span.recordException(error);
|
|
263
|
+
span.setStatus({
|
|
264
|
+
code: SpanStatusCode.ERROR,
|
|
265
|
+
message: error instanceof Error ? error.message : String(error)
|
|
266
|
+
});
|
|
267
|
+
throw error;
|
|
268
|
+
} finally {
|
|
269
|
+
span.end();
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
} });
|
|
273
|
+
return value;
|
|
274
|
+
} });
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region src/bindings/images.ts
|
|
279
|
+
/**
|
|
280
|
+
* Images binding instrumentation
|
|
281
|
+
*
|
|
282
|
+
* The Images binding uses a fluent chain: input() -> transform() -> draw() -> output()
|
|
283
|
+
* We only create a span at the terminal output() call to avoid intermediate noise.
|
|
284
|
+
* info() is a standalone operation and gets its own span.
|
|
285
|
+
*/
|
|
286
|
+
const pipelineMetaSymbol = Symbol("images-pipeline-meta");
|
|
287
|
+
function proxyTransformer(transformer, meta, bindingName) {
|
|
288
|
+
const proxy = new Proxy(transformer, { get(target, prop) {
|
|
289
|
+
const value = Reflect.get(target, prop);
|
|
290
|
+
if ((prop === "transform" || prop === "draw") && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
291
|
+
meta.operationCount++;
|
|
292
|
+
const result = Reflect.apply(fnTarget, target, args);
|
|
293
|
+
if (result === target || result && typeof result === "object" && "output" in result) return proxyTransformer(result, meta, bindingName);
|
|
294
|
+
return result;
|
|
295
|
+
} });
|
|
296
|
+
if (prop === "output" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
297
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
298
|
+
const [formatOrOptions] = args;
|
|
299
|
+
const attributes = {
|
|
300
|
+
"images.system": "cloudflare-images",
|
|
301
|
+
"images.pipeline.operation_count": meta.operationCount
|
|
302
|
+
};
|
|
303
|
+
if (typeof formatOrOptions === "string") attributes["images.output.format"] = formatOrOptions;
|
|
304
|
+
else if (formatOrOptions && typeof formatOrOptions === "object") {
|
|
305
|
+
const fmt = formatOrOptions.format;
|
|
306
|
+
if (fmt) attributes["images.output.format"] = fmt;
|
|
307
|
+
}
|
|
308
|
+
return tracer.startActiveSpan(`Images ${bindingName}: output`, {
|
|
309
|
+
kind: SpanKind.CLIENT,
|
|
310
|
+
attributes
|
|
311
|
+
}, async (span) => {
|
|
312
|
+
try {
|
|
313
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
314
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
315
|
+
return result;
|
|
316
|
+
} catch (error) {
|
|
317
|
+
span.recordException(error);
|
|
318
|
+
span.setStatus({
|
|
319
|
+
code: SpanStatusCode.ERROR,
|
|
320
|
+
message: error instanceof Error ? error.message : String(error)
|
|
321
|
+
});
|
|
322
|
+
throw error;
|
|
323
|
+
} finally {
|
|
324
|
+
span.end();
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
} });
|
|
328
|
+
return value;
|
|
329
|
+
} });
|
|
330
|
+
Object.defineProperty(proxy, pipelineMetaSymbol, {
|
|
331
|
+
value: meta,
|
|
332
|
+
writable: false,
|
|
333
|
+
enumerable: false,
|
|
334
|
+
configurable: false
|
|
335
|
+
});
|
|
336
|
+
return proxy;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Instrument Images binding
|
|
340
|
+
*/
|
|
341
|
+
function instrumentImages(images, bindingName) {
|
|
342
|
+
const name = bindingName || "images";
|
|
343
|
+
return wrap(images, { get(target, prop) {
|
|
344
|
+
const value = Reflect.get(target, prop);
|
|
345
|
+
if (prop === "info" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
346
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`Images ${name}: info`, {
|
|
347
|
+
kind: SpanKind.CLIENT,
|
|
348
|
+
attributes: {
|
|
349
|
+
"images.system": "cloudflare-images",
|
|
350
|
+
"images.operation": "info"
|
|
351
|
+
}
|
|
352
|
+
}, async (span) => {
|
|
353
|
+
try {
|
|
354
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
355
|
+
setAttr(span, "images.width", result?.width);
|
|
356
|
+
setAttr(span, "images.height", result?.height);
|
|
357
|
+
setAttr(span, "images.format", result?.format);
|
|
358
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
359
|
+
return result;
|
|
360
|
+
} catch (error) {
|
|
361
|
+
span.recordException(error);
|
|
362
|
+
span.setStatus({
|
|
363
|
+
code: SpanStatusCode.ERROR,
|
|
364
|
+
message: error instanceof Error ? error.message : String(error)
|
|
365
|
+
});
|
|
366
|
+
throw error;
|
|
367
|
+
} finally {
|
|
368
|
+
span.end();
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
} });
|
|
372
|
+
if (prop === "input" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
373
|
+
return proxyTransformer(Reflect.apply(fnTarget, target, args), { operationCount: 0 }, name);
|
|
374
|
+
} });
|
|
375
|
+
return value;
|
|
376
|
+
} });
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
//#endregion
|
|
380
|
+
//#region src/bindings/bindings.ts
|
|
381
|
+
/**
|
|
382
|
+
* Auto-instrumentation for Cloudflare Workers bindings
|
|
383
|
+
*
|
|
384
|
+
* Note: This file uses Cloudflare Workers types (KVNamespace, R2Bucket, D1Database, Fetcher, etc.)
|
|
385
|
+
* which are globally available via @cloudflare/workers-types when listed in tsconfig.json.
|
|
386
|
+
* These types are devDependencies only - they're not runtime dependencies.
|
|
387
|
+
* At runtime, Cloudflare Workers runtime provides the actual implementations.
|
|
388
|
+
*
|
|
389
|
+
* This module provides automatic tracing for Cloudflare bindings:
|
|
390
|
+
* - KV (key-value operations)
|
|
391
|
+
* - R2 (object storage operations)
|
|
392
|
+
* - D1 (database operations)
|
|
393
|
+
* - Service Bindings
|
|
394
|
+
* - Events Engine
|
|
395
|
+
* - Workers AI
|
|
396
|
+
* - Vectorize
|
|
397
|
+
* - Hyperdrive
|
|
398
|
+
*/
|
|
399
|
+
/**
|
|
400
|
+
* Sanitize a SQL statement based on the capture mode.
|
|
401
|
+
* - 'full': returns the statement as-is
|
|
402
|
+
* - 'obfuscated': replaces string literals and numbers with '?'
|
|
403
|
+
* - 'off': returns undefined (attribute not set)
|
|
404
|
+
*/
|
|
405
|
+
function sanitizeStatement(query, mode) {
|
|
406
|
+
if (mode === "off") return void 0;
|
|
407
|
+
if (mode === "obfuscated") return query.replaceAll(/'[^']*'/g, "'?'").replaceAll(/\b\d+\b/g, "?");
|
|
408
|
+
return query;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Instrument KV namespace
|
|
412
|
+
*/
|
|
413
|
+
function instrumentKV(kv, namespaceName) {
|
|
414
|
+
const name = namespaceName || "kv";
|
|
415
|
+
return wrap(kv, { get(target, prop) {
|
|
416
|
+
const value = Reflect.get(target, prop);
|
|
417
|
+
if (prop === "get" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
418
|
+
const [key, options] = args;
|
|
419
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`KV ${name}: get`, {
|
|
420
|
+
kind: SpanKind.CLIENT,
|
|
421
|
+
attributes: {
|
|
422
|
+
"db.system": "cloudflare-kv",
|
|
423
|
+
"db.operation": "get",
|
|
424
|
+
"db.namespace": name,
|
|
425
|
+
"db.key": key,
|
|
426
|
+
"db.cache_hit": options?.cacheTtl !== void 0
|
|
427
|
+
}
|
|
428
|
+
}, async (span) => {
|
|
429
|
+
try {
|
|
430
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
431
|
+
span.setAttribute("db.result.type", result === null ? "null" : typeof result);
|
|
432
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
433
|
+
return result;
|
|
434
|
+
} catch (error) {
|
|
435
|
+
span.recordException(error);
|
|
436
|
+
span.setStatus({
|
|
437
|
+
code: SpanStatusCode.ERROR,
|
|
438
|
+
message: error instanceof Error ? error.message : String(error)
|
|
439
|
+
});
|
|
440
|
+
throw error;
|
|
441
|
+
} finally {
|
|
442
|
+
span.end();
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
} });
|
|
446
|
+
if (prop === "put" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
447
|
+
const [key] = args;
|
|
448
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`KV ${name}: put`, {
|
|
449
|
+
kind: SpanKind.CLIENT,
|
|
450
|
+
attributes: {
|
|
451
|
+
"db.system": "cloudflare-kv",
|
|
452
|
+
"db.operation": "put",
|
|
453
|
+
"db.namespace": name,
|
|
454
|
+
"db.key": key
|
|
455
|
+
}
|
|
456
|
+
}, async (span) => {
|
|
457
|
+
try {
|
|
458
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
459
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
460
|
+
return result;
|
|
461
|
+
} catch (error) {
|
|
462
|
+
span.recordException(error);
|
|
463
|
+
span.setStatus({
|
|
464
|
+
code: SpanStatusCode.ERROR,
|
|
465
|
+
message: error instanceof Error ? error.message : String(error)
|
|
466
|
+
});
|
|
467
|
+
throw error;
|
|
468
|
+
} finally {
|
|
469
|
+
span.end();
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
} });
|
|
473
|
+
if (prop === "delete" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
474
|
+
const [key] = args;
|
|
475
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`KV ${name}: delete`, {
|
|
476
|
+
kind: SpanKind.CLIENT,
|
|
477
|
+
attributes: {
|
|
478
|
+
"db.system": "cloudflare-kv",
|
|
479
|
+
"db.operation": "delete",
|
|
480
|
+
"db.namespace": name,
|
|
481
|
+
"db.key": key
|
|
482
|
+
}
|
|
483
|
+
}, async (span) => {
|
|
484
|
+
try {
|
|
485
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
486
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
487
|
+
return result;
|
|
488
|
+
} catch (error) {
|
|
489
|
+
span.recordException(error);
|
|
490
|
+
span.setStatus({
|
|
491
|
+
code: SpanStatusCode.ERROR,
|
|
492
|
+
message: error instanceof Error ? error.message : String(error)
|
|
493
|
+
});
|
|
494
|
+
throw error;
|
|
495
|
+
} finally {
|
|
496
|
+
span.end();
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
} });
|
|
500
|
+
if (prop === "list" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
501
|
+
const [options] = args;
|
|
502
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`KV ${name}: list`, {
|
|
503
|
+
kind: SpanKind.CLIENT,
|
|
504
|
+
attributes: {
|
|
505
|
+
"db.system": "cloudflare-kv",
|
|
506
|
+
"db.operation": "list",
|
|
507
|
+
"db.namespace": name,
|
|
508
|
+
"db.prefix": options?.prefix || void 0,
|
|
509
|
+
"db.limit": options?.limit || void 0
|
|
510
|
+
}
|
|
511
|
+
}, async (span) => {
|
|
512
|
+
try {
|
|
513
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
514
|
+
span.setAttribute("db.result.keys_count", result.keys.length);
|
|
515
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
516
|
+
return result;
|
|
517
|
+
} catch (error) {
|
|
518
|
+
span.recordException(error);
|
|
519
|
+
span.setStatus({
|
|
520
|
+
code: SpanStatusCode.ERROR,
|
|
521
|
+
message: error instanceof Error ? error.message : String(error)
|
|
522
|
+
});
|
|
523
|
+
throw error;
|
|
524
|
+
} finally {
|
|
525
|
+
span.end();
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
} });
|
|
529
|
+
return value;
|
|
530
|
+
} });
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Instrument R2 bucket
|
|
534
|
+
*/
|
|
535
|
+
function instrumentR2(r2, bucketName) {
|
|
536
|
+
const name = bucketName || "r2";
|
|
537
|
+
return wrap(r2, { get(target, prop) {
|
|
538
|
+
const value = Reflect.get(target, prop);
|
|
539
|
+
if (prop === "get" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
540
|
+
const [key] = args;
|
|
541
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`R2 ${name}: get`, {
|
|
542
|
+
kind: SpanKind.CLIENT,
|
|
543
|
+
attributes: {
|
|
544
|
+
"db.system": "cloudflare-r2",
|
|
545
|
+
"db.operation": "get",
|
|
546
|
+
"db.bucket": name,
|
|
547
|
+
"db.key": key
|
|
548
|
+
}
|
|
549
|
+
}, async (span) => {
|
|
550
|
+
try {
|
|
551
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
552
|
+
if (result) {
|
|
553
|
+
span.setAttribute("db.result.size", result.size);
|
|
554
|
+
span.setAttribute("db.result.etag", result.etag);
|
|
555
|
+
span.setAttribute("db.result.content_type", result.httpMetadata?.contentType);
|
|
556
|
+
} else span.setAttribute("db.result.exists", false);
|
|
557
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
558
|
+
return result;
|
|
559
|
+
} catch (error) {
|
|
560
|
+
span.recordException(error);
|
|
561
|
+
span.setStatus({
|
|
562
|
+
code: SpanStatusCode.ERROR,
|
|
563
|
+
message: error instanceof Error ? error.message : String(error)
|
|
564
|
+
});
|
|
565
|
+
throw error;
|
|
566
|
+
} finally {
|
|
567
|
+
span.end();
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
} });
|
|
571
|
+
if (prop === "put" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
572
|
+
const [key] = args;
|
|
573
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`R2 ${name}: put`, {
|
|
574
|
+
kind: SpanKind.CLIENT,
|
|
575
|
+
attributes: {
|
|
576
|
+
"db.system": "cloudflare-r2",
|
|
577
|
+
"db.operation": "put",
|
|
578
|
+
"db.bucket": name,
|
|
579
|
+
"db.key": key
|
|
580
|
+
}
|
|
581
|
+
}, async (span) => {
|
|
582
|
+
try {
|
|
583
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
584
|
+
span.setAttribute("db.result.etag", result.etag);
|
|
585
|
+
span.setAttribute("db.result.uploaded", result.uploaded);
|
|
586
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
587
|
+
return result;
|
|
588
|
+
} catch (error) {
|
|
589
|
+
span.recordException(error);
|
|
590
|
+
span.setStatus({
|
|
591
|
+
code: SpanStatusCode.ERROR,
|
|
592
|
+
message: error instanceof Error ? error.message : String(error)
|
|
593
|
+
});
|
|
594
|
+
throw error;
|
|
595
|
+
} finally {
|
|
596
|
+
span.end();
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
} });
|
|
600
|
+
if (prop === "delete" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
601
|
+
const keys = args;
|
|
602
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`R2 ${name}: delete`, {
|
|
603
|
+
kind: SpanKind.CLIENT,
|
|
604
|
+
attributes: {
|
|
605
|
+
"db.system": "cloudflare-r2",
|
|
606
|
+
"db.operation": "delete",
|
|
607
|
+
"db.bucket": name,
|
|
608
|
+
"db.keys_count": keys.length
|
|
609
|
+
}
|
|
610
|
+
}, async (span) => {
|
|
611
|
+
try {
|
|
612
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
613
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
614
|
+
return result;
|
|
615
|
+
} catch (error) {
|
|
616
|
+
span.recordException(error);
|
|
617
|
+
span.setStatus({
|
|
618
|
+
code: SpanStatusCode.ERROR,
|
|
619
|
+
message: error instanceof Error ? error.message : String(error)
|
|
620
|
+
});
|
|
621
|
+
throw error;
|
|
622
|
+
} finally {
|
|
623
|
+
span.end();
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
} });
|
|
627
|
+
if (prop === "list" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
628
|
+
const [options] = args;
|
|
629
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`R2 ${name}: list`, {
|
|
630
|
+
kind: SpanKind.CLIENT,
|
|
631
|
+
attributes: {
|
|
632
|
+
"db.system": "cloudflare-r2",
|
|
633
|
+
"db.operation": "list",
|
|
634
|
+
"db.bucket": name,
|
|
635
|
+
"db.prefix": options?.prefix || void 0,
|
|
636
|
+
"db.limit": options?.limit || void 0
|
|
637
|
+
}
|
|
638
|
+
}, async (span) => {
|
|
639
|
+
try {
|
|
640
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
641
|
+
span.setAttribute("db.result.objects_count", result.objects.length);
|
|
642
|
+
span.setAttribute("db.result.truncated", result.truncated);
|
|
643
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
644
|
+
return result;
|
|
645
|
+
} catch (error) {
|
|
646
|
+
span.recordException(error);
|
|
647
|
+
span.setStatus({
|
|
648
|
+
code: SpanStatusCode.ERROR,
|
|
649
|
+
message: error instanceof Error ? error.message : String(error)
|
|
650
|
+
});
|
|
651
|
+
throw error;
|
|
652
|
+
} finally {
|
|
653
|
+
span.end();
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
} });
|
|
657
|
+
return value;
|
|
658
|
+
} });
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Instrument D1 database
|
|
662
|
+
*/
|
|
663
|
+
function instrumentD1(d1, databaseName) {
|
|
664
|
+
const name = databaseName || "d1";
|
|
665
|
+
return wrap(d1, { get(target, prop) {
|
|
666
|
+
const value = Reflect.get(target, prop);
|
|
667
|
+
if (prop === "prepare" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
668
|
+
const [query] = args;
|
|
669
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
670
|
+
return wrap(Reflect.apply(fnTarget, target, args), { get(target, prop) {
|
|
671
|
+
const value = Reflect.get(target, prop);
|
|
672
|
+
if (prop === "first" || prop === "run" || prop === "all" || prop === "raw") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
673
|
+
const statement = sanitizeStatement(query, getActiveConfig()?.dataSafety?.captureDbStatement ?? "full");
|
|
674
|
+
const attributes = {
|
|
675
|
+
"db.system": "cloudflare-d1",
|
|
676
|
+
"db.operation": prop,
|
|
677
|
+
"db.name": name
|
|
678
|
+
};
|
|
679
|
+
if (statement !== void 0) attributes["db.statement"] = statement;
|
|
680
|
+
return tracer.startActiveSpan(`D1 ${name}: ${prop}`, {
|
|
681
|
+
kind: SpanKind.CLIENT,
|
|
682
|
+
attributes
|
|
683
|
+
}, async (span) => {
|
|
684
|
+
try {
|
|
685
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
686
|
+
if (prop === "all" && Array.isArray(result)) span.setAttribute("db.result.rows_count", result.length);
|
|
687
|
+
else if (prop === "first" && result) span.setAttribute("db.result.exists", true);
|
|
688
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
689
|
+
return result;
|
|
690
|
+
} catch (error) {
|
|
691
|
+
span.recordException(error);
|
|
692
|
+
span.setStatus({
|
|
693
|
+
code: SpanStatusCode.ERROR,
|
|
694
|
+
message: error instanceof Error ? error.message : String(error)
|
|
695
|
+
});
|
|
696
|
+
throw error;
|
|
697
|
+
} finally {
|
|
698
|
+
span.end();
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
} });
|
|
702
|
+
return value;
|
|
703
|
+
} });
|
|
704
|
+
} });
|
|
705
|
+
if (prop === "exec" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
706
|
+
const [query] = args;
|
|
707
|
+
const tracer = trace.getTracer("autotel-edge");
|
|
708
|
+
const statement = sanitizeStatement(query, getActiveConfig()?.dataSafety?.captureDbStatement ?? "full");
|
|
709
|
+
const attributes = {
|
|
710
|
+
"db.system": "cloudflare-d1",
|
|
711
|
+
"db.operation": "exec",
|
|
712
|
+
"db.name": name
|
|
713
|
+
};
|
|
714
|
+
if (statement !== void 0) attributes["db.statement"] = statement;
|
|
715
|
+
return tracer.startActiveSpan(`D1 ${name}: exec`, {
|
|
716
|
+
kind: SpanKind.CLIENT,
|
|
717
|
+
attributes
|
|
718
|
+
}, async (span) => {
|
|
719
|
+
try {
|
|
720
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
721
|
+
span.setAttribute("db.result.count", result.count);
|
|
722
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
723
|
+
return result;
|
|
724
|
+
} catch (error) {
|
|
725
|
+
span.recordException(error);
|
|
726
|
+
span.setStatus({
|
|
727
|
+
code: SpanStatusCode.ERROR,
|
|
728
|
+
message: error instanceof Error ? error.message : String(error)
|
|
729
|
+
});
|
|
730
|
+
throw error;
|
|
731
|
+
} finally {
|
|
732
|
+
span.end();
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
} });
|
|
736
|
+
return value;
|
|
737
|
+
} });
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Instrument service binding (Fetcher)
|
|
741
|
+
*
|
|
742
|
+
* Unlike other bindings, Fetcher objects are native Cloudflare C++ bindings
|
|
743
|
+
* whose methods throw "Illegal invocation" when called through a Proxy with
|
|
744
|
+
* a different `this` reference. We work around this by calling `target.fetch()`
|
|
745
|
+
* directly on the original binding instead of using `Reflect.apply` on a
|
|
746
|
+
* detached function reference.
|
|
747
|
+
*/
|
|
748
|
+
function instrumentServiceBinding(fetcher, serviceName) {
|
|
749
|
+
const name = serviceName || "service";
|
|
750
|
+
return wrap(fetcher, { get(target, prop) {
|
|
751
|
+
if (prop === "fetch" && typeof target.fetch === "function") {
|
|
752
|
+
const tracedFetch = (...args) => {
|
|
753
|
+
const [input, init] = args;
|
|
754
|
+
const request = new Request(input, init);
|
|
755
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`Service ${name}: ${request.method}`, {
|
|
756
|
+
kind: SpanKind.CLIENT,
|
|
757
|
+
attributes: {
|
|
758
|
+
"rpc.system": "cloudflare-service-binding",
|
|
759
|
+
"rpc.service": name,
|
|
760
|
+
"http.request.method": request.method,
|
|
761
|
+
"url.full": request.url
|
|
762
|
+
}
|
|
763
|
+
}, async (span) => {
|
|
764
|
+
try {
|
|
765
|
+
const response = await target.fetch(input, init);
|
|
766
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
767
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
768
|
+
return response;
|
|
769
|
+
} catch (error) {
|
|
770
|
+
span.recordException(error);
|
|
771
|
+
span.setStatus({
|
|
772
|
+
code: SpanStatusCode.ERROR,
|
|
773
|
+
message: error instanceof Error ? error.message : String(error)
|
|
774
|
+
});
|
|
775
|
+
throw error;
|
|
776
|
+
} finally {
|
|
777
|
+
span.end();
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
};
|
|
781
|
+
return tracedFetch;
|
|
782
|
+
}
|
|
783
|
+
const value = Reflect.get(target, prop);
|
|
784
|
+
if (typeof value === "function") return value.bind(target);
|
|
785
|
+
return value;
|
|
786
|
+
} });
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Detection helpers
|
|
790
|
+
*/
|
|
791
|
+
const hasMethod = (obj, m) => typeof obj?.[m] === "function";
|
|
792
|
+
const hasExactMethods = (obj, methods) => methods.every((m) => hasMethod(obj, m));
|
|
793
|
+
/**
|
|
794
|
+
* Auto-instrument all Cloudflare bindings in the environment
|
|
795
|
+
*
|
|
796
|
+
* Detection order (most specific first):
|
|
797
|
+
* 1. R2 — get, put, delete, list, head
|
|
798
|
+
* 2. KV — get, put, delete, list (not head)
|
|
799
|
+
* 3. D1 — prepare, exec
|
|
800
|
+
* 4. Vectorize — query, insert, upsert, describe
|
|
801
|
+
* 5. AI — run + (gateway or models discriminator)
|
|
802
|
+
* 6. Hyperdrive — connect + connectionString + host
|
|
803
|
+
* 7. Queue Producer — send, sendBatch (not get)
|
|
804
|
+
* 8. Analytics Engine — writeDataPoint
|
|
805
|
+
* 9. Images — info, input
|
|
806
|
+
* 10. Service Binding — fetch (broadest, must be last)
|
|
807
|
+
*
|
|
808
|
+
* Not auto-detected (manual only):
|
|
809
|
+
* - Rate Limiter — limit() alone too generic
|
|
810
|
+
* - Browser Rendering — indistinguishable from Service Binding
|
|
811
|
+
*/
|
|
812
|
+
const envCache = /* @__PURE__ */ new WeakMap();
|
|
813
|
+
function instrumentBindings(env) {
|
|
814
|
+
const cached = envCache.get(env);
|
|
815
|
+
if (cached) return cached;
|
|
816
|
+
const instrumented = {};
|
|
817
|
+
for (const [key, value] of Object.entries(env)) {
|
|
818
|
+
if (!value || typeof value !== "object") {
|
|
819
|
+
instrumented[key] = value;
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
if (isWrapped(value)) {
|
|
823
|
+
instrumented[key] = value;
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
if (hasExactMethods(value, [
|
|
827
|
+
"get",
|
|
828
|
+
"put",
|
|
829
|
+
"delete",
|
|
830
|
+
"list",
|
|
831
|
+
"head"
|
|
832
|
+
])) {
|
|
833
|
+
instrumented[key] = instrumentR2(value, key);
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
if (hasExactMethods(value, [
|
|
837
|
+
"get",
|
|
838
|
+
"put",
|
|
839
|
+
"delete",
|
|
840
|
+
"list"
|
|
841
|
+
]) && !("head" in value)) {
|
|
842
|
+
instrumented[key] = instrumentKV(value, key);
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
if (hasExactMethods(value, ["prepare", "exec"])) {
|
|
846
|
+
instrumented[key] = instrumentD1(value, key);
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
if (hasExactMethods(value, [
|
|
850
|
+
"query",
|
|
851
|
+
"insert",
|
|
852
|
+
"upsert",
|
|
853
|
+
"describe"
|
|
854
|
+
])) {
|
|
855
|
+
instrumented[key] = instrumentVectorize(value, key);
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
858
|
+
if (hasMethod(value, "run") && ("gateway" in value || "models" in value)) {
|
|
859
|
+
instrumented[key] = instrumentAI(value, key);
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
862
|
+
if (hasMethod(value, "connect") && "connectionString" in value && "host" in value) {
|
|
863
|
+
instrumented[key] = instrumentHyperdrive(value, key);
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (hasExactMethods(value, ["send", "sendBatch"]) && !("get" in value)) {
|
|
867
|
+
instrumented[key] = instrumentQueueProducer(value, key);
|
|
868
|
+
continue;
|
|
869
|
+
}
|
|
870
|
+
if (hasMethod(value, "writeDataPoint")) {
|
|
871
|
+
instrumented[key] = instrumentAnalyticsEngine(value, key);
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
if (hasExactMethods(value, ["info", "input"])) {
|
|
875
|
+
instrumented[key] = instrumentImages(value, key);
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
if (hasMethod(value, "fetch")) {
|
|
879
|
+
instrumented[key] = instrumentServiceBinding(value, key);
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
instrumented[key] = value;
|
|
883
|
+
}
|
|
884
|
+
envCache.set(env, instrumented);
|
|
885
|
+
return instrumented;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
//#endregion
|
|
889
|
+
//#region src/bindings/rate-limiter.ts
|
|
890
|
+
/**
|
|
891
|
+
* Rate Limiter binding instrumentation
|
|
892
|
+
*/
|
|
893
|
+
/**
|
|
894
|
+
* Instrument Rate Limiter binding (manual only — not auto-detected)
|
|
895
|
+
*/
|
|
896
|
+
function instrumentRateLimiter(limiter, bindingName) {
|
|
897
|
+
const name = bindingName || "rate-limiter";
|
|
898
|
+
return wrap(limiter, { get(target, prop) {
|
|
899
|
+
const value = Reflect.get(target, prop);
|
|
900
|
+
if (prop === "limit" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
901
|
+
const [options] = args;
|
|
902
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`RateLimiter ${name}: limit`, {
|
|
903
|
+
kind: SpanKind.CLIENT,
|
|
904
|
+
attributes: {
|
|
905
|
+
"rate_limiter.system": "cloudflare-rate-limiter",
|
|
906
|
+
"rate_limiter.key": options?.key
|
|
907
|
+
}
|
|
908
|
+
}, async (span) => {
|
|
909
|
+
try {
|
|
910
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
911
|
+
setAttr(span, "rate_limiter.success", result?.success);
|
|
912
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
913
|
+
return result;
|
|
914
|
+
} catch (error) {
|
|
915
|
+
span.recordException(error);
|
|
916
|
+
span.setStatus({
|
|
917
|
+
code: SpanStatusCode.ERROR,
|
|
918
|
+
message: error instanceof Error ? error.message : String(error)
|
|
919
|
+
});
|
|
920
|
+
throw error;
|
|
921
|
+
} finally {
|
|
922
|
+
span.end();
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
} });
|
|
926
|
+
return value;
|
|
927
|
+
} });
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
//#endregion
|
|
931
|
+
//#region src/bindings/browser-rendering.ts
|
|
932
|
+
/**
|
|
933
|
+
* Browser Rendering binding instrumentation
|
|
934
|
+
*/
|
|
935
|
+
/**
|
|
936
|
+
* Instrument Browser Rendering binding (manual only — not auto-detected)
|
|
937
|
+
*/
|
|
938
|
+
function instrumentBrowserRendering(browser, bindingName) {
|
|
939
|
+
const name = bindingName || "browser";
|
|
940
|
+
return wrap(browser, { get(target, prop) {
|
|
941
|
+
const value = Reflect.get(target, prop);
|
|
942
|
+
if (prop === "fetch" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
|
|
943
|
+
const [input] = args;
|
|
944
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
945
|
+
return trace.getTracer("autotel-edge").startActiveSpan(`BrowserRendering ${name}: fetch`, {
|
|
946
|
+
kind: SpanKind.CLIENT,
|
|
947
|
+
attributes: {
|
|
948
|
+
"browser.system": "cloudflare-browser-rendering",
|
|
949
|
+
"url.full": url
|
|
950
|
+
}
|
|
951
|
+
}, async (span) => {
|
|
952
|
+
try {
|
|
953
|
+
const result = await Reflect.apply(fnTarget, target, args);
|
|
954
|
+
setAttr(span, "http.response.status_code", result?.status);
|
|
955
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
956
|
+
return result;
|
|
957
|
+
} catch (error) {
|
|
958
|
+
span.recordException(error);
|
|
959
|
+
span.setStatus({
|
|
960
|
+
code: SpanStatusCode.ERROR,
|
|
961
|
+
message: error instanceof Error ? error.message : String(error)
|
|
962
|
+
});
|
|
963
|
+
throw error;
|
|
964
|
+
} finally {
|
|
965
|
+
span.end();
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
} });
|
|
969
|
+
return value;
|
|
970
|
+
} });
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
//#endregion
|
|
974
|
+
export { instrumentKV as a, instrumentImages as c, instrumentHyperdrive as d, instrumentVectorize as f, instrumentD1 as i, instrumentAnalyticsEngine as l, instrumentRateLimiter as n, instrumentR2 as o, instrumentAI as p, instrumentBindings as r, instrumentServiceBinding as s, instrumentBrowserRendering as t, instrumentQueueProducer as u };
|
|
975
|
+
//# sourceMappingURL=bindings-C10RI6Il.js.map
|