autotel-cloudflare 2.1.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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +432 -0
  3. package/dist/actors.d.ts +248 -0
  4. package/dist/actors.js +1030 -0
  5. package/dist/actors.js.map +1 -0
  6. package/dist/agents.d.ts +219 -0
  7. package/dist/agents.js +276 -0
  8. package/dist/agents.js.map +1 -0
  9. package/dist/bindings.d.ts +40 -0
  10. package/dist/bindings.js +4 -0
  11. package/dist/bindings.js.map +1 -0
  12. package/dist/chunk-JDPN3HND.js +520 -0
  13. package/dist/chunk-JDPN3HND.js.map +1 -0
  14. package/dist/chunk-QXFYTHQF.js +298 -0
  15. package/dist/chunk-QXFYTHQF.js.map +1 -0
  16. package/dist/chunk-SKKRPS5K.js +50 -0
  17. package/dist/chunk-SKKRPS5K.js.map +1 -0
  18. package/dist/events.d.ts +1 -0
  19. package/dist/events.js +3 -0
  20. package/dist/events.js.map +1 -0
  21. package/dist/handlers.d.ts +121 -0
  22. package/dist/handlers.js +4 -0
  23. package/dist/handlers.js.map +1 -0
  24. package/dist/index.d.ts +144 -0
  25. package/dist/index.js +576 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/logger.d.ts +1 -0
  28. package/dist/logger.js +3 -0
  29. package/dist/logger.js.map +1 -0
  30. package/dist/sampling.d.ts +4 -0
  31. package/dist/sampling.js +3 -0
  32. package/dist/sampling.js.map +1 -0
  33. package/dist/testing.d.ts +1 -0
  34. package/dist/testing.js +3 -0
  35. package/dist/testing.js.map +1 -0
  36. package/package.json +107 -0
  37. package/src/actors/alarms.ts +225 -0
  38. package/src/actors/index.ts +36 -0
  39. package/src/actors/instrument-actor.test.ts +179 -0
  40. package/src/actors/instrument-actor.ts +574 -0
  41. package/src/actors/sockets.ts +217 -0
  42. package/src/actors/storage.ts +263 -0
  43. package/src/actors/traced-handler.ts +300 -0
  44. package/src/actors/types.ts +98 -0
  45. package/src/actors.ts +50 -0
  46. package/src/agents/index.ts +42 -0
  47. package/src/agents/otel-observability.test.ts +329 -0
  48. package/src/agents/otel-observability.ts +465 -0
  49. package/src/agents/types.ts +167 -0
  50. package/src/agents.ts +76 -0
  51. package/src/bindings/bindings.ts +621 -0
  52. package/src/bindings/common.ts +75 -0
  53. package/src/bindings/index.ts +12 -0
  54. package/src/bindings.ts +6 -0
  55. package/src/events.ts +6 -0
  56. package/src/global/cache.test.ts +292 -0
  57. package/src/global/cache.ts +164 -0
  58. package/src/global/fetch.test.ts +344 -0
  59. package/src/global/fetch.ts +134 -0
  60. package/src/global/index.ts +7 -0
  61. package/src/handlers/durable-objects.test.ts +524 -0
  62. package/src/handlers/durable-objects.ts +250 -0
  63. package/src/handlers/index.ts +6 -0
  64. package/src/handlers/workflows.ts +318 -0
  65. package/src/handlers.ts +6 -0
  66. package/src/index.ts +57 -0
  67. package/src/logger.ts +6 -0
  68. package/src/sampling.ts +6 -0
  69. package/src/testing.ts +6 -0
  70. package/src/wrappers/index.ts +8 -0
  71. package/src/wrappers/instrument.integration.test.ts +468 -0
  72. package/src/wrappers/instrument.ts +643 -0
  73. package/src/wrappers/wrap-do.ts +34 -0
  74. package/src/wrappers/wrap-module.ts +37 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Jag Reehal 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,432 @@
