autotel-cloudflare 2.18.19 → 3.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.
@@ -41,10 +41,14 @@ import {
41
41
  getActiveConfig,
42
42
  getServiceForPath,
43
43
  shouldInstrumentPath,
44
+ withNativeTracer,
45
+ ensureGlobalContextManager,
44
46
  type Initialiser,
47
+ type NativeTracer,
45
48
  WorkerTracerProvider,
46
49
  WorkerTracer,
47
50
  } from 'autotel-edge';
51
+ import { getNativeTracerFromCtx } from '../native/native-tracing';
48
52
  import { proxyExecutionContext, unwrap, wrap, type PromiseTracker } from '../bindings/common';
49
53
  import { instrumentGlobalFetch } from '../global/fetch';
50
54
  import { instrumentGlobalCache } from '../global/cache';
@@ -528,6 +532,68 @@ function createHandlerFlow<T extends Trigger, E, R>(
528
532
  };
529
533
  }
530
534
 
535
+ let warnedMissingNative = false;
536
+
537
+ /**
538
+ * Resolve whether this invocation should use Cloudflare's native tracer.
539
+ *
540
+ * - `nativeTracing: 'off'` → never use native (always autotel's OTLP pipeline).
541
+ * - `nativeTracing: 'on'` → require native; warn once and fall back if absent.
542
+ * - `nativeTracing: 'auto'` (default) → use native when `ctx.tracing` exists.
543
+ */
544
+ function resolveNativeTracer(
545
+ config: ResolvedEdgeConfig,
546
+ ctx: ExecutionContext,
547
+ trigger: Trigger,
548
+ ): NativeTracer | null {
549
+ const mode = config.nativeTracing ?? 'auto';
550
+ if (mode === 'off') {
551
+ return null;
552
+ }
553
+ // Correlation id: prefer Cloudflare's ray id (also stamped on the native root
554
+ // span + carried by the workers logger), so logs/spans/dashboard share a key.
555
+ // Fall back to a per-invocation uuid for non-fetch triggers.
556
+ const rayId = trigger instanceof Request ? trigger.headers.get('cf-ray') : null;
557
+ const correlationId = rayId ?? crypto.randomUUID();
558
+ const nativeTracer = getNativeTracerFromCtx(ctx, correlationId);
559
+ if (!nativeTracer && mode === 'on' && !warnedMissingNative) {
560
+ warnedMissingNative = true;
561
+ console.warn(
562
+ "[autotel-cloudflare] nativeTracing is 'on' but Cloudflare native tracing was not detected. " +
563
+ 'Enable observability.traces in your Wrangler config (and use a recent compatibility_date). ' +
564
+ 'Falling back to the autotel OTLP exporter.',
565
+ );
566
+ }
567
+ return nativeTracer;
568
+ }
569
+
570
+ /**
571
+ * Run a handler in native-tracing mode.
572
+ *
573
+ * Cloudflare already creates the root handler span and instruments platform
574
+ * operations (fetch / KV / R2 / D1 / DO), so autotel defers entirely: no
575
+ * binding proxies (avoids duplicate spans), no provider/exporter, no manual
576
+ * flush. We install the native tracer into the active context so that the
577
+ * user's `span()` / `trace()` / `enterSpan()` calls nest inside Cloudflare's
578
+ * native waterfall and are exported by the platform.
579
+ */
580
+ function runWithNativeTracing<T extends Trigger, E, R>(
581
+ handlerFn: (trigger: T, env: E, ctx: ExecutionContext) => R | Promise<R>,
582
+ trigger: T,
583
+ env: E,
584
+ ctx: ExecutionContext,
585
+ config: ResolvedEdgeConfig,
586
+ nativeTracer: NativeTracer,
587
+ ): R | Promise<R> {
588
+ // Register the context manager (we skip initProvider in native mode) so the
589
+ // native tracer propagates through OTel context into span()/trace() — without
590
+ // it, getActiveNativeTracer() returns null and custom spans never route to
591
+ // enterSpan. Bindings are NOT proxied: Cloudflare instruments them natively.
592
+ ensureGlobalContextManager();
593
+ const nativeContext = withNativeTracer(nativeTracer, setConfig(config));
594
+ return api_context.with(nativeContext, () => handlerFn(trigger, env, ctx));
595
+ }
596
+
531
597
  /**
532
598
  * Create handler proxy
533
599
  */
@@ -539,16 +605,22 @@ function createHandlerProxy<T extends Trigger, E, R>(
539
605
  ): (trigger: T, env: E, ctx: ExecutionContext) => ReturnType<typeof handlerFn> {
540
606
  return (trigger: T, env: E, ctx: ExecutionContext) => {
541
607
  const config = initialiser(env, trigger);
542
-
608
+
543
609
  // Check if instrumentation is disabled (useful for local dev)
544
610
  if (config.instrumentation.disabled) {
545
611
  // Return handler as-is without instrumentation
546
612
  return handlerFn(trigger, env, ctx);
547
613
  }
548
-
614
+
615
+ // Prefer Cloudflare native tracing when available — defer to the platform.
616
+ const nativeTracer = resolveNativeTracer(config, ctx, trigger);
617
+ if (nativeTracer) {
618
+ return runWithNativeTracing(handlerFn, trigger, env, ctx, config, nativeTracer);
619
+ }
620
+
549
621
  // Auto-instrument Cloudflare bindings in the environment
550
622
  const instrumentedEnv = instrumentBindings(env as Record<string, any>) as E;
551
-
623
+
552
624
  const configContext = setConfig(config);
553
625
 
554
626
  // Initialize provider on first call
@@ -593,10 +665,16 @@ function createHandlerProxyWithConfig<T extends Trigger, E, R>(
593
665
  return handlerFn(trigger, env, ctx) as ReturnType<typeof handlerFn>;
594
666
  }
595
667
  }
596
-
668
+
669
+ // Prefer Cloudflare native tracing when available — defer to the platform.
670
+ const nativeTracer = resolveNativeTracer(config, ctx, trigger);
671
+ if (nativeTracer) {
672
+ return runWithNativeTracing(handlerFn, trigger, env, ctx, config, nativeTracer) as ReturnType<typeof handlerFn>;
673
+ }
674
+
597
675
  // Auto-instrument Cloudflare bindings in the environment
598
676
  const instrumentedEnv = instrumentBindings(env as Record<string, any>) as E;
599
-
677
+
600
678
  const configContext = setConfig(config);
601
679
 
602
680
  // Initialize provider on first call
@@ -0,0 +1,153 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { instrument } from './instrument';
3
+ import { span } from 'autotel-edge';
4
+ import { isWrapped } from '../bindings/common';
5
+
6
+ /**
7
+ * A KV-shaped binding so instrumentBindings() would proxy it in the OTLP path.
8
+ * In native mode we must NOT proxy it (Cloudflare traces KV natively) — these
9
+ * tests assert that the handler receives the original, unwrapped binding and
10
+ * that user spans route to ctx.tracing.enterSpan instead of the OTel pipeline.
11
+ */
12
+ function fakeKv() {
13
+ return {
14
+ get: vi.fn(async () => 'value'),
15
+ put: vi.fn(async () => {}),
16
+ delete: vi.fn(async () => {}),
17
+ list: vi.fn(async () => ({ keys: [] })),
18
+ };
19
+ }
20
+
21
+ function nativeCtx() {
22
+ const enteredSpans: string[] = [];
23
+ const waitUntil = vi.fn();
24
+ const ctx = {
25
+ waitUntil,
26
+ passThroughOnException() {},
27
+ tracing: {
28
+ enterSpan: vi.fn((name: string, cb: (s: any) => unknown) => {
29
+ enteredSpans.push(name);
30
+ return cb({ isTraced: true, setAttribute: vi.fn() });
31
+ }),
32
+ },
33
+ };
34
+ return { ctx, enteredSpans, waitUntil };
35
+ }
36
+
37
+ const baseConfig = {
38
+ service: { name: 'native-test' },
39
+ exporter: { url: 'http://localhost:4318/v1/traces' },
40
+ } as const;
41
+
42
+ describe('instrument() with Cloudflare native tracing (auto)', () => {
43
+ it('defers binding instrumentation to the platform (no proxy wrapping)', async () => {
44
+ const { ctx } = nativeCtx();
45
+ const kv = fakeKv();
46
+ let seenBinding: unknown;
47
+
48
+ const handler = instrument(
49
+ {
50
+ async fetch(_req, env: { MY_KV: ReturnType<typeof fakeKv> }) {
51
+ seenBinding = env.MY_KV;
52
+ await env.MY_KV.get('k');
53
+ return new Response('ok');
54
+ },
55
+ },
56
+ baseConfig,
57
+ );
58
+
59
+ await handler.fetch!(new Request('https://x/'), { MY_KV: kv }, ctx as never);
60
+
61
+ // Handler received the ORIGINAL binding, not an autotel proxy.
62
+ expect(seenBinding).toBe(kv);
63
+ expect(isWrapped(seenBinding)).toBe(false);
64
+ // No "KV ...: get" span was created via the native tracer.
65
+ expect(
66
+ ctx.tracing.enterSpan.mock.calls.some(([name]) =>
67
+ String(name).startsWith('KV '),
68
+ ),
69
+ ).toBe(false);
70
+ });
71
+
72
+ it('surfaces the cf-ray header as a correlation.id span attribute', async () => {
73
+ const attrs: Record<string, unknown> = {};
74
+ const ctx = {
75
+ waitUntil() {},
76
+ passThroughOnException() {},
77
+ tracing: {
78
+ enterSpan: vi.fn((_name: string, cb: (s: any) => unknown) =>
79
+ cb({
80
+ isTraced: true,
81
+ setAttribute(k: string, v: unknown) {
82
+ attrs[k] = v;
83
+ },
84
+ }),
85
+ ),
86
+ },
87
+ };
88
+
89
+ const handler = instrument(
90
+ { async fetch() { return span('work', () => new Response('ok')); } },
91
+ baseConfig,
92
+ );
93
+
94
+ const req = new Request('https://x/', { headers: { 'cf-ray': 'ray-7f' } });
95
+ await handler.fetch!(req, {}, ctx as never);
96
+ expect(attrs['correlation.id']).toBe('ray-7f');
97
+ });
98
+
99
+ it('routes user span() calls to ctx.tracing.enterSpan', async () => {
100
+ const { ctx, enteredSpans } = nativeCtx();
101
+
102
+ const handler = instrument(
103
+ {
104
+ async fetch() {
105
+ return span('user.work', (s) => {
106
+ s.setAttribute('ok', true);
107
+ return new Response('done');
108
+ });
109
+ },
110
+ },
111
+ baseConfig,
112
+ );
113
+
114
+ const res = await handler.fetch!(new Request('https://x/'), {}, ctx as never);
115
+ expect(await res.text()).toBe('done');
116
+ expect(enteredSpans).toContain('user.work');
117
+ });
118
+
119
+ it('does not run the OTLP export flow (no waitUntil) in native mode', async () => {
120
+ const { ctx, waitUntil } = nativeCtx();
121
+ const handler = instrument(
122
+ { async fetch() { return new Response('ok'); } },
123
+ baseConfig,
124
+ );
125
+ await handler.fetch!(new Request('https://x/'), {}, ctx as never);
126
+ expect(waitUntil).not.toHaveBeenCalled();
127
+ });
128
+ });
129
+
130
+ describe('instrument() with nativeTracing: "off"', () => {
131
+ it('ignores ctx.tracing and uses the autotel pipeline (proxies bindings)', async () => {
132
+ const { ctx } = nativeCtx();
133
+ const kv = fakeKv();
134
+ let seenBinding: unknown;
135
+
136
+ const handler = instrument(
137
+ {
138
+ async fetch(_req, env: { MY_KV: ReturnType<typeof fakeKv> }) {
139
+ seenBinding = env.MY_KV;
140
+ return new Response('ok');
141
+ },
142
+ },
143
+ { ...baseConfig, nativeTracing: 'off' },
144
+ );
145
+
146
+ await handler.fetch!(new Request('https://x/'), { MY_KV: kv }, ctx as never);
147
+
148
+ // OTLP path proxies the binding, so the handler sees a wrapped object.
149
+ expect(isWrapped(seenBinding)).toBe(true);
150
+ // Native tracer was never used.
151
+ expect(ctx.tracing.enterSpan).not.toHaveBeenCalled();
152
+ });
153
+ });
@@ -1 +0,0 @@
1
- {"version":3,"file":"bindings-D3lNJZmq.js","names":[],"sources":["../src/bindings/ai.ts","../src/bindings/vectorize.ts","../src/bindings/hyperdrive.ts","../src/bindings/queue-producer.ts","../src/bindings/analytics-engine.ts","../src/bindings/images.ts","../src/bindings/bindings.ts","../src/bindings/rate-limiter.ts","../src/bindings/browser-rendering.ts"],"sourcesContent":["/**\n * Workers AI binding instrumentation\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap, setAttr } from './common';\n\n/**\n * Instrument Workers AI binding\n */\nexport function instrumentAI<T extends Ai>(ai: T, bindingName?: string): T {\n const name = bindingName || 'ai';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'run' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [model] = args as [string, unknown, unknown];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `AI ${name}: run ${model}`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'gen_ai.system': 'cloudflare-workers-ai',\n 'gen_ai.operation.name': 'run',\n 'gen_ai.request.model': model,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n if (result?.usage?.prompt_tokens !== undefined) {\n setAttr(span, 'gen_ai.usage.input_tokens', Number(result.usage.prompt_tokens));\n }\n if (result?.usage?.completion_tokens !== undefined) {\n setAttr(span, 'gen_ai.usage.output_tokens', Number(result.usage.completion_tokens));\n }\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(ai, handler);\n}\n","/**\n * Vectorize binding instrumentation\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap, setAttr } from './common';\n\nconst TRACED_METHODS = ['query', 'insert', 'upsert', 'deleteByIds', 'getByIds', 'describe'] as const;\n\n/**\n * Instrument Vectorize index binding\n */\nexport function instrumentVectorize<T extends VectorizeIndex>(vectorize: T, indexName?: string): T {\n const name = indexName || 'vectorize';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (typeof prop === 'string' && TRACED_METHODS.includes(prop as any) && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const operation = prop as string;\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n const attributes: Record<string, string | number> = {\n 'db.system': 'cloudflare-vectorize',\n 'db.operation': operation,\n 'db.collection.name': name,\n };\n\n // Per-operation attributes\n if (operation === 'query') {\n const queryInput = args[0] as { topK?: number } | undefined;\n if (queryInput?.topK !== undefined) {\n attributes['db.vectorize.top_k'] = queryInput.topK;\n }\n }\n\n if ((operation === 'insert' || operation === 'upsert') && Array.isArray(args[0])) {\n attributes['db.vectorize.vectors_count'] = args[0].length;\n }\n\n return tracer.startActiveSpan(\n `Vectorize ${name}: ${operation}`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n\n if (operation === 'query' && result?.matches) {\n setAttr(span, 'db.vectorize.matches_count', result.matches.length);\n }\n\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(vectorize, handler);\n}\n","/**\n * Hyperdrive binding instrumentation\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap, setAttr } from './common';\n\n/**\n * Instrument Hyperdrive binding\n */\nexport function instrumentHyperdrive<T extends Hyperdrive>(hyperdrive: T, bindingName?: string): T {\n const name = bindingName || 'hyperdrive';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'connect' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n const attributes: Record<string, string | number> = {\n 'db.system': 'cloudflare-hyperdrive',\n 'db.operation': 'connect',\n };\n\n // Extract connection info safely (never record password)\n try {\n setAttr({ setAttribute: (k: string, v: any) => { if (v !== undefined && v !== null) attributes[k] = v; } }, 'server.address', target.host);\n setAttr({ setAttribute: (k: string, v: any) => { if (v !== undefined && v !== null) attributes[k] = v; } }, 'server.port', target.port);\n setAttr({ setAttribute: (k: string, v: any) => { if (v !== undefined && v !== null) attributes[k] = v; } }, 'db.user', target.user);\n } catch {\n // Properties may not be accessible in all environments\n }\n\n return tracer.startActiveSpan(\n `Hyperdrive ${name}: connect`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(hyperdrive, handler);\n}\n","/**\n * Queue producer binding instrumentation\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap, setAttr } from './common';\n\n/**\n * Instrument Queue producer binding\n */\nexport function instrumentQueueProducer<T extends Queue>(queue: T, queueName?: string): T {\n const name = queueName || 'queue';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'send' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `Queue ${name}: send`,\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n 'messaging.system': 'cloudflare-queues',\n 'messaging.operation.type': 'publish',\n 'messaging.operation': 'send',\n 'messaging.destination.name': name,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n setAttr(span, 'messaging.message.id', (result as any)?.messageId);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n if (prop === 'sendBatch' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [messages] = args as [{ body: unknown }[]];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `Queue ${name}: sendBatch`,\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n 'messaging.system': 'cloudflare-queues',\n 'messaging.operation.type': 'publish',\n 'messaging.operation': 'sendBatch',\n 'messaging.destination.name': name,\n 'messaging.batch.message_count': Array.isArray(messages) ? messages.length : 0,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(queue, handler);\n}\n","/**\n * Analytics Engine binding instrumentation\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap } from './common';\n\n/**\n * Instrument Analytics Engine binding\n */\nexport function instrumentAnalyticsEngine<T extends AnalyticsEngineDataset>(ae: T, datasetName?: string): T {\n const name = datasetName || 'analytics-engine';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'writeDataPoint' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [dataPoint] = args as [AnalyticsEngineDataPoint | undefined];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n const attributes: Record<string, string | number> = {\n 'analytics.system': 'cloudflare-analytics-engine',\n 'analytics.operation': 'writeDataPoint',\n };\n\n if (dataPoint) {\n if (dataPoint.indexes) {\n attributes['analytics.indexes_count'] = Array.isArray(dataPoint.indexes) ? dataPoint.indexes.length : 1;\n }\n if (dataPoint.doubles) {\n attributes['analytics.doubles_count'] = dataPoint.doubles.length;\n }\n if (dataPoint.blobs) {\n attributes['analytics.blobs_count'] = dataPoint.blobs.length;\n }\n }\n\n return tracer.startActiveSpan(\n `AnalyticsEngine ${name}: writeDataPoint`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n (span) => {\n try {\n // writeDataPoint is synchronous/void\n Reflect.apply(fnTarget, target, args);\n span.setStatus({ code: SpanStatusCode.OK });\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(ae, handler);\n}\n","/**\n * Images binding instrumentation\n *\n * The Images binding uses a fluent chain: input() -> transform() -> draw() -> output()\n * We only create a span at the terminal output() call to avoid intermediate noise.\n * info() is a standalone operation and gets its own span.\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap, setAttr } from './common';\n\nconst pipelineMetaSymbol = Symbol('images-pipeline-meta');\n\ninterface PipelineMeta {\n operationCount: number;\n}\n\ninterface ImagesLike {\n info(blob: ReadableStream | ArrayBuffer | Blob): Promise<{ width: number; height: number; format: string }>;\n input(blob: ReadableStream | ArrayBuffer | Blob): ImageTransformerLike;\n}\n\ninterface ImageTransformerLike {\n transform(options: unknown): ImageTransformerLike;\n draw(image: unknown, options?: unknown): ImageTransformerLike;\n output(options?: unknown): Promise<ImageOutputLike>;\n}\n\ninterface ImageOutputLike {\n response(): Response;\n blob(): Promise<Blob>;\n arrayBuffer(): Promise<ArrayBuffer>;\n}\n\nfunction proxyTransformer(transformer: ImageTransformerLike, meta: PipelineMeta, bindingName: string): ImageTransformerLike {\n const handler: ProxyHandler<ImageTransformerLike> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if ((prop === 'transform' || prop === 'draw') && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n meta.operationCount++;\n const result = Reflect.apply(fnTarget, target, args);\n // If the result is the transformer itself (fluent chain), return our proxy\n if (result === target || (result && typeof result === 'object' && 'output' in result)) {\n return proxyTransformer(result as ImageTransformerLike, meta, bindingName);\n }\n return result;\n },\n });\n }\n\n if (prop === 'output' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n const [formatOrOptions] = args;\n\n const attributes: Record<string, string | number> = {\n 'images.system': 'cloudflare-images',\n 'images.pipeline.operation_count': meta.operationCount,\n };\n\n // Capture output format\n if (typeof formatOrOptions === 'string') {\n attributes['images.output.format'] = formatOrOptions;\n } else if (formatOrOptions && typeof formatOrOptions === 'object') {\n const fmt = (formatOrOptions as any).format;\n if (fmt) attributes['images.output.format'] = fmt;\n }\n\n return tracer.startActiveSpan(\n `Images ${bindingName}: output`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n const proxy = new Proxy(transformer, handler);\n Object.defineProperty(proxy, pipelineMetaSymbol, {\n value: meta,\n writable: false,\n enumerable: false,\n configurable: false,\n });\n return proxy;\n}\n\n/**\n * Instrument Images binding\n */\nexport function instrumentImages<T extends ImagesLike>(images: T, bindingName?: string): T {\n const name = bindingName || 'images';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'info' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `Images ${name}: info`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'images.system': 'cloudflare-images',\n 'images.operation': 'info',\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n setAttr(span, 'images.width', result?.width);\n setAttr(span, 'images.height', result?.height);\n setAttr(span, 'images.format', result?.format);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n if (prop === 'input' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const transformer = Reflect.apply(fnTarget, target, args) as ImageTransformerLike;\n const meta: PipelineMeta = { operationCount: 0 };\n return proxyTransformer(transformer, meta, name);\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(images, handler);\n}\n","/**\n * Auto-instrumentation for Cloudflare Workers bindings\n * \n * Note: This file uses Cloudflare Workers types (KVNamespace, R2Bucket, D1Database, Fetcher, etc.)\n * which are globally available via @cloudflare/workers-types when listed in tsconfig.json.\n * These types are devDependencies only - they're not runtime dependencies.\n * At runtime, Cloudflare Workers runtime provides the actual implementations.\n * \n * This module provides automatic tracing for Cloudflare bindings:\n * - KV (key-value operations)\n * - R2 (object storage operations)\n * - D1 (database operations)\n * - Service Bindings\n * - Events Engine\n * - Workers AI\n * - Vectorize\n * - Hyperdrive\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport { WorkerTracer, getActiveConfig } from 'autotel-edge';\nimport { wrap, isWrapped } from './common';\nimport { instrumentAI } from './ai';\nimport { instrumentVectorize } from './vectorize';\nimport { instrumentHyperdrive } from './hyperdrive';\nimport { instrumentQueueProducer } from './queue-producer';\nimport { instrumentAnalyticsEngine } from './analytics-engine';\nimport { instrumentImages } from './images';\n\ntype DbStatementCapture = 'off' | 'obfuscated' | 'full';\n\n/**\n * Sanitize a SQL statement based on the capture mode.\n * - 'full': returns the statement as-is\n * - 'obfuscated': replaces string literals and numbers with '?'\n * - 'off': returns undefined (attribute not set)\n */\nfunction sanitizeStatement(query: string, mode: DbStatementCapture): string | undefined {\n if (mode === 'off') return undefined;\n if (mode === 'obfuscated') return query.replaceAll(/'[^']*'/g, \"'?'\").replaceAll(/\\b\\d+\\b/g, '?');\n return query;\n}\n\n/**\n * Instrument KV namespace\n */\nexport function instrumentKV<K extends KVNamespace>(kv: K, namespaceName?: string): K {\n const name = namespaceName || 'kv';\n \n const kvHandler: ProxyHandler<K> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n \n if (prop === 'get' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [key, options] = args as [string, KVNamespaceGetOptions<unknown> | undefined];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `KV ${name}: get`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-kv',\n 'db.operation': 'get',\n 'db.namespace': name,\n 'db.key': key,\n 'db.cache_hit': options?.cacheTtl !== undefined,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setAttribute('db.result.type', result === null ? 'null' : typeof result);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n if (prop === 'put' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [key] = args as [string, unknown, KVNamespacePutOptions | undefined];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `KV ${name}: put`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-kv',\n 'db.operation': 'put',\n 'db.namespace': name,\n 'db.key': key,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n if (prop === 'delete' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [key] = args as [string];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `KV ${name}: delete`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-kv',\n 'db.operation': 'delete',\n 'db.namespace': name,\n 'db.key': key,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n if (prop === 'list' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [options] = args as [KVNamespaceListOptions | undefined];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `KV ${name}: list`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-kv',\n 'db.operation': 'list',\n 'db.namespace': name,\n 'db.prefix': options?.prefix || undefined,\n 'db.limit': options?.limit || undefined,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setAttribute('db.result.keys_count', result.keys.length);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n return value;\n },\n };\n \n return wrap(kv, kvHandler);\n}\n\n/**\n * Instrument R2 bucket\n */\nexport function instrumentR2<R extends R2Bucket>(r2: R, bucketName?: string): R {\n const name = bucketName || 'r2';\n \n const r2Handler: ProxyHandler<R> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n \n if (prop === 'get' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [key] = args as [string, R2GetOptions | undefined];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `R2 ${name}: get`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-r2',\n 'db.operation': 'get',\n 'db.bucket': name,\n 'db.key': key,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n if (result) {\n span.setAttribute('db.result.size', result.size);\n span.setAttribute('db.result.etag', result.etag);\n span.setAttribute('db.result.content_type', result.httpMetadata?.contentType);\n } else {\n span.setAttribute('db.result.exists', false);\n }\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n if (prop === 'put' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [key] = args as [string, ReadableStream | ArrayBuffer | ArrayBufferView | string | null | Blob, R2PutOptions | undefined];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `R2 ${name}: put`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-r2',\n 'db.operation': 'put',\n 'db.bucket': name,\n 'db.key': key,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setAttribute('db.result.etag', result.etag);\n span.setAttribute('db.result.uploaded', result.uploaded);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n if (prop === 'delete' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const keys = args as string[];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `R2 ${name}: delete`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-r2',\n 'db.operation': 'delete',\n 'db.bucket': name,\n 'db.keys_count': keys.length,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n if (prop === 'list' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [options] = args as [R2ListOptions | undefined];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `R2 ${name}: list`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'db.system': 'cloudflare-r2',\n 'db.operation': 'list',\n 'db.bucket': name,\n 'db.prefix': options?.prefix || undefined,\n 'db.limit': options?.limit || undefined,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setAttribute('db.result.objects_count', result.objects.length);\n span.setAttribute('db.result.truncated', result.truncated);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n return value;\n },\n };\n \n return wrap(r2, r2Handler);\n}\n\n/**\n * Instrument D1 database\n */\nexport function instrumentD1<D extends D1Database>(d1: D, databaseName?: string): D {\n const name = databaseName || 'd1';\n \n const d1Handler: ProxyHandler<D> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n \n if (prop === 'prepare' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [query] = args as [string];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n const prepared = Reflect.apply(fnTarget, target, args);\n \n // Instrument the prepared statement\n const preparedHandler: ProxyHandler<typeof prepared> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n \n if (prop === 'first' || prop === 'run' || prop === 'all' || prop === 'raw') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const activeConfig = getActiveConfig();\n const captureMode: DbStatementCapture = activeConfig?.dataSafety?.captureDbStatement ?? 'full';\n const statement = sanitizeStatement(query, captureMode);\n const attributes: Record<string, any> = {\n 'db.system': 'cloudflare-d1',\n 'db.operation': prop,\n 'db.name': name,\n };\n if (statement !== undefined) {\n attributes['db.statement'] = statement;\n }\n return tracer.startActiveSpan(\n `D1 ${name}: ${prop}`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n if (prop === 'all' && Array.isArray(result)) {\n span.setAttribute('db.result.rows_count', result.length);\n } else if (prop === 'first' && result) {\n span.setAttribute('db.result.exists', true);\n }\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n return value;\n },\n };\n \n return wrap(prepared, preparedHandler);\n },\n });\n }\n \n if (prop === 'exec' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [query] = args as [string];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n const activeConfig = getActiveConfig();\n const captureMode: DbStatementCapture = activeConfig?.dataSafety?.captureDbStatement ?? 'full';\n const statement = sanitizeStatement(query, captureMode);\n const attributes: Record<string, any> = {\n 'db.system': 'cloudflare-d1',\n 'db.operation': 'exec',\n 'db.name': name,\n };\n if (statement !== undefined) {\n attributes['db.statement'] = statement;\n }\n\n return tracer.startActiveSpan(\n `D1 ${name}: exec`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n span.setAttribute('db.result.count', result.count);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n \n return value;\n },\n };\n \n return wrap(d1, d1Handler);\n}\n\n/**\n * Instrument service binding (Fetcher)\n *\n * Unlike other bindings, Fetcher objects are native Cloudflare C++ bindings\n * whose methods throw \"Illegal invocation\" when called through a Proxy with\n * a different `this` reference. We work around this by calling `target.fetch()`\n * directly on the original binding instead of using `Reflect.apply` on a\n * detached function reference.\n */\nexport function instrumentServiceBinding<F extends Fetcher>(fetcher: F, serviceName?: string): F {\n const name = serviceName || 'service';\n\n const fetcherHandler: ProxyHandler<F> = {\n get(target, prop) {\n if (prop === 'fetch' && typeof target.fetch === 'function') {\n // Return a plain function wrapper instead of proxying the native method.\n // This avoids detaching the native method from its binding, which would\n // cause \"Illegal invocation\" on Cloudflare's native Fetcher objects.\n const tracedFetch = (...args: any[]) => {\n const [input, init] = args as [RequestInfo | URL, RequestInit | undefined];\n const request = new Request(input, init);\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `Service ${name}: ${request.method}`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'rpc.system': 'cloudflare-service-binding',\n 'rpc.service': name,\n 'http.request.method': request.method,\n 'url.full': request.url,\n },\n },\n async (span) => {\n try {\n // Call fetch directly on the original target to preserve\n // the native `this` binding that Cloudflare requires\n const response = await target.fetch(input, init as RequestInit);\n span.setAttribute('http.response.status_code', response.status);\n span.setStatus({ code: SpanStatusCode.OK });\n return response;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n };\n return tracedFetch;\n }\n\n // For non-fetch properties, access the original target directly\n // to avoid Proxy-related issues with native bindings\n const value = Reflect.get(target, prop);\n if (typeof value === 'function') {\n // Bind native methods to the original target to prevent\n // \"Illegal invocation\" errors\n return value.bind(target);\n }\n return value;\n },\n };\n\n return wrap(fetcher, fetcherHandler);\n}\n\n/**\n * Detection helpers\n */\nconst hasMethod = (obj: any, m: string): boolean =>\n typeof obj?.[m] === 'function';\n\nconst hasExactMethods = (obj: any, methods: string[]): boolean =>\n methods.every(m => hasMethod(obj, m));\n\n/**\n * Auto-instrument all Cloudflare bindings in the environment\n *\n * Detection order (most specific first):\n * 1. R2 — get, put, delete, list, head\n * 2. KV — get, put, delete, list (not head)\n * 3. D1 — prepare, exec\n * 4. Vectorize — query, insert, upsert, describe\n * 5. AI — run + (gateway or models discriminator)\n * 6. Hyperdrive — connect + connectionString + host\n * 7. Queue Producer — send, sendBatch (not get)\n * 8. Analytics Engine — writeDataPoint\n * 9. Images — info, input\n * 10. Service Binding — fetch (broadest, must be last)\n *\n * Not auto-detected (manual only):\n * - Rate Limiter — limit() alone too generic\n * - Browser Rendering — indistinguishable from Service Binding\n */\nconst envCache = new WeakMap<object, Record<string, any>>();\n\nexport function instrumentBindings(env: Record<string, any>): Record<string, any> {\n const cached = envCache.get(env);\n if (cached) return cached;\n\n const instrumented: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(env)) {\n if (!value || typeof value !== 'object') {\n instrumented[key] = value;\n continue;\n }\n\n // Skip already-instrumented bindings\n if (isWrapped(value)) {\n instrumented[key] = value;\n continue;\n }\n\n // 1. R2 — most specific (has head)\n if (hasExactMethods(value, ['get', 'put', 'delete', 'list', 'head'])) {\n instrumented[key] = instrumentR2(value as R2Bucket, key);\n continue;\n }\n\n // 2. KV — like R2 but without head\n if (hasExactMethods(value, ['get', 'put', 'delete', 'list']) && !('head' in value)) {\n instrumented[key] = instrumentKV(value as KVNamespace, key);\n continue;\n }\n\n // 3. D1\n if (hasExactMethods(value, ['prepare', 'exec'])) {\n instrumented[key] = instrumentD1(value as D1Database, key);\n continue;\n }\n\n // 4. Vectorize\n if (hasExactMethods(value, ['query', 'insert', 'upsert', 'describe'])) {\n instrumented[key] = instrumentVectorize(value as VectorizeIndex, key);\n continue;\n }\n\n // 5. AI — has run() + discriminator properties\n if (hasMethod(value, 'run') && ('gateway' in value || 'models' in value)) {\n instrumented[key] = instrumentAI(value as Ai, key);\n continue;\n }\n\n // 6. Hyperdrive — connect + connection properties\n if (hasMethod(value, 'connect') && 'connectionString' in value && 'host' in value) {\n instrumented[key] = instrumentHyperdrive(value as Hyperdrive, key);\n continue;\n }\n\n // 7. Queue Producer — send + sendBatch (not get, to avoid KV collision)\n if (hasExactMethods(value, ['send', 'sendBatch']) && !('get' in value)) {\n instrumented[key] = instrumentQueueProducer(value as Queue, key);\n continue;\n }\n\n // 8. Analytics Engine\n if (hasMethod(value, 'writeDataPoint')) {\n instrumented[key] = instrumentAnalyticsEngine(value as AnalyticsEngineDataset, key);\n continue;\n }\n\n // 9. Images\n if (hasExactMethods(value, ['info', 'input'])) {\n instrumented[key] = instrumentImages(value as any, key);\n continue;\n }\n\n // 10. Service Binding (broadest — must be last)\n if (hasMethod(value, 'fetch')) {\n instrumented[key] = instrumentServiceBinding(value as Fetcher, key);\n continue;\n }\n\n // Unknown binding type — pass through\n instrumented[key] = value;\n }\n\n envCache.set(env, instrumented);\n return instrumented;\n}\n\n","/**\n * Rate Limiter binding instrumentation\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap, setAttr } from './common';\n\ninterface RateLimiterLike {\n limit(options: { key: string }): Promise<{ success: boolean }>;\n}\n\n/**\n * Instrument Rate Limiter binding (manual only — not auto-detected)\n */\nexport function instrumentRateLimiter<T extends RateLimiterLike>(limiter: T, bindingName?: string): T {\n const name = bindingName || 'rate-limiter';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'limit' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [options] = args as [{ key: string }];\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `RateLimiter ${name}: limit`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'rate_limiter.system': 'cloudflare-rate-limiter',\n 'rate_limiter.key': options?.key,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n setAttr(span, 'rate_limiter.success', result?.success);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(limiter, handler);\n}\n","/**\n * Browser Rendering binding instrumentation\n */\n\nimport {\n trace,\n SpanKind,\n SpanStatusCode,\n} from '@opentelemetry/api';\nimport type { WorkerTracer } from 'autotel-edge';\nimport { wrap, setAttr } from './common';\n\ninterface BrowserRenderingLike {\n fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;\n}\n\n/**\n * Instrument Browser Rendering binding (manual only — not auto-detected)\n */\nexport function instrumentBrowserRendering<T extends BrowserRenderingLike>(browser: T, bindingName?: string): T {\n const name = bindingName || 'browser';\n\n const handler: ProxyHandler<T> = {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'fetch' && typeof value === 'function') {\n return new Proxy(value, {\n apply: (fnTarget, _thisArg, args) => {\n const [input] = args as [RequestInfo | URL, RequestInit | undefined];\n const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n const tracer = trace.getTracer('autotel-edge') as WorkerTracer;\n\n return tracer.startActiveSpan(\n `BrowserRendering ${name}: fetch`,\n {\n kind: SpanKind.CLIENT,\n attributes: {\n 'browser.system': 'cloudflare-browser-rendering',\n 'url.full': url,\n },\n },\n async (span) => {\n try {\n const result = await Reflect.apply(fnTarget, target, args);\n setAttr(span, 'http.response.status_code', result?.status);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n span.end();\n }\n },\n );\n },\n });\n }\n\n return value;\n },\n };\n\n return wrap(browser, handler);\n}\n"],"mappings":"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"}