autotel-cloudflare 6.0.2 → 9.0.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/README.md +1 -1
- package/dist/actors.d.ts +15 -2
- package/dist/actors.js +95 -93
- package/dist/agents.d.ts +2 -1
- package/dist/agents.js +20 -28
- package/dist/{bindings-xEZcXo5r.d.ts → bindings-BcSPZDWF.d.ts} +5 -20
- package/dist/{bindings-DznsCwCn.js → bindings-s6W9szMm.js} +199 -154
- package/dist/bindings.d.ts +1 -1
- package/dist/bindings.js +1 -1
- package/dist/{common-DiWH6nmG.js → exception-D3xOCdBW.js} +11 -2
- package/dist/{execution-logger-BxmgP8jF.js → execution-logger-6IZS5fEz.js} +2 -1
- package/dist/{handlers-BePc7OJU.js → handlers-avm65CVU.js} +37 -34
- package/dist/handlers.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +60 -62
- package/dist/logger.js +1 -1
- package/dist/tracer-z8zwRBVS.js +10 -0
- package/dist/values-BC6rdpGG.js +108 -0
- package/dist/values-CRvW9g6_.d.ts +19 -0
- package/package.json +5 -5
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { _ as trapArgs, a as asRecord, c as asString, d as hasMethods, f as member, g as readProperty, h as readPath, i as asNumber, m as numberAt, n as asBoolean, r as asFunction, u as hasMethod } from "./values-BC6rdpGG.js";
|
|
2
|
+
import { i as setAttr, n as isWrapped, o as wrap, t as toException } from "./exception-D3xOCdBW.js";
|
|
3
|
+
import { t as workerTracer } from "./tracer-z8zwRBVS.js";
|
|
2
4
|
import { getActiveConfig } from "autotel-edge";
|
|
3
|
-
import { SpanKind, SpanStatusCode
|
|
5
|
+
import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
|
|
4
6
|
|
|
5
7
|
//#region src/bindings/ai.ts
|
|
6
8
|
/**
|
|
@@ -12,10 +14,11 @@ import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
|
12
14
|
function instrumentAI(ai, bindingName) {
|
|
13
15
|
const name = bindingName || "ai";
|
|
14
16
|
return wrap(ai, { get(target, prop) {
|
|
15
|
-
const value =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const value = member(target, prop);
|
|
18
|
+
const method = asFunction(value);
|
|
19
|
+
if (prop === "run" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
20
|
+
const [model] = trapArgs(args);
|
|
21
|
+
return workerTracer("autotel-edge").startActiveSpan(`AI ${name}: run ${model}`, {
|
|
19
22
|
kind: SpanKind.CLIENT,
|
|
20
23
|
attributes: {
|
|
21
24
|
"gen_ai.provider.name": "cloudflare-workers-ai",
|
|
@@ -24,13 +27,15 @@ function instrumentAI(ai, bindingName) {
|
|
|
24
27
|
}
|
|
25
28
|
}, async (span) => {
|
|
26
29
|
try {
|
|
27
|
-
const result = await
|
|
28
|
-
|
|
29
|
-
if (
|
|
30
|
+
const result = await fnTarget.apply(target, args);
|
|
31
|
+
const inputTokens = numberAt(result, "usage", "prompt_tokens");
|
|
32
|
+
if (inputTokens !== void 0) setAttr(span, "gen_ai.usage.input_tokens", inputTokens);
|
|
33
|
+
const outputTokens = numberAt(result, "usage", "completion_tokens");
|
|
34
|
+
if (outputTokens !== void 0) setAttr(span, "gen_ai.usage.output_tokens", outputTokens);
|
|
30
35
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
31
36
|
return result;
|
|
32
37
|
} catch (error) {
|
|
33
|
-
span.recordException(error);
|
|
38
|
+
span.recordException(toException(error));
|
|
34
39
|
span.setStatus({
|
|
35
40
|
code: SpanStatusCode.ERROR,
|
|
36
41
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -64,10 +69,11 @@ const TRACED_METHODS = [
|
|
|
64
69
|
function instrumentVectorize(vectorize, indexName) {
|
|
65
70
|
const name = indexName || "vectorize";
|
|
66
71
|
return wrap(vectorize, { get(target, prop) {
|
|
67
|
-
const value =
|
|
68
|
-
|
|
72
|
+
const value = member(target, prop);
|
|
73
|
+
const method = asFunction(value);
|
|
74
|
+
if (typeof prop === "string" && TRACED_METHODS.includes(prop) && method !== void 0) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
69
75
|
const operation = prop;
|
|
70
|
-
const tracer =
|
|
76
|
+
const tracer = workerTracer("autotel-edge");
|
|
71
77
|
const attributes = {
|
|
72
78
|
"db.system": "cloudflare-vectorize",
|
|
73
79
|
"db.operation": operation,
|
|
@@ -83,12 +89,13 @@ function instrumentVectorize(vectorize, indexName) {
|
|
|
83
89
|
attributes
|
|
84
90
|
}, async (span) => {
|
|
85
91
|
try {
|
|
86
|
-
const result = await
|
|
87
|
-
|
|
92
|
+
const result = await fnTarget.apply(target, args);
|
|
93
|
+
const matches = readProperty(result, "matches");
|
|
94
|
+
if (operation === "query" && Array.isArray(matches)) setAttr(span, "db.vectorize.matches_count", matches.length);
|
|
88
95
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
89
96
|
return result;
|
|
90
97
|
} catch (error) {
|
|
91
|
-
span.recordException(error);
|
|
98
|
+
span.recordException(toException(error));
|
|
92
99
|
span.setStatus({
|
|
93
100
|
code: SpanStatusCode.ERROR,
|
|
94
101
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -114,9 +121,10 @@ function instrumentVectorize(vectorize, indexName) {
|
|
|
114
121
|
function instrumentHyperdrive(hyperdrive, bindingName) {
|
|
115
122
|
const name = bindingName || "hyperdrive";
|
|
116
123
|
return wrap(hyperdrive, { get(target, prop) {
|
|
117
|
-
const value =
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
const value = member(target, prop);
|
|
125
|
+
const method = asFunction(value);
|
|
126
|
+
if (prop === "connect" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
127
|
+
const tracer = workerTracer("autotel-edge");
|
|
120
128
|
const attributes = {
|
|
121
129
|
"db.system": "cloudflare-hyperdrive",
|
|
122
130
|
"db.operation": "connect"
|
|
@@ -137,11 +145,11 @@ function instrumentHyperdrive(hyperdrive, bindingName) {
|
|
|
137
145
|
attributes
|
|
138
146
|
}, async (span) => {
|
|
139
147
|
try {
|
|
140
|
-
const result = await
|
|
148
|
+
const result = await fnTarget.apply(target, args);
|
|
141
149
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
142
150
|
return result;
|
|
143
151
|
} catch (error) {
|
|
144
|
-
span.recordException(error);
|
|
152
|
+
span.recordException(toException(error));
|
|
145
153
|
span.setStatus({
|
|
146
154
|
code: SpanStatusCode.ERROR,
|
|
147
155
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -167,9 +175,10 @@ function instrumentHyperdrive(hyperdrive, bindingName) {
|
|
|
167
175
|
function instrumentQueueProducer(queue, queueName) {
|
|
168
176
|
const name = queueName || "queue";
|
|
169
177
|
return wrap(queue, { get(target, prop) {
|
|
170
|
-
const value =
|
|
171
|
-
|
|
172
|
-
|
|
178
|
+
const value = member(target, prop);
|
|
179
|
+
const method = asFunction(value);
|
|
180
|
+
if (prop === "send" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
181
|
+
return workerTracer("autotel-edge").startActiveSpan(`Queue ${name}: send`, {
|
|
173
182
|
kind: SpanKind.PRODUCER,
|
|
174
183
|
attributes: {
|
|
175
184
|
"messaging.system": "cloudflare-queues",
|
|
@@ -179,12 +188,12 @@ function instrumentQueueProducer(queue, queueName) {
|
|
|
179
188
|
}
|
|
180
189
|
}, async (span) => {
|
|
181
190
|
try {
|
|
182
|
-
const result = await
|
|
191
|
+
const result = await fnTarget.apply(target, args);
|
|
183
192
|
setAttr(span, "messaging.message.id", result?.messageId);
|
|
184
193
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
185
194
|
return result;
|
|
186
195
|
} catch (error) {
|
|
187
|
-
span.recordException(error);
|
|
196
|
+
span.recordException(toException(error));
|
|
188
197
|
span.setStatus({
|
|
189
198
|
code: SpanStatusCode.ERROR,
|
|
190
199
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -195,9 +204,9 @@ function instrumentQueueProducer(queue, queueName) {
|
|
|
195
204
|
}
|
|
196
205
|
});
|
|
197
206
|
} });
|
|
198
|
-
if (prop === "sendBatch" &&
|
|
199
|
-
const [messages] = args;
|
|
200
|
-
return
|
|
207
|
+
if (prop === "sendBatch" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
208
|
+
const [messages] = trapArgs(args);
|
|
209
|
+
return workerTracer("autotel-edge").startActiveSpan(`Queue ${name}: sendBatch`, {
|
|
201
210
|
kind: SpanKind.PRODUCER,
|
|
202
211
|
attributes: {
|
|
203
212
|
"messaging.system": "cloudflare-queues",
|
|
@@ -208,11 +217,11 @@ function instrumentQueueProducer(queue, queueName) {
|
|
|
208
217
|
}
|
|
209
218
|
}, async (span) => {
|
|
210
219
|
try {
|
|
211
|
-
const result = await
|
|
220
|
+
const result = await fnTarget.apply(target, args);
|
|
212
221
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
213
222
|
return result;
|
|
214
223
|
} catch (error) {
|
|
215
|
-
span.recordException(error);
|
|
224
|
+
span.recordException(toException(error));
|
|
216
225
|
span.setStatus({
|
|
217
226
|
code: SpanStatusCode.ERROR,
|
|
218
227
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -238,10 +247,11 @@ function instrumentQueueProducer(queue, queueName) {
|
|
|
238
247
|
function instrumentAnalyticsEngine(ae, datasetName) {
|
|
239
248
|
const name = datasetName || "analytics-engine";
|
|
240
249
|
return wrap(ae, { get(target, prop) {
|
|
241
|
-
const value =
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const
|
|
250
|
+
const value = member(target, prop);
|
|
251
|
+
const method = asFunction(value);
|
|
252
|
+
if (prop === "writeDataPoint" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
253
|
+
const [dataPoint] = trapArgs(args);
|
|
254
|
+
const tracer = workerTracer("autotel-edge");
|
|
245
255
|
const attributes = {
|
|
246
256
|
"analytics.system": "cloudflare-analytics-engine",
|
|
247
257
|
"analytics.operation": "writeDataPoint"
|
|
@@ -256,10 +266,10 @@ function instrumentAnalyticsEngine(ae, datasetName) {
|
|
|
256
266
|
attributes
|
|
257
267
|
}, (span) => {
|
|
258
268
|
try {
|
|
259
|
-
|
|
269
|
+
fnTarget.apply(target, args);
|
|
260
270
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
261
271
|
} catch (error) {
|
|
262
|
-
span.recordException(error);
|
|
272
|
+
span.recordException(toException(error));
|
|
263
273
|
span.setStatus({
|
|
264
274
|
code: SpanStatusCode.ERROR,
|
|
265
275
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -286,15 +296,16 @@ function instrumentAnalyticsEngine(ae, datasetName) {
|
|
|
286
296
|
const pipelineMetaSymbol = Symbol("images-pipeline-meta");
|
|
287
297
|
function proxyTransformer(transformer, meta, bindingName) {
|
|
288
298
|
const proxy = new Proxy(transformer, { get(target, prop) {
|
|
289
|
-
const value =
|
|
290
|
-
|
|
299
|
+
const value = member(target, prop);
|
|
300
|
+
const method = asFunction(value);
|
|
301
|
+
if ((prop === "transform" || prop === "draw") && method !== void 0) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
291
302
|
meta.operationCount++;
|
|
292
|
-
const result =
|
|
303
|
+
const result = fnTarget.apply(target, args);
|
|
293
304
|
if (result === target || result && typeof result === "object" && "output" in result) return proxyTransformer(result, meta, bindingName);
|
|
294
305
|
return result;
|
|
295
306
|
} });
|
|
296
|
-
if (prop === "output" &&
|
|
297
|
-
const tracer =
|
|
307
|
+
if (prop === "output" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
308
|
+
const tracer = workerTracer("autotel-edge");
|
|
298
309
|
const [formatOrOptions] = args;
|
|
299
310
|
const attributes = {
|
|
300
311
|
"images.system": "cloudflare-images",
|
|
@@ -310,11 +321,11 @@ function proxyTransformer(transformer, meta, bindingName) {
|
|
|
310
321
|
attributes
|
|
311
322
|
}, async (span) => {
|
|
312
323
|
try {
|
|
313
|
-
const result = await
|
|
324
|
+
const result = await fnTarget.apply(target, args);
|
|
314
325
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
315
326
|
return result;
|
|
316
327
|
} catch (error) {
|
|
317
|
-
span.recordException(error);
|
|
328
|
+
span.recordException(toException(error));
|
|
318
329
|
span.setStatus({
|
|
319
330
|
code: SpanStatusCode.ERROR,
|
|
320
331
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -341,9 +352,10 @@ function proxyTransformer(transformer, meta, bindingName) {
|
|
|
341
352
|
function instrumentImages(images, bindingName) {
|
|
342
353
|
const name = bindingName || "images";
|
|
343
354
|
return wrap(images, { get(target, prop) {
|
|
344
|
-
const value =
|
|
345
|
-
|
|
346
|
-
|
|
355
|
+
const value = member(target, prop);
|
|
356
|
+
const method = asFunction(value);
|
|
357
|
+
if (prop === "info" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
358
|
+
return workerTracer("autotel-edge").startActiveSpan(`Images ${name}: info`, {
|
|
347
359
|
kind: SpanKind.CLIENT,
|
|
348
360
|
attributes: {
|
|
349
361
|
"images.system": "cloudflare-images",
|
|
@@ -351,14 +363,14 @@ function instrumentImages(images, bindingName) {
|
|
|
351
363
|
}
|
|
352
364
|
}, async (span) => {
|
|
353
365
|
try {
|
|
354
|
-
const result = await
|
|
355
|
-
setAttr(span, "images.width", result
|
|
356
|
-
setAttr(span, "images.height", result
|
|
357
|
-
setAttr(span, "images.format", result
|
|
366
|
+
const result = await fnTarget.apply(target, args);
|
|
367
|
+
setAttr(span, "images.width", numberAt(result, "width"));
|
|
368
|
+
setAttr(span, "images.height", numberAt(result, "height"));
|
|
369
|
+
setAttr(span, "images.format", asString(readProperty(result, "format")));
|
|
358
370
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
359
371
|
return result;
|
|
360
372
|
} catch (error) {
|
|
361
|
-
span.recordException(error);
|
|
373
|
+
span.recordException(toException(error));
|
|
362
374
|
span.setStatus({
|
|
363
375
|
code: SpanStatusCode.ERROR,
|
|
364
376
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -369,8 +381,8 @@ function instrumentImages(images, bindingName) {
|
|
|
369
381
|
}
|
|
370
382
|
});
|
|
371
383
|
} });
|
|
372
|
-
if (prop === "input" &&
|
|
373
|
-
return proxyTransformer(
|
|
384
|
+
if (prop === "input" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
385
|
+
return proxyTransformer(fnTarget.apply(target, args), { operationCount: 0 }, name);
|
|
374
386
|
} });
|
|
375
387
|
return value;
|
|
376
388
|
} });
|
|
@@ -413,10 +425,11 @@ function sanitizeStatement(query, mode) {
|
|
|
413
425
|
function instrumentKV(kv, namespaceName) {
|
|
414
426
|
const name = namespaceName || "kv";
|
|
415
427
|
return wrap(kv, { get(target, prop) {
|
|
416
|
-
const value =
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
428
|
+
const value = member(target, prop);
|
|
429
|
+
const method = asFunction(value);
|
|
430
|
+
if (prop === "get" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
431
|
+
const [key, options] = trapArgs(args);
|
|
432
|
+
return workerTracer("autotel-edge").startActiveSpan(`KV ${name}: get`, {
|
|
420
433
|
kind: SpanKind.CLIENT,
|
|
421
434
|
attributes: {
|
|
422
435
|
"db.system": "cloudflare-kv",
|
|
@@ -427,12 +440,12 @@ function instrumentKV(kv, namespaceName) {
|
|
|
427
440
|
}
|
|
428
441
|
}, async (span) => {
|
|
429
442
|
try {
|
|
430
|
-
const result = await
|
|
443
|
+
const result = await fnTarget.apply(target, args);
|
|
431
444
|
span.setAttribute("db.result.type", result === null ? "null" : typeof result);
|
|
432
445
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
433
446
|
return result;
|
|
434
447
|
} catch (error) {
|
|
435
|
-
span.recordException(error);
|
|
448
|
+
span.recordException(toException(error));
|
|
436
449
|
span.setStatus({
|
|
437
450
|
code: SpanStatusCode.ERROR,
|
|
438
451
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -443,9 +456,9 @@ function instrumentKV(kv, namespaceName) {
|
|
|
443
456
|
}
|
|
444
457
|
});
|
|
445
458
|
} });
|
|
446
|
-
if (prop === "put" &&
|
|
447
|
-
const [key] = args;
|
|
448
|
-
return
|
|
459
|
+
if (prop === "put" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
460
|
+
const [key] = trapArgs(args);
|
|
461
|
+
return workerTracer("autotel-edge").startActiveSpan(`KV ${name}: put`, {
|
|
449
462
|
kind: SpanKind.CLIENT,
|
|
450
463
|
attributes: {
|
|
451
464
|
"db.system": "cloudflare-kv",
|
|
@@ -455,11 +468,11 @@ function instrumentKV(kv, namespaceName) {
|
|
|
455
468
|
}
|
|
456
469
|
}, async (span) => {
|
|
457
470
|
try {
|
|
458
|
-
const result = await
|
|
471
|
+
const result = await fnTarget.apply(target, args);
|
|
459
472
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
460
473
|
return result;
|
|
461
474
|
} catch (error) {
|
|
462
|
-
span.recordException(error);
|
|
475
|
+
span.recordException(toException(error));
|
|
463
476
|
span.setStatus({
|
|
464
477
|
code: SpanStatusCode.ERROR,
|
|
465
478
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -470,9 +483,9 @@ function instrumentKV(kv, namespaceName) {
|
|
|
470
483
|
}
|
|
471
484
|
});
|
|
472
485
|
} });
|
|
473
|
-
if (prop === "delete" &&
|
|
474
|
-
const [key] = args;
|
|
475
|
-
return
|
|
486
|
+
if (prop === "delete" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
487
|
+
const [key] = trapArgs(args);
|
|
488
|
+
return workerTracer("autotel-edge").startActiveSpan(`KV ${name}: delete`, {
|
|
476
489
|
kind: SpanKind.CLIENT,
|
|
477
490
|
attributes: {
|
|
478
491
|
"db.system": "cloudflare-kv",
|
|
@@ -482,11 +495,11 @@ function instrumentKV(kv, namespaceName) {
|
|
|
482
495
|
}
|
|
483
496
|
}, async (span) => {
|
|
484
497
|
try {
|
|
485
|
-
const result = await
|
|
498
|
+
const result = await fnTarget.apply(target, args);
|
|
486
499
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
487
500
|
return result;
|
|
488
501
|
} catch (error) {
|
|
489
|
-
span.recordException(error);
|
|
502
|
+
span.recordException(toException(error));
|
|
490
503
|
span.setStatus({
|
|
491
504
|
code: SpanStatusCode.ERROR,
|
|
492
505
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -497,9 +510,9 @@ function instrumentKV(kv, namespaceName) {
|
|
|
497
510
|
}
|
|
498
511
|
});
|
|
499
512
|
} });
|
|
500
|
-
if (prop === "list" &&
|
|
501
|
-
const [options] = args;
|
|
502
|
-
return
|
|
513
|
+
if (prop === "list" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
514
|
+
const [options] = trapArgs(args);
|
|
515
|
+
return workerTracer("autotel-edge").startActiveSpan(`KV ${name}: list`, {
|
|
503
516
|
kind: SpanKind.CLIENT,
|
|
504
517
|
attributes: {
|
|
505
518
|
"db.system": "cloudflare-kv",
|
|
@@ -510,12 +523,13 @@ function instrumentKV(kv, namespaceName) {
|
|
|
510
523
|
}
|
|
511
524
|
}, async (span) => {
|
|
512
525
|
try {
|
|
513
|
-
const result = await
|
|
514
|
-
|
|
526
|
+
const result = await fnTarget.apply(target, args);
|
|
527
|
+
const keys = readProperty(result, "keys");
|
|
528
|
+
if (Array.isArray(keys)) span.setAttribute("db.result.keys_count", keys.length);
|
|
515
529
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
516
530
|
return result;
|
|
517
531
|
} catch (error) {
|
|
518
|
-
span.recordException(error);
|
|
532
|
+
span.recordException(toException(error));
|
|
519
533
|
span.setStatus({
|
|
520
534
|
code: SpanStatusCode.ERROR,
|
|
521
535
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -535,10 +549,11 @@ function instrumentKV(kv, namespaceName) {
|
|
|
535
549
|
function instrumentR2(r2, bucketName) {
|
|
536
550
|
const name = bucketName || "r2";
|
|
537
551
|
return wrap(r2, { get(target, prop) {
|
|
538
|
-
const value =
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
552
|
+
const value = member(target, prop);
|
|
553
|
+
const method = asFunction(value);
|
|
554
|
+
if (prop === "get" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
555
|
+
const [key] = trapArgs(args);
|
|
556
|
+
return workerTracer("autotel-edge").startActiveSpan(`R2 ${name}: get`, {
|
|
542
557
|
kind: SpanKind.CLIENT,
|
|
543
558
|
attributes: {
|
|
544
559
|
"db.system": "cloudflare-r2",
|
|
@@ -548,16 +563,17 @@ function instrumentR2(r2, bucketName) {
|
|
|
548
563
|
}
|
|
549
564
|
}, async (span) => {
|
|
550
565
|
try {
|
|
551
|
-
const result = await
|
|
566
|
+
const result = await fnTarget.apply(target, args);
|
|
552
567
|
if (result) {
|
|
553
|
-
span
|
|
554
|
-
span
|
|
555
|
-
|
|
568
|
+
setResultAttr(span, "db.result.size", result, "size");
|
|
569
|
+
setResultAttr(span, "db.result.etag", result, "etag");
|
|
570
|
+
const contentType = asString(readPath(result, "httpMetadata", "contentType"));
|
|
571
|
+
if (contentType !== void 0) span.setAttribute("db.result.content_type", contentType);
|
|
556
572
|
} else span.setAttribute("db.result.exists", false);
|
|
557
573
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
558
574
|
return result;
|
|
559
575
|
} catch (error) {
|
|
560
|
-
span.recordException(error);
|
|
576
|
+
span.recordException(toException(error));
|
|
561
577
|
span.setStatus({
|
|
562
578
|
code: SpanStatusCode.ERROR,
|
|
563
579
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -568,9 +584,9 @@ function instrumentR2(r2, bucketName) {
|
|
|
568
584
|
}
|
|
569
585
|
});
|
|
570
586
|
} });
|
|
571
|
-
if (prop === "put" &&
|
|
572
|
-
const [key] = args;
|
|
573
|
-
return
|
|
587
|
+
if (prop === "put" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
588
|
+
const [key] = trapArgs(args);
|
|
589
|
+
return workerTracer("autotel-edge").startActiveSpan(`R2 ${name}: put`, {
|
|
574
590
|
kind: SpanKind.CLIENT,
|
|
575
591
|
attributes: {
|
|
576
592
|
"db.system": "cloudflare-r2",
|
|
@@ -580,13 +596,13 @@ function instrumentR2(r2, bucketName) {
|
|
|
580
596
|
}
|
|
581
597
|
}, async (span) => {
|
|
582
598
|
try {
|
|
583
|
-
const result = await
|
|
584
|
-
span
|
|
585
|
-
span
|
|
599
|
+
const result = await fnTarget.apply(target, args);
|
|
600
|
+
setResultAttr(span, "db.result.etag", result, "etag");
|
|
601
|
+
setResultAttr(span, "db.result.uploaded", result, "uploaded");
|
|
586
602
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
587
603
|
return result;
|
|
588
604
|
} catch (error) {
|
|
589
|
-
span.recordException(error);
|
|
605
|
+
span.recordException(toException(error));
|
|
590
606
|
span.setStatus({
|
|
591
607
|
code: SpanStatusCode.ERROR,
|
|
592
608
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -597,9 +613,9 @@ function instrumentR2(r2, bucketName) {
|
|
|
597
613
|
}
|
|
598
614
|
});
|
|
599
615
|
} });
|
|
600
|
-
if (prop === "delete" &&
|
|
616
|
+
if (prop === "delete" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
601
617
|
const keys = args;
|
|
602
|
-
return
|
|
618
|
+
return workerTracer("autotel-edge").startActiveSpan(`R2 ${name}: delete`, {
|
|
603
619
|
kind: SpanKind.CLIENT,
|
|
604
620
|
attributes: {
|
|
605
621
|
"db.system": "cloudflare-r2",
|
|
@@ -609,11 +625,11 @@ function instrumentR2(r2, bucketName) {
|
|
|
609
625
|
}
|
|
610
626
|
}, async (span) => {
|
|
611
627
|
try {
|
|
612
|
-
const result = await
|
|
628
|
+
const result = await fnTarget.apply(target, args);
|
|
613
629
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
614
630
|
return result;
|
|
615
631
|
} catch (error) {
|
|
616
|
-
span.recordException(error);
|
|
632
|
+
span.recordException(toException(error));
|
|
617
633
|
span.setStatus({
|
|
618
634
|
code: SpanStatusCode.ERROR,
|
|
619
635
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -624,9 +640,9 @@ function instrumentR2(r2, bucketName) {
|
|
|
624
640
|
}
|
|
625
641
|
});
|
|
626
642
|
} });
|
|
627
|
-
if (prop === "list" &&
|
|
628
|
-
const [options] = args;
|
|
629
|
-
return
|
|
643
|
+
if (prop === "list" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
644
|
+
const [options] = trapArgs(args);
|
|
645
|
+
return workerTracer("autotel-edge").startActiveSpan(`R2 ${name}: list`, {
|
|
630
646
|
kind: SpanKind.CLIENT,
|
|
631
647
|
attributes: {
|
|
632
648
|
"db.system": "cloudflare-r2",
|
|
@@ -637,13 +653,14 @@ function instrumentR2(r2, bucketName) {
|
|
|
637
653
|
}
|
|
638
654
|
}, async (span) => {
|
|
639
655
|
try {
|
|
640
|
-
const result = await
|
|
641
|
-
|
|
642
|
-
span.setAttribute("db.result.
|
|
656
|
+
const result = await fnTarget.apply(target, args);
|
|
657
|
+
const objects = readProperty(result, "objects");
|
|
658
|
+
if (Array.isArray(objects)) span.setAttribute("db.result.objects_count", objects.length);
|
|
659
|
+
setResultAttr(span, "db.result.truncated", result, "truncated");
|
|
643
660
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
644
661
|
return result;
|
|
645
662
|
} catch (error) {
|
|
646
|
-
span.recordException(error);
|
|
663
|
+
span.recordException(toException(error));
|
|
647
664
|
span.setStatus({
|
|
648
665
|
code: SpanStatusCode.ERROR,
|
|
649
666
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -663,13 +680,15 @@ function instrumentR2(r2, bucketName) {
|
|
|
663
680
|
function instrumentD1(d1, databaseName) {
|
|
664
681
|
const name = databaseName || "d1";
|
|
665
682
|
return wrap(d1, { get(target, prop) {
|
|
666
|
-
const value =
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
683
|
+
const value = member(target, prop);
|
|
684
|
+
const method = asFunction(value);
|
|
685
|
+
if (prop === "prepare" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
686
|
+
const [query] = trapArgs(args);
|
|
687
|
+
const tracer = workerTracer("autotel-edge");
|
|
688
|
+
return wrap(fnTarget.apply(target, args), { get(target, prop) {
|
|
689
|
+
const value = member(target, prop);
|
|
690
|
+
const method = asFunction(value);
|
|
691
|
+
if (method && (prop === "first" || prop === "run" || prop === "all" || prop === "raw")) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
673
692
|
const captureMode = getActiveConfig()?.dataSafety?.captureDbStatement ?? "full";
|
|
674
693
|
const statement = sanitizeStatement(query, captureMode);
|
|
675
694
|
const attributes = {
|
|
@@ -683,13 +702,13 @@ function instrumentD1(d1, databaseName) {
|
|
|
683
702
|
attributes
|
|
684
703
|
}, async (span) => {
|
|
685
704
|
try {
|
|
686
|
-
const result = await
|
|
705
|
+
const result = await fnTarget.apply(target, args);
|
|
687
706
|
if (prop === "all" && Array.isArray(result)) span.setAttribute("db.result.rows_count", result.length);
|
|
688
707
|
else if (prop === "first" && result) span.setAttribute("db.result.exists", true);
|
|
689
708
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
690
709
|
return result;
|
|
691
710
|
} catch (error) {
|
|
692
|
-
span.recordException(error);
|
|
711
|
+
span.recordException(toException(error));
|
|
693
712
|
span.setStatus({
|
|
694
713
|
code: SpanStatusCode.ERROR,
|
|
695
714
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -703,9 +722,9 @@ function instrumentD1(d1, databaseName) {
|
|
|
703
722
|
return value;
|
|
704
723
|
} });
|
|
705
724
|
} });
|
|
706
|
-
if (prop === "exec" &&
|
|
707
|
-
const [query] = args;
|
|
708
|
-
const tracer =
|
|
725
|
+
if (prop === "exec" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
726
|
+
const [query] = trapArgs(args);
|
|
727
|
+
const tracer = workerTracer("autotel-edge");
|
|
709
728
|
const statement = sanitizeStatement(query, getActiveConfig()?.dataSafety?.captureDbStatement ?? "full");
|
|
710
729
|
const attributes = {
|
|
711
730
|
"db.system": "cloudflare-d1",
|
|
@@ -718,12 +737,13 @@ function instrumentD1(d1, databaseName) {
|
|
|
718
737
|
attributes
|
|
719
738
|
}, async (span) => {
|
|
720
739
|
try {
|
|
721
|
-
const result = await
|
|
722
|
-
|
|
740
|
+
const result = await fnTarget.apply(target, args);
|
|
741
|
+
const count = numberAt(result, "count");
|
|
742
|
+
if (count !== void 0) span.setAttribute("db.result.count", count);
|
|
723
743
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
724
744
|
return result;
|
|
725
745
|
} catch (error) {
|
|
726
|
-
span.recordException(error);
|
|
746
|
+
span.recordException(toException(error));
|
|
727
747
|
span.setStatus({
|
|
728
748
|
code: SpanStatusCode.ERROR,
|
|
729
749
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -743,7 +763,7 @@ function instrumentD1(d1, databaseName) {
|
|
|
743
763
|
* Unlike other bindings, Fetcher objects are native Cloudflare C++ bindings
|
|
744
764
|
* whose methods throw "Illegal invocation" when called through a Proxy with
|
|
745
765
|
* a different `this` reference. We work around this by calling `target.fetch()`
|
|
746
|
-
* directly on the original binding instead of using `
|
|
766
|
+
* directly on the original binding instead of using `fn.apply` on a
|
|
747
767
|
* detached function reference.
|
|
748
768
|
*/
|
|
749
769
|
function instrumentServiceBinding(fetcher, serviceName) {
|
|
@@ -751,9 +771,9 @@ function instrumentServiceBinding(fetcher, serviceName) {
|
|
|
751
771
|
return wrap(fetcher, { get(target, prop) {
|
|
752
772
|
if (prop === "fetch" && typeof target.fetch === "function") {
|
|
753
773
|
const tracedFetch = (...args) => {
|
|
754
|
-
const [input, init] = args;
|
|
774
|
+
const [input, init] = trapArgs(args);
|
|
755
775
|
const request = new Request(input, init);
|
|
756
|
-
return
|
|
776
|
+
return workerTracer("autotel-edge").startActiveSpan(`Service ${name}: ${request.method}`, {
|
|
757
777
|
kind: SpanKind.CLIENT,
|
|
758
778
|
attributes: {
|
|
759
779
|
"rpc.system": "cloudflare-service-binding",
|
|
@@ -768,7 +788,7 @@ function instrumentServiceBinding(fetcher, serviceName) {
|
|
|
768
788
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
769
789
|
return response;
|
|
770
790
|
} catch (error) {
|
|
771
|
-
span.recordException(error);
|
|
791
|
+
span.recordException(toException(error));
|
|
772
792
|
span.setStatus({
|
|
773
793
|
code: SpanStatusCode.ERROR,
|
|
774
794
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -781,16 +801,16 @@ function instrumentServiceBinding(fetcher, serviceName) {
|
|
|
781
801
|
};
|
|
782
802
|
return tracedFetch;
|
|
783
803
|
}
|
|
784
|
-
const value =
|
|
785
|
-
|
|
804
|
+
const value = member(target, prop);
|
|
805
|
+
const method = asFunction(value);
|
|
806
|
+
if (method !== void 0) return method.bind(target);
|
|
786
807
|
return value;
|
|
787
808
|
} });
|
|
788
809
|
}
|
|
789
810
|
/**
|
|
790
|
-
* Detection helpers
|
|
811
|
+
* Detection helpers - a binding is recognised by the methods it carries.
|
|
791
812
|
*/
|
|
792
|
-
const
|
|
793
|
-
const hasExactMethods = (obj, methods) => methods.every((m) => hasMethod(obj, m));
|
|
813
|
+
const hasExactMethods = (obj, methods) => hasMethods(obj, methods);
|
|
794
814
|
/**
|
|
795
815
|
* Auto-instrument all Cloudflare bindings in the environment
|
|
796
816
|
*
|
|
@@ -811,13 +831,36 @@ const hasExactMethods = (obj, methods) => methods.every((m) => hasMethod(obj, m)
|
|
|
811
831
|
* - Browser Rendering — indistinguishable from Service Binding
|
|
812
832
|
*/
|
|
813
833
|
const envCache = /* @__PURE__ */ new WeakMap();
|
|
834
|
+
/**
|
|
835
|
+
* One Worker binding, read as the type its method set identifies it as.
|
|
836
|
+
*
|
|
837
|
+
* SAFETY: each call below has just checked the exact set of methods that
|
|
838
|
+
* distinguishes one binding kind from every other, in the documented order
|
|
839
|
+
* (R2 before KV because R2 also has `head`, service bindings last because
|
|
840
|
+
* `fetch` is the broadest). The wrapper that receives it calls only the
|
|
841
|
+
* methods that check just found.
|
|
842
|
+
*/
|
|
843
|
+
/** Set an attribute from a result field, when the result carries one there. */
|
|
844
|
+
function setResultAttr(span, attribute, result, key) {
|
|
845
|
+
const value = readProperty(result, key);
|
|
846
|
+
const attributeValue = asString(value) ?? asNumber(value) ?? asBoolean(value);
|
|
847
|
+
if (attributeValue !== void 0) span.setAttribute(attribute, attributeValue);
|
|
848
|
+
}
|
|
849
|
+
function asBinding(value) {
|
|
850
|
+
return value;
|
|
851
|
+
}
|
|
852
|
+
/** A binding is an object; anything else in env is a plain config value. */
|
|
853
|
+
function asObjectBinding(value) {
|
|
854
|
+
return asRecord(value);
|
|
855
|
+
}
|
|
814
856
|
function instrumentBindings(env) {
|
|
815
857
|
const cached = envCache.get(env);
|
|
816
858
|
if (cached) return cached;
|
|
817
859
|
const instrumented = {};
|
|
818
|
-
for (const [key,
|
|
819
|
-
|
|
820
|
-
|
|
860
|
+
for (const [key, entry] of Object.entries(env)) {
|
|
861
|
+
const value = asObjectBinding(entry);
|
|
862
|
+
if (!value) {
|
|
863
|
+
instrumented[key] = entry;
|
|
821
864
|
continue;
|
|
822
865
|
}
|
|
823
866
|
if (isWrapped(value)) {
|
|
@@ -831,7 +874,7 @@ function instrumentBindings(env) {
|
|
|
831
874
|
"list",
|
|
832
875
|
"head"
|
|
833
876
|
])) {
|
|
834
|
-
instrumented[key] = instrumentR2(value, key);
|
|
877
|
+
instrumented[key] = instrumentR2(asBinding(value), key);
|
|
835
878
|
continue;
|
|
836
879
|
}
|
|
837
880
|
if (hasExactMethods(value, [
|
|
@@ -840,11 +883,11 @@ function instrumentBindings(env) {
|
|
|
840
883
|
"delete",
|
|
841
884
|
"list"
|
|
842
885
|
]) && !("head" in value)) {
|
|
843
|
-
instrumented[key] = instrumentKV(value, key);
|
|
886
|
+
instrumented[key] = instrumentKV(asBinding(value), key);
|
|
844
887
|
continue;
|
|
845
888
|
}
|
|
846
889
|
if (hasExactMethods(value, ["prepare", "exec"])) {
|
|
847
|
-
instrumented[key] = instrumentD1(value, key);
|
|
890
|
+
instrumented[key] = instrumentD1(asBinding(value), key);
|
|
848
891
|
continue;
|
|
849
892
|
}
|
|
850
893
|
if (hasExactMethods(value, [
|
|
@@ -853,31 +896,31 @@ function instrumentBindings(env) {
|
|
|
853
896
|
"upsert",
|
|
854
897
|
"describe"
|
|
855
898
|
])) {
|
|
856
|
-
instrumented[key] = instrumentVectorize(value, key);
|
|
899
|
+
instrumented[key] = instrumentVectorize(asBinding(value), key);
|
|
857
900
|
continue;
|
|
858
901
|
}
|
|
859
902
|
if (hasMethod(value, "run") && ("gateway" in value || "models" in value)) {
|
|
860
|
-
instrumented[key] = instrumentAI(value, key);
|
|
903
|
+
instrumented[key] = instrumentAI(asBinding(value), key);
|
|
861
904
|
continue;
|
|
862
905
|
}
|
|
863
906
|
if (hasMethod(value, "connect") && "connectionString" in value && "host" in value) {
|
|
864
|
-
instrumented[key] = instrumentHyperdrive(value, key);
|
|
907
|
+
instrumented[key] = instrumentHyperdrive(asBinding(value), key);
|
|
865
908
|
continue;
|
|
866
909
|
}
|
|
867
910
|
if (hasExactMethods(value, ["send", "sendBatch"]) && !("get" in value)) {
|
|
868
|
-
instrumented[key] = instrumentQueueProducer(value, key);
|
|
911
|
+
instrumented[key] = instrumentQueueProducer(asBinding(value), key);
|
|
869
912
|
continue;
|
|
870
913
|
}
|
|
871
914
|
if (hasMethod(value, "writeDataPoint")) {
|
|
872
|
-
instrumented[key] = instrumentAnalyticsEngine(value, key);
|
|
915
|
+
instrumented[key] = instrumentAnalyticsEngine(asBinding(value), key);
|
|
873
916
|
continue;
|
|
874
917
|
}
|
|
875
918
|
if (hasExactMethods(value, ["info", "input"])) {
|
|
876
|
-
instrumented[key] = instrumentImages(value, key);
|
|
919
|
+
instrumented[key] = instrumentImages(asBinding(value), key);
|
|
877
920
|
continue;
|
|
878
921
|
}
|
|
879
922
|
if (hasMethod(value, "fetch")) {
|
|
880
|
-
instrumented[key] = instrumentServiceBinding(value, key);
|
|
923
|
+
instrumented[key] = instrumentServiceBinding(asBinding(value), key);
|
|
881
924
|
continue;
|
|
882
925
|
}
|
|
883
926
|
instrumented[key] = value;
|
|
@@ -897,10 +940,11 @@ function instrumentBindings(env) {
|
|
|
897
940
|
function instrumentRateLimiter(limiter, bindingName) {
|
|
898
941
|
const name = bindingName || "rate-limiter";
|
|
899
942
|
return wrap(limiter, { get(target, prop) {
|
|
900
|
-
const value =
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
943
|
+
const value = member(target, prop);
|
|
944
|
+
const method = asFunction(value);
|
|
945
|
+
if (prop === "limit" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
946
|
+
const [options] = trapArgs(args);
|
|
947
|
+
return workerTracer("autotel-edge").startActiveSpan(`RateLimiter ${name}: limit`, {
|
|
904
948
|
kind: SpanKind.CLIENT,
|
|
905
949
|
attributes: {
|
|
906
950
|
"rate_limiter.system": "cloudflare-rate-limiter",
|
|
@@ -908,12 +952,12 @@ function instrumentRateLimiter(limiter, bindingName) {
|
|
|
908
952
|
}
|
|
909
953
|
}, async (span) => {
|
|
910
954
|
try {
|
|
911
|
-
const result = await
|
|
912
|
-
setAttr(span, "rate_limiter.success", result
|
|
955
|
+
const result = await fnTarget.apply(target, args);
|
|
956
|
+
setAttr(span, "rate_limiter.success", asBoolean(readProperty(result, "success")));
|
|
913
957
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
914
958
|
return result;
|
|
915
959
|
} catch (error) {
|
|
916
|
-
span.recordException(error);
|
|
960
|
+
span.recordException(toException(error));
|
|
917
961
|
span.setStatus({
|
|
918
962
|
code: SpanStatusCode.ERROR,
|
|
919
963
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -939,11 +983,12 @@ function instrumentRateLimiter(limiter, bindingName) {
|
|
|
939
983
|
function instrumentBrowserRendering(browser, bindingName) {
|
|
940
984
|
const name = bindingName || "browser";
|
|
941
985
|
return wrap(browser, { get(target, prop) {
|
|
942
|
-
const value =
|
|
943
|
-
|
|
944
|
-
|
|
986
|
+
const value = member(target, prop);
|
|
987
|
+
const method = asFunction(value);
|
|
988
|
+
if (prop === "fetch" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
|
|
989
|
+
const [input] = trapArgs(args);
|
|
945
990
|
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
946
|
-
return
|
|
991
|
+
return workerTracer("autotel-edge").startActiveSpan(`BrowserRendering ${name}: fetch`, {
|
|
947
992
|
kind: SpanKind.CLIENT,
|
|
948
993
|
attributes: {
|
|
949
994
|
"browser.system": "cloudflare-browser-rendering",
|
|
@@ -951,12 +996,12 @@ function instrumentBrowserRendering(browser, bindingName) {
|
|
|
951
996
|
}
|
|
952
997
|
}, async (span) => {
|
|
953
998
|
try {
|
|
954
|
-
const result = await
|
|
955
|
-
setAttr(span, "http.response.status_code", result
|
|
999
|
+
const result = await fnTarget.apply(target, args);
|
|
1000
|
+
setAttr(span, "http.response.status_code", numberAt(result, "status"));
|
|
956
1001
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
957
1002
|
return result;
|
|
958
1003
|
} catch (error) {
|
|
959
|
-
span.recordException(error);
|
|
1004
|
+
span.recordException(toException(error));
|
|
960
1005
|
span.setStatus({
|
|
961
1006
|
code: SpanStatusCode.ERROR,
|
|
962
1007
|
message: error instanceof Error ? error.message : String(error)
|