1
+ # autotel-cloudflare
2
+
3
+ **The #1 OpenTelemetry package for Cloudflare Workers** - complete bindings coverage, native CF OTel integration, advanced sampling, zero vendor lock-in.
4
+
5
+ [![npm version](https://badge.fury.io/js/autotel-cloudflare.svg)](https://www.npmjs.com/package/autotel-cloudflare)
6
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/autotel-cloudflare)](https://bundlephobia.com/package/autotel-cloudflare)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## Features
10
+
11
+ - ✅ **Native Cloudflare OTel integration** - Works with `wrangler.toml` destinations
12
+ - ✅ **Complete bindings coverage** - KV, R2, D1, DO, AI, Vectorize, Hyperdrive, and more
13
+ - ✅ **Multiple API styles** - `instrument()`, `wrapModule()`, `wrapDurableObject()`, functional
14
+ - ✅ **Advanced sampling** - Adaptive tail sampling (10% baseline, 100% errors/slow)
15
+ - ✅ **Events integration** - Product analytics with trace correlation
16
+ - ✅ **Zero vendor lock-in** - OTLP compatible, works with any backend
17
+ - ✅ **Tree-shakeable** - Import only what you need
18
+ - ✅ **TypeScript native** - Full type safety
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install autotel-cloudflare
24
+ # or
25
+ pnpm add autotel-cloudflare
26
+ # or
27
+ yarn add autotel-cloudflare
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ### 1. Configure Cloudflare Native OTel (wrangler.toml)
33
+
34
+ ```toml
35
+ [observability.traces]
36
+ enabled = true
37
+ destinations = ["honeycomb"] # Configure in CF dashboard
38
+ head_sampling_rate = 1.0 # Let autotel handle sampling
39
+ ```
40
+
41
+ ### 2. Instrument Your Worker
42
+
43
+ ```typescript
44
+ import { wrapModule, trace } from 'autotel-cloudflare'
45
+
46
+ // Zero-boilerplate function tracing
47
+ const processOrder = trace(async (orderId: string) => {
48
+ const order = await env.ORDERS_KV.get(orderId) // Auto-instrumented!
49
+ return order
50
+ })
51
+
52
+ export default wrapModule(
53
+ {
54
+ service: { name: 'my-worker' },
55
+ instrumentBindings: true, // Auto-instrument KV, R2, D1, etc.
56
+ sampling: 'adaptive' // 10% baseline, 100% errors/slow
57
+ },
58
+ {
59
+ async fetch(req, env, ctx) {
60
+ return Response.json(await processOrder('123'))
61
+ }
62
+ }
63
+ )
64
+ ```
65
+
66
+ ## API Styles
67
+
68
+ ### Style 1: wrapModule (Recommended)
69
+
70
+ Inspired by workers-honeycomb-logger:
71
+
72
+ ```typescript
73
+ import { wrapModule } from 'autotel-cloudflare'
74
+
75
+ const handler = {
76
+ async fetch(req, env, ctx) {
77
+ return new Response('Hello')
78
+ }
79
+ }
80
+
81
+ export default wrapModule(
82
+ { service: { name: 'my-worker' } },
83
+ handler
84
+ )
85
+ ```
86
+
87
+ ### Style 2: instrument
88
+
89
+ ```typescript
90
+ import { instrument } from 'autotel-cloudflare'
91
+
92
+ export default instrument(
93
+ {
94
+ async fetch(req, env, ctx) {
95
+ return new Response('Hello')
96
+ }
97
+ },
98
+ { service: { name: 'my-worker' } }
99
+ )
100
+ ```
101
+
102
+ ### Style 3: Functional API (Unique)
103
+
104
+ Zero-boilerplate function tracing:
105
+
106
+ ```typescript
107
+ import { trace, span } from 'autotel-cloudflare'
108
+
109
+ // Automatic trace name inference
110
+ export const createUser = trace(async (data: UserData) => {
111
+ return await db.insert(data)
112
+ })
113
+
114
+ // Factory pattern for context access
115
+ export const processPayment = trace(ctx => async (amount: number) => {
116
+ ctx.setAttribute('amount', amount)
117
+
118
+ await span('validate.card', () => validateCard())
119
+ await span('charge.card', () => chargeCard(amount))
120
+
121
+ return { success: true }
122
+ })
123
+ ```
124
+
125
+ ## Complete Bindings Coverage
126
+
127
+ ### Auto-Instrumented Bindings
128
+
129
+ All bindings are automatically instrumented when `instrumentBindings: true`:
130
+
131
+ ```typescript
132
+ // KV
133
+ await env.MY_KV.get('key') // → Span: "KV MY_KV: get"
134
+ await env.MY_KV.put('key', 'value') // → Span: "KV MY_KV: put"
135
+
136
+ // R2
137
+ await env.MY_R2.get('file.txt') // → Span: "R2 MY_R2: get"
138
+ await env.MY_R2.put('file.txt', data) // → Span: "R2 MY_R2: put"
139
+
140
+ // D1
141
+ await env.MY_D1.prepare('SELECT * FROM users').all() // → Span: "D1 MY_D1: all"
142
+
143
+ // Durable Objects
144
+ await env.MY_DO.get(id).fetch(req) // → Span: "DO MY_DO: fetch"
145
+
146
+ // Workers AI
147
+ await env.AI.run('@cf/meta/llama', { prompt: '...' }) // → Span: "AI: run"
148
+
149
+ // Vectorize
150
+ await env.VECTOR.query(vector) // → Span: "Vectorize VECTOR: query"
151
+
152
+ // Service Bindings
153
+ await env.MY_SERVICE.fetch(req) // → Span: "Service MY_SERVICE: fetch"
154
+
155
+ // Queue
156
+ await env.MY_QUEUE.send({ data }) // → Span: "Queue MY_QUEUE: send"
157
+
158
+ // Analytics Engine
159
+ await env.ANALYTICS.writeDataPoint({ ... }) // → Span: "Analytics: writeDataPoint"
160
+ ```
161
+
162
+ **Supported Bindings:**
163
+
164
+ - ✅ KV (get, put, delete, list, getWithMetadata)
165
+ - ✅ R2 (head, get, put, delete, list, createMultipartUpload)
166
+ - ✅ D1 (prepare, batch, exec, dump)
167
+ - ✅ Durable Objects (fetch, alarm)
168
+ - ✅ Workflows (get, create, getInstance)
169
+ - ✅ Workers AI (run)
170
+ - ✅ Vectorize (insert, query, getByIds, deleteByIds, upsert)
171
+ - ✅ Hyperdrive (all queries)
172
+ - ✅ Service Bindings (fetch)
173
+ - ✅ Queue (send, sendBatch)
174
+ - ✅ Analytics Engine (writeDataPoint)
175
+ - ✅ Email (send, forward)
176
+
177
+ ## Sampling Strategies
178
+
179
+ ### Adaptive Sampling (Recommended)
180
+
181
+ ```typescript
182
+ import { SamplingPresets } from 'autotel-cloudflare/sampling'
183
+
184
+ wrapModule(
185
+ {
186
+ service: { name: 'my-worker' },
187
+ sampling: {
188
+ tailSampler: SamplingPresets.production()
189
+ // 10% baseline, 100% errors, 100% slow requests (>1s)
190
+ }
191
+ },
192
+ handler
193
+ )
194
+ ```
195
+
196
+ ### Available Presets
197
+
198
+ ```typescript
199
+ // Development - 100% sampling
200
+ sampling: { tailSampler: SamplingPresets.development() }
201
+
202
+ // Production - 10% baseline, all errors, slow >1s
203
+ sampling: { tailSampler: SamplingPresets.production() }
204
+
205
+ // High traffic - 1% baseline, all errors, slow >1s
206
+ sampling: { tailSampler: SamplingPresets.highTraffic() }
207
+
208
+ // Debugging - errors only
209
+ sampling: { tailSampler: SamplingPresets.debugging() }
210
+
211
+ // Or use shorthand
212
+ sampling: 'adaptive' // Same as SamplingPresets.production()
213
+ sampling: 'error-only' // Same as SamplingPresets.debugging()
214
+ ```
215
+
216
+ ### Custom Sampling
217
+
218
+ ```typescript
219
+ import { createCustomTailSampler } from 'autotel-cloudflare/sampling'
220
+
221
+ const customSampler = createCustomTailSampler((trace) => {
222
+ const span = trace.localRootSpan
223
+
224
+ // Always sample /api/* endpoints
225
+ if (span.attributes['http.route']?.toString().startsWith('/api/')) {
226
+ return true
227
+ }
228
+
229
+ // Sample all errors
230
+ if (span.status.code === SpanStatusCode.ERROR) {
231
+ return true
232
+ }
233
+
234
+ // Sample slow requests
235
+ const duration = (span.endTime[0] - span.startTime[0]) / 1_000_000
236
+ if (duration > 1000) {
237
+ return true
238
+ }
239
+
240
+ return Math.random() < 0.1 // 10% of everything else
241
+ })
242
+ ```
243
+
244
+ ## Durable Objects
245
+
246
+ ### Instrument Durable Object Class
247
+
248
+ ```typescript
249
+ import { wrapDurableObject } from 'autotel-cloudflare'
250
+
251
+ class Counter implements DurableObject {
252
+ async fetch(request: Request) {
253
+ // Auto-traced with span "Counter: fetch"
254
+ const count = await this.state.storage.get('count') || 0
255
+ await this.state.storage.put('count', count + 1)
256
+ return new Response(String(count + 1))
257
+ }
258
+
259
+ async alarm() {
260
+ // Auto-traced with span "Counter: alarm"
261
+ console.log('Alarm triggered')
262
+ }
263
+ }
264
+
265
+ export default wrapDurableObject(
266
+ { service: { name: 'counter-do' } },
267
+ Counter
268
+ )
269
+ ```
270
+
271
+ ## Events Integration
272
+
273
+ Track product events with automatic trace correlation:
274
+
275
+ ```typescript
276
+ import { publishEvent } from 'autotel-cloudflare/events'
277
+
278
+ wrapModule(
279
+ {
280
+ service: { name: 'my-worker' },
281
+ // Configure event subscribers
282
+ subscribers: [
283
+ async (event) => {
284
+ // Send to your analytics platform
285
+ await fetch('https://analytics.example.com/events', {
286
+ method: 'POST',
287
+ body: JSON.stringify(event)
288
+ })
289
+ }
290
+ ]
291
+ },
292
+ {
293
+ async fetch(req, env, ctx) {
294
+ // Track user events
295
+ await publishEvent({
296
+ name: 'order.completed',
297
+ userId: '123',
298
+ properties: {
299
+ orderId: 'abc',
300
+ amount: 99.99
301
+ }
302
+ // Automatically includes current trace ID
303
+ })
304
+
305
+ return new Response('OK')
306
+ }
307
+ }
308
+ )
309
+ ```
310
+
311
+ ## Configuration
312
+
313
+ ### Complete Example
314
+
315
+ ```typescript
316
+ import { wrapModule, SamplingPresets } from 'autotel-cloudflare'
317
+
318
+ export default wrapModule(
319
+ {
320
+ // Service identification
321
+ service: {
322
+ name: 'my-worker',
323
+ version: '1.0.0',
324
+ namespace: 'production'
325
+ },
326
+
327
+ // Auto-instrument bindings
328
+ instrumentBindings: true,
329
+
330
+ // Global instrumentations
331
+ instrumentation: {
332
+ instrumentGlobalFetch: true, // Trace all fetch() calls
333
+ instrumentGlobalCache: true, // Trace cache API
334
+ disabled: false // Set true to disable all tracing
335
+ },
336
+
337
+ // Sampling strategy
338
+ sampling: {
339
+ tailSampler: SamplingPresets.production()
340
+ },
341
+
342
+ // Handler-specific config
343
+ handlers: {
344
+ fetch: {
345
+ postProcess: (span, { request, response }) => {
346
+ // Add custom attributes
347
+ const url = new URL(request.url)
348
+ if (url.pathname.startsWith('/api/')) {
349
+ span.setAttribute('api.endpoint', url.pathname)
350
+ }
351
+ }
352
+ }
353
+ }
354
+ },
355
+ handler
356
+ )
357
+ ```
358
+
359
+ ### Dynamic Configuration
360
+
361
+ ```typescript
362
+ // Configuration can be a function
363
+ export default wrapModule(
364
+ (env, trigger) => ({
365
+ service: { name: env.SERVICE_NAME || 'my-worker' },
366
+ exporter: {
367
+ url: env.OTEL_ENDPOINT,
368
+ headers: { 'x-api-key': env.API_KEY }
369
+ },
370
+ sampling: {
371
+ tailSampler: env.ENVIRONMENT === 'production'
372
+ ? SamplingPresets.production()
373
+ : SamplingPresets.development()
374
+ }
375
+ }),
376
+ handler
377
+ )
378
+ ```
379
+
380
+ ## Entry Points (Tree-Shaking)
381
+
382
+ ```typescript
383
+ // Main export (everything)
384
+ import { wrapModule, trace, instrument } from 'autotel-cloudflare'
385
+
386
+ // Tree-shakeable entry points
387
+ import { instrumentKV, instrumentR2 } from 'autotel-cloudflare/bindings'
388
+ import { instrumentDO } from 'autotel-cloudflare/handlers'
389
+ import { SamplingPresets } from 'autotel-cloudflare/sampling'
390
+ import { publishEvent } from 'autotel-cloudflare/events'
391
+ import { createEdgeLogger } from 'autotel-cloudflare/logger'
392
+ import { createTraceCollector } from 'autotel-cloudflare/testing'
393
+ ```
394
+
395
+ ## Testing
396
+
397
+ ```typescript
398
+ import { createTraceCollector, assertTraceCreated } from 'autotel-cloudflare/testing'
399
+
400
+ describe('my worker', () => {
401
+ it('creates traces', async () => {
402
+ const collector = createTraceCollector()
403
+
404
+ await myFunction()
405
+
406
+ assertTraceCreated(collector, 'myFunction')
407
+ })
408
+ })
409
+ ```
410
+
411
+ ## Examples
412
+
413
+ See [apps/cloudflare-example](../../apps/cloudflare-example) for a complete working example with:
414
+
415
+ - ✅ All bindings instrumented (KV, R2, D1, etc.)
416
+ - ✅ Multiple handler types (fetch, scheduled, queue, email)
417
+ - ✅ Durable Objects
418
+ - ✅ Custom spans and attributes
419
+ - ✅ Error handling
420
+ - ✅ Sampling strategies
421
+ - ✅ Events tracking
422
+
423
+ ## License
424
+
425
+ MIT © [Jag Reehal](https://github.com/jagreehal)
426
+
427
+ ## Links
428
+
429
+ - [GitHub Repository](https://github.com/jagreehal/autotel)
430
+ - [Documentation](https://github.com/jagreehal/autotel#readme)
431
+ - [Issues](https://github.com/jagreehal/autotel/issues)
432
+ - [autotel-edge](../autotel-edge) - Vendor-agnostic foundation
@@ -0,0 +1,248 @@
1
+ import { ConfigurationOption } from 'autotel-edge';
2
+
3
+ /**
4
+ * Type definitions for @cloudflare/actors integration
5
+ */
6
+
7
+ /**
8
+ * Actor-specific instrumentation options
9
+ */
10
+ interface ActorInstrumentationOptions {
11
+ /**
12
+ * Whether to instrument storage operations (sql queries, etc.)
13
+ * @default true
14
+ */
15
+ instrumentStorage?: boolean;
16
+ /**
17
+ * Whether to instrument alarm operations
18
+ * @default true
19
+ */
20
+ instrumentAlarms?: boolean;
21
+ /**
22
+ * Whether to instrument socket operations
23
+ * @default true
24
+ */
25
+ instrumentSockets?: boolean;
26
+ /**
27
+ * Whether to capture persist events as spans
28
+ * @default true
29
+ */
30
+ capturePersistEvents?: boolean;
31
+ /**
32
+ * Custom span name formatter for lifecycle methods
33
+ */
34
+ spanNameFormatter?: (actorName: string, lifecycle: string) => string;
35
+ }
36
+ /**
37
+ * Actor-specific configuration
38
+ * Can be a static config object with actors options, or a function that returns config
39
+ */
40
+ type ActorConfig = ConfigurationOption & {
41
+ /**
42
+ * Actor-specific instrumentation options
43
+ */
44
+ actors?: ActorInstrumentationOptions;
45
+ };
46
+ /**
47
+ * Actor lifecycle events that can be traced
48
+ */
49
+ type ActorLifecycle = 'init' | 'request' | 'alarm' | 'persist' | 'websocket.connect' | 'websocket.message' | 'websocket.disconnect' | 'websocket.upgrade' | 'destroy';
50
+ /**
51
+ * Minimal interface matching @cloudflare/actors Actor class
52
+ * We don't import the actual type to avoid coupling
53
+ */
54
+ interface ActorLike {
55
+ name?: string;
56
+ identifier?: string;
57
+ storage?: unknown;
58
+ alarms?: unknown;
59
+ sockets?: unknown;
60
+ fetch?(request: Request): Promise<Response>;
61
+ alarm?(alarmInfo?: unknown): Promise<void>;
62
+ }
63
+ /**
64
+ * Constructor type for Actor classes
65
+ */
66
+ type ActorConstructor<T extends ActorLike = ActorLike> = new (state: DurableObjectState, env: unknown) => T;
67
+
68
+ /**
69
+ * Actor class instrumentation for @cloudflare/actors
70
+ *
71
+ * Wraps Actor lifecycle methods with OpenTelemetry tracing:
72
+ * - onInit: Traced as 'actor.lifecycle': 'init'
73
+ * - onRequest: Traced with full HTTP semantics
74
+ * - onAlarm: Traced as 'actor.lifecycle': 'alarm'
75
+ * - onPersist: Traced as 'actor.lifecycle': 'persist'
76
+ * - WebSocket methods: Traced with socket semantics
77
+ */
78
+
79
+ /**
80
+ * Instrument an Actor class for comprehensive OpenTelemetry tracing
81
+ *
82
+ * This wraps the Actor class to automatically trace all lifecycle methods:
83
+ * - onInit: Actor initialization
84
+ * - onRequest: HTTP request handling
85
+ * - onAlarm: Alarm triggers
86
+ * - onPersist: Property persistence events
87
+ * - WebSocket methods: Connection, message, disconnect
88
+ *
89
+ * It also optionally instruments:
90
+ * - actor.storage: SQL queries and storage operations
91
+ * - actor.alarms: Alarm scheduling operations
92
+ * - actor.sockets: WebSocket operations
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * import { Actor } from '@cloudflare/actors'
97
+ * import { instrumentActor } from 'autotel-cloudflare/actors'
98
+ *
99
+ * class Counter extends Actor<Env> {
100
+ * protected onInit() {
101
+ * console.log('Counter initialized')
102
+ * }
103
+ *
104
+ * protected onRequest(request: Request) {
105
+ * return new Response('count: 42')
106
+ * }
107
+ * }
108
+ *
109
+ * // Wrap the class
110
+ * export const InstrumentedCounter = instrumentActor(Counter, (env: Env) => ({
111
+ * service: { name: 'counter-actor' },
112
+ * exporter: { url: env.OTLP_ENDPOINT },
113
+ * actors: {
114
+ * instrumentStorage: true,
115
+ * capturePersistEvents: true
116
+ * }
117
+ * }))
118
+ * ```
119
+ *
120
+ * @param actorClass - The Actor class to instrument
121
+ * @param config - Configuration (static object or function)
122
+ * @returns Instrumented Actor class
123
+ */
124
+ declare function instrumentActor<C extends ActorConstructor>(actorClass: C, config: ActorConfig | ((env: unknown, trigger?: unknown) => ActorConfig)): C;
125
+
126
+ /**
127
+ * Traced handler wrapper for @cloudflare/actors
128
+ *
129
+ * Wraps the Actors handler() to provide:
130
+ * - Root span for the entire request lifecycle
131
+ * - Actor name extraction and correlation
132
+ * - Request routing tracing
133
+ */
134
+
135
+ /**
136
+ * Worker handler type matching @cloudflare/actors output
137
+ */
138
+ interface WorkerHandler<E = unknown> {
139
+ fetch(request: Request, env: E, ctx: ExecutionContext): Promise<Response>;
140
+ }
141
+ /**
142
+ * Create a traced handler that combines Actor instrumentation with request tracing
143
+ *
144
+ * This is an all-in-one wrapper that:
145
+ * 1. Initializes telemetry for the Worker
146
+ * 2. Creates a root span for each incoming request
147
+ * 3. Extracts the Actor name using `nameFromRequest`
148
+ * 4. Instruments the Actor class with lifecycle tracing
149
+ * 5. Routes the request to the instrumented Actor
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * import { Actor } from '@cloudflare/actors'
154
+ * import { tracedHandler } from 'autotel-cloudflare/actors'
155
+ *
156
+ * class MyActor extends Actor<Env> {
157
+ * protected onRequest(request: Request) {
158
+ * return new Response('Hello!')
159
+ * }
160
+ * }
161
+ *
162
+ * // Export the Actor class and use tracedHandler
163
+ * export { MyActor }
164
+ * export default tracedHandler(MyActor, (env) => ({
165
+ * service: { name: 'my-actor-service' },
166
+ * exporter: { url: env.OTLP_ENDPOINT }
167
+ * }))
168
+ * ```
169
+ *
170
+ * @param actorClass - The Actor class to handle requests
171
+ * @param config - Configuration (static object or function)
172
+ * @returns A Worker handler with full tracing
173
+ */
174
+ declare function tracedHandler<E, A extends ActorLike>(actorClass: ActorConstructor<A> & {
175
+ nameFromRequest?(request: Request): Promise<string | undefined>;
176
+ configuration?(request: Request): {
177
+ locationHint?: DurableObjectLocationHint;
178
+ };
179
+ }, config: ActorConfig | ((env: E, trigger?: unknown) => ActorConfig)): WorkerHandler<E>;
180
+ /**
181
+ * Alternative: Create a handler wrapper that uses the existing @cloudflare/actors handler
182
+ *
183
+ * This is useful if you want to use the original handler() but add tracing around it.
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * import { Actor, handler } from '@cloudflare/actors'
188
+ * import { wrapHandler } from 'autotel-cloudflare/actors'
189
+ *
190
+ * class MyActor extends Actor<Env> {}
191
+ *
192
+ * export { MyActor }
193
+ * export default wrapHandler(handler(MyActor), (env) => ({
194
+ * service: { name: 'my-service' }
195
+ * }))
196
+ * ```
197
+ */
198
+ declare function wrapHandler<E>(originalHandler: WorkerHandler<E>, config: ActorConfig | ((env: E, trigger?: unknown) => ActorConfig)): WorkerHandler<E>;
199
+
200
+ /**
201
+ * Actor storage instrumentation
202
+ *
203
+ * Traces operations on actor.storage including SQL queries
204
+ */
205
+
206
+ /**
207
+ * Instrument Actor storage for tracing
208
+ *
209
+ * Captures:
210
+ * - SQL query operations
211
+ * - Key-value operations (if available)
212
+ */
213
+ declare function instrumentActorStorage(storage: unknown, actorInstance: ActorLike, actorClass: object): unknown;
214
+
215
+ /**
216
+ * Actor alarms instrumentation
217
+ *
218
+ * Traces operations on actor.alarms
219
+ */
220
+
221
+ /**
222
+ * Instrument Actor alarms for tracing
223
+ *
224
+ * Captures:
225
+ * - set: Schedule a single alarm
226
+ * - setMultiple: Schedule multiple alarms
227
+ * - cancel: Cancel an alarm
228
+ * - cancelAll: Cancel all alarms
229
+ */
230
+ declare function instrumentActorAlarms(alarms: unknown, actorInstance: ActorLike, actorClass: object): unknown;
231
+
232
+ /**
233
+ * Actor sockets instrumentation
234
+ *
235
+ * Traces operations on actor.sockets
236
+ */
237
+
238
+ /**
239
+ * Instrument Actor sockets for tracing
240
+ *
241
+ * Captures:
242
+ * - acceptWebSocket: Accept an incoming WebSocket connection
243
+ * - broadcast: Send message to all connected sockets
244
+ * - send: Send message to a specific socket
245
+ */
246
+ declare function instrumentActorSockets(sockets: unknown, actorInstance: ActorLike, actorClass: object): unknown;
247
+
248
+ export { type ActorConfig, type ActorInstrumentationOptions, type ActorLifecycle, instrumentActor, instrumentActorAlarms, instrumentActorSockets, instrumentActorStorage, tracedHandler, wrapHandler };