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.
@@ -1,6 +1,8 @@
1
- import { a as wrap, r as setAttr, t as isWrapped } from "./common-DiWH6nmG.js";
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, trace } from "@opentelemetry/api";
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 = 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}`, {
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 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
+ 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 = Reflect.get(target, prop);
68
- if (typeof prop === "string" && TRACED_METHODS.includes(prop) && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
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 = trace.getTracer("autotel-edge");
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 Reflect.apply(fnTarget, target, args);
87
- if (operation === "query" && result?.matches) setAttr(span, "db.vectorize.matches_count", result.matches.length);
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 = 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");
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 Reflect.apply(fnTarget, target, args);
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 = 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`, {
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 Reflect.apply(fnTarget, target, args);
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" && 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`, {
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 Reflect.apply(fnTarget, target, args);
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 = 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");
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
- Reflect.apply(fnTarget, target, args);
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 = Reflect.get(target, prop);
290
- if ((prop === "transform" || prop === "draw") && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
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 = Reflect.apply(fnTarget, target, args);
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" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
297
- const tracer = trace.getTracer("autotel-edge");
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 Reflect.apply(fnTarget, target, args);
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 = 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`, {
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 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);
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" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
373
- return proxyTransformer(Reflect.apply(fnTarget, target, args), { operationCount: 0 }, name);
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 = 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`, {
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 Reflect.apply(fnTarget, target, args);
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" && 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`, {
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 Reflect.apply(fnTarget, target, args);
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" && 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`, {
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 Reflect.apply(fnTarget, target, args);
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" && 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`, {
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 Reflect.apply(fnTarget, target, args);
514
- span.setAttribute("db.result.keys_count", result.keys.length);
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 = 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`, {
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 Reflect.apply(fnTarget, target, args);
566
+ const result = await fnTarget.apply(target, args);
552
567
  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);
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" && 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`, {
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 Reflect.apply(fnTarget, target, args);
584
- span.setAttribute("db.result.etag", result.etag);
585
- span.setAttribute("db.result.uploaded", result.uploaded);
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" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
616
+ if (prop === "delete" && method) return new Proxy(method, { apply: (fnTarget, _thisArg, args) => {
601
617
  const keys = args;
602
- return trace.getTracer("autotel-edge").startActiveSpan(`R2 ${name}: delete`, {
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 Reflect.apply(fnTarget, target, args);
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" && 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`, {
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 Reflect.apply(fnTarget, target, args);
641
- span.setAttribute("db.result.objects_count", result.objects.length);
642
- span.setAttribute("db.result.truncated", result.truncated);
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 = 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) => {
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 Reflect.apply(fnTarget, target, args);
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" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
707
- const [query] = args;
708
- const tracer = trace.getTracer("autotel-edge");
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 Reflect.apply(fnTarget, target, args);
722
- span.setAttribute("db.result.count", result.count);
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 `Reflect.apply` on a
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 trace.getTracer("autotel-edge").startActiveSpan(`Service ${name}: ${request.method}`, {
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 = Reflect.get(target, prop);
785
- if (typeof value === "function") return value.bind(target);
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 hasMethod = (obj, m) => typeof obj?.[m] === "function";
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, value] of Object.entries(env)) {
819
- if (!value || typeof value !== "object") {
820
- instrumented[key] = value;
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 = Reflect.get(target, prop);
901
- if (prop === "limit" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
902
- const [options] = args;
903
- return trace.getTracer("autotel-edge").startActiveSpan(`RateLimiter ${name}: limit`, {
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 Reflect.apply(fnTarget, target, args);
912
- setAttr(span, "rate_limiter.success", result?.success);
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 = Reflect.get(target, prop);
943
- if (prop === "fetch" && typeof value === "function") return new Proxy(value, { apply: (fnTarget, _thisArg, args) => {
944
- const [input] = args;
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 trace.getTracer("autotel-edge").startActiveSpan(`BrowserRendering ${name}: fetch`, {
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 Reflect.apply(fnTarget, target, args);
955
- setAttr(span, "http.response.status_code", result?.status);
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)