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.
Files changed (58) hide show
  1. package/dist/actors.d.ts +54 -89
  2. package/dist/actors.d.ts.map +1 -0
  3. package/dist/actors.js +990 -986
  4. package/dist/actors.js.map +1 -1
  5. package/dist/agents.d.ts +102 -128
  6. package/dist/agents.d.ts.map +1 -0
  7. package/dist/agents.js +275 -259
  8. package/dist/agents.js.map +1 -1
  9. package/dist/bindings-C10RI6Il.js +975 -0
  10. package/dist/bindings-C10RI6Il.js.map +1 -0
  11. package/dist/bindings-xEZcXo5r.d.ts +149 -0
  12. package/dist/bindings-xEZcXo5r.d.ts.map +1 -0
  13. package/dist/bindings.d.ts +2 -139
  14. package/dist/bindings.js +3 -4
  15. package/dist/common-DiWH6nmG.js +63 -0
  16. package/dist/common-DiWH6nmG.js.map +1 -0
  17. package/dist/events.d.ts +1 -1
  18. package/dist/events.js +3 -3
  19. package/dist/execution-logger-BxmgP8jF.js +65 -0
  20. package/dist/execution-logger-BxmgP8jF.js.map +1 -0
  21. package/dist/{logger-Cm_73k3-.d.ts → execution-logger-tgQmJeeU.d.ts} +9 -7
  22. package/dist/execution-logger-tgQmJeeU.d.ts.map +1 -0
  23. package/dist/handlers-CMg9l_T-.js +378 -0
  24. package/dist/handlers-CMg9l_T-.js.map +1 -0
  25. package/dist/handlers-C_VojUeA.d.ts +96 -0
  26. package/dist/handlers-C_VojUeA.d.ts.map +1 -0
  27. package/dist/handlers.d.ts +2 -112
  28. package/dist/handlers.js +3 -4
  29. package/dist/index.d.ts +20 -99
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +644 -600
  32. package/dist/index.js.map +1 -1
  33. package/dist/logger.d.ts +3 -3
  34. package/dist/logger.js +5 -4
  35. package/dist/parse-error.d.ts +2 -1
  36. package/dist/parse-error.js +3 -3
  37. package/dist/sampling.d.ts +1 -4
  38. package/dist/sampling.js +3 -3
  39. package/dist/testing.d.ts +1 -1
  40. package/dist/testing.js +3 -3
  41. package/package.json +6 -6
  42. package/src/bindings/ai.test.ts +1 -1
  43. package/src/bindings/ai.ts +3 -1
  44. package/dist/bindings.js.map +0 -1
  45. package/dist/chunk-KAUHT25H.js +0 -1084
  46. package/dist/chunk-KAUHT25H.js.map +0 -1
  47. package/dist/chunk-MIDMNKDC.js +0 -333
  48. package/dist/chunk-MIDMNKDC.js.map +0 -1
  49. package/dist/chunk-O4IYKWPJ.js +0 -55
  50. package/dist/chunk-O4IYKWPJ.js.map +0 -1
  51. package/dist/chunk-RVVMMPWN.js +0 -63
  52. package/dist/chunk-RVVMMPWN.js.map +0 -1
  53. package/dist/events.js.map +0 -1
  54. package/dist/handlers.js.map +0 -1
  55. package/dist/logger.js.map +0 -1
  56. package/dist/parse-error.js.map +0 -1
  57. package/dist/sampling.js.map +0 -1
  58. 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