@mertdogar/otel-cf-workers 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2302 @@
1
+ // src/buffer.ts
2
+ import { Buffer } from "node:buffer";
3
+ globalThis.Buffer = Buffer;
4
+
5
+ // src/sampling.ts
6
+ import { TraceFlags, SpanStatusCode } from "@opentelemetry/api";
7
+ import { ParentBasedSampler, TraceIdRatioBasedSampler } from "@opentelemetry/sdk-trace-base";
8
+ function multiTailSampler(samplers) {
9
+ return (traceInfo) => {
10
+ return samplers.reduce((result, sampler) => result || sampler(traceInfo), false);
11
+ };
12
+ }
13
+ var isHeadSampled = (traceInfo) => {
14
+ const localRootSpan = traceInfo.localRootSpan;
15
+ return (localRootSpan.spanContext().traceFlags & TraceFlags.SAMPLED) === TraceFlags.SAMPLED;
16
+ };
17
+ var isRootErrorSpan = (traceInfo) => {
18
+ const localRootSpan = traceInfo.localRootSpan;
19
+ return localRootSpan.status.code === SpanStatusCode.ERROR;
20
+ };
21
+ function createSampler(conf) {
22
+ const ratioSampler = new TraceIdRatioBasedSampler(conf.ratio);
23
+ if (typeof conf.acceptRemote === "boolean" && !conf.acceptRemote) {
24
+ return new ParentBasedSampler({
25
+ root: ratioSampler,
26
+ remoteParentSampled: ratioSampler,
27
+ remoteParentNotSampled: ratioSampler
28
+ });
29
+ } else {
30
+ return new ParentBasedSampler({ root: ratioSampler });
31
+ }
32
+ }
33
+
34
+ // src/sdk.ts
35
+ import { context as api_context4, propagation as propagation2, SpanStatusCode as SpanStatusCode6, trace as trace12 } from "@opentelemetry/api";
36
+ import { resourceFromAttributes } from "@opentelemetry/resources";
37
+
38
+ // src/config.ts
39
+ import { context } from "@opentelemetry/api";
40
+
41
+ // src/types.ts
42
+ function isSpanProcessorConfig(config) {
43
+ return !!config.spanProcessors;
44
+ }
45
+
46
+ // src/config.ts
47
+ import { W3CTraceContextPropagator } from "@opentelemetry/core";
48
+
49
+ // src/exporter.ts
50
+ import { ExportResultCode } from "@opentelemetry/core";
51
+ import { OTLPExporterError } from "@opentelemetry/otlp-exporter-base";
52
+ import { JsonTraceSerializer } from "@opentelemetry/otlp-transformer";
53
+
54
+ // src/wrap.ts
55
+ var unwrapSymbol = Symbol("unwrap");
56
+ function isWrapped(item) {
57
+ return item && !!item[unwrapSymbol];
58
+ }
59
+ function isProxyable(item) {
60
+ return item !== null && typeof item === "object" || typeof item === "function";
61
+ }
62
+ function wrap(item, handler, autoPassthrough = true) {
63
+ if (isWrapped(item) || !isProxyable(item)) {
64
+ return item;
65
+ }
66
+ const proxyHandler = Object.assign({}, handler);
67
+ proxyHandler.get = (target, prop, receiver) => {
68
+ if (prop === unwrapSymbol) {
69
+ return item;
70
+ } else {
71
+ if (handler.get) {
72
+ return handler.get(target, prop, receiver);
73
+ } else if (prop === "bind") {
74
+ return () => receiver;
75
+ } else if (autoPassthrough) {
76
+ return passthroughGet(target, prop);
77
+ }
78
+ }
79
+ };
80
+ proxyHandler.apply = (target, thisArg, argArray) => {
81
+ if (handler.apply) {
82
+ return handler.apply(unwrap(target), unwrap(thisArg), argArray);
83
+ }
84
+ };
85
+ return new Proxy(item, proxyHandler);
86
+ }
87
+ function unwrap(item) {
88
+ if (item && isWrapped(item)) {
89
+ return item[unwrapSymbol];
90
+ } else {
91
+ return item;
92
+ }
93
+ }
94
+ function passthroughGet(target, prop, thisArg) {
95
+ const unwrappedTarget = unwrap(target);
96
+ thisArg = unwrap(thisArg) || unwrappedTarget;
97
+ const value = Reflect.get(unwrappedTarget, prop);
98
+ if (typeof value === "function") {
99
+ if (value.constructor.name === "RpcProperty") {
100
+ return (...args) => unwrappedTarget[prop](...args);
101
+ }
102
+ return value.bind(thisArg);
103
+ } else {
104
+ return value;
105
+ }
106
+ }
107
+
108
+ // versions.json
109
+ var _mertdogar_otel_cf_workers = "1.0.1";
110
+ var node = "25.1.0";
111
+
112
+ // src/exporter.ts
113
+ var defaultHeaders = {
114
+ accept: "application/json",
115
+ "content-type": "application/json",
116
+ "user-agent": `Cloudflare Worker @mertdogar/otel-cf-workers v${_mertdogar_otel_cf_workers}`
117
+ };
118
+ var OTLPExporter = class {
119
+ headers;
120
+ url;
121
+ constructor(config) {
122
+ this.url = config.url;
123
+ this.headers = Object.assign({}, defaultHeaders, config.headers);
124
+ }
125
+ export(items, resultCallback) {
126
+ this._export(items).then(() => {
127
+ resultCallback({ code: ExportResultCode.SUCCESS });
128
+ }).catch((error) => {
129
+ resultCallback({ code: ExportResultCode.FAILED, error });
130
+ });
131
+ }
132
+ _export(items) {
133
+ return new Promise((resolve, reject) => {
134
+ try {
135
+ this.send(items, resolve, reject);
136
+ } catch (e) {
137
+ reject(e);
138
+ }
139
+ });
140
+ }
141
+ send(items, onSuccess, onError) {
142
+ const decoder = new TextDecoder();
143
+ const exportMessage = JsonTraceSerializer.serializeRequest(items);
144
+ const body = decoder.decode(exportMessage);
145
+ const params = {
146
+ method: "POST",
147
+ headers: this.headers,
148
+ body
149
+ };
150
+ unwrap(fetch)(this.url, params).then((response) => {
151
+ if (response.ok) {
152
+ onSuccess();
153
+ } else {
154
+ onError(new OTLPExporterError(`Exporter received a statusCode: ${response.status}`));
155
+ }
156
+ }).catch((error) => {
157
+ onError(new OTLPExporterError(`Exception during export: ${error.toString()}`, error.code, error.stack));
158
+ });
159
+ }
160
+ async shutdown() {
161
+ }
162
+ };
163
+
164
+ // src/spanprocessor.ts
165
+ import { ExportResultCode as ExportResultCode2 } from "@opentelemetry/core";
166
+ function getSampler() {
167
+ const conf = getActiveConfig();
168
+ if (!conf) {
169
+ console.log("Could not find config for sampling, sending everything by default");
170
+ }
171
+ return conf ? conf.sampling.tailSampler : () => true;
172
+ }
173
+ var TraceState = class {
174
+ unexportedSpans = [];
175
+ inprogressSpans = /* @__PURE__ */ new Set();
176
+ exporter;
177
+ exportPromises = [];
178
+ localRootSpan;
179
+ traceDecision;
180
+ constructor(exporter) {
181
+ this.exporter = exporter;
182
+ }
183
+ addSpan(span) {
184
+ const readableSpan = span;
185
+ this.localRootSpan = this.localRootSpan || readableSpan;
186
+ this.unexportedSpans.push(readableSpan);
187
+ this.inprogressSpans.add(span.spanContext().spanId);
188
+ }
189
+ endSpan(span) {
190
+ this.inprogressSpans.delete(span.spanContext().spanId);
191
+ if (this.inprogressSpans.size === 0) {
192
+ this.flush();
193
+ }
194
+ }
195
+ sample() {
196
+ if (this.traceDecision === void 0 && this.unexportedSpans.length > 0) {
197
+ const sampler = getSampler();
198
+ this.traceDecision = sampler({
199
+ traceId: this.localRootSpan.spanContext().traceId,
200
+ localRootSpan: this.localRootSpan,
201
+ spans: this.unexportedSpans
202
+ });
203
+ }
204
+ this.unexportedSpans = this.traceDecision ? this.unexportedSpans : [];
205
+ }
206
+ async flush() {
207
+ if (this.unexportedSpans.length > 0) {
208
+ const unfinishedSpans = this.unexportedSpans.filter((span) => this.isSpanInProgress(span));
209
+ for (const span of unfinishedSpans) {
210
+ console.log(`Span ${span.spanContext().spanId} was not ended properly`);
211
+ span.end();
212
+ }
213
+ this.sample();
214
+ this.exportPromises.push(this.exportSpans(this.unexportedSpans));
215
+ this.unexportedSpans = [];
216
+ }
217
+ if (this.exportPromises.length > 0) {
218
+ await Promise.allSettled(this.exportPromises);
219
+ }
220
+ }
221
+ isSpanInProgress(span) {
222
+ return this.inprogressSpans.has(span.spanContext().spanId);
223
+ }
224
+ async exportSpans(spans) {
225
+ const config = getActiveConfig();
226
+ if (!config) {
227
+ console.log("Could not find config for exporting, skipping export");
228
+ return;
229
+ }
230
+ await scheduler.wait(1);
231
+ const promise = new Promise((resolve, reject) => {
232
+ this.exporter.export(spans, (result) => {
233
+ if (result.code === ExportResultCode2.SUCCESS) {
234
+ resolve();
235
+ } else {
236
+ console.log("exporting spans failed! " + result.error);
237
+ reject(result.error);
238
+ }
239
+ });
240
+ });
241
+ await promise;
242
+ }
243
+ };
244
+ var BatchTraceSpanProcessor = class {
245
+ constructor(exporter) {
246
+ this.exporter = exporter;
247
+ }
248
+ traces = {};
249
+ getTraceState(traceId) {
250
+ const traceState = this.traces[traceId] || new TraceState(this.exporter);
251
+ this.traces[traceId] = traceState;
252
+ return traceState;
253
+ }
254
+ onStart(span, _parentContext) {
255
+ const traceId = span.spanContext().traceId;
256
+ this.getTraceState(traceId).addSpan(span);
257
+ }
258
+ onEnd(span) {
259
+ const traceId = span.spanContext().traceId;
260
+ this.getTraceState(traceId).endSpan(span);
261
+ }
262
+ async forceFlush(traceId) {
263
+ if (traceId) {
264
+ await this.getTraceState(traceId).flush();
265
+ } else {
266
+ const promises = Object.values(this.traces).map((traceState) => traceState.flush);
267
+ await Promise.allSettled(promises);
268
+ }
269
+ }
270
+ async shutdown() {
271
+ await this.forceFlush();
272
+ }
273
+ };
274
+
275
+ // src/config.ts
276
+ var configSymbol = Symbol("Otel Workers Tracing Configuration");
277
+ function setConfig(config, ctx = context.active()) {
278
+ return ctx.setValue(configSymbol, config);
279
+ }
280
+ function getActiveConfig() {
281
+ const config = context.active().getValue(configSymbol);
282
+ return config || void 0;
283
+ }
284
+ function isSpanExporter(exporterConfig) {
285
+ return !!exporterConfig.export;
286
+ }
287
+ function isSampler(sampler) {
288
+ return !!sampler.shouldSample;
289
+ }
290
+ function parseConfig(supplied) {
291
+ if (isSpanProcessorConfig(supplied)) {
292
+ const headSampleConf = supplied.sampling?.headSampler || { ratio: 1 };
293
+ const headSampler = isSampler(headSampleConf) ? headSampleConf : createSampler(headSampleConf);
294
+ const spanProcessors = Array.isArray(supplied.spanProcessors) ? supplied.spanProcessors : [supplied.spanProcessors];
295
+ if (spanProcessors.length === 0) {
296
+ console.log(
297
+ "Warning! You must either specify an exporter or your own SpanProcessor(s)/Exporter combination in the open-telemetry configuration."
298
+ );
299
+ }
300
+ return {
301
+ fetch: {
302
+ includeTraceContext: supplied.fetch?.includeTraceContext ?? true
303
+ },
304
+ handlers: {
305
+ fetch: {
306
+ acceptTraceContext: supplied.handlers?.fetch?.acceptTraceContext ?? true
307
+ }
308
+ },
309
+ postProcessor: supplied.postProcessor || ((spans) => spans),
310
+ sampling: {
311
+ headSampler,
312
+ tailSampler: supplied.sampling?.tailSampler || multiTailSampler([isHeadSampled, isRootErrorSpan])
313
+ },
314
+ service: supplied.service,
315
+ spanProcessors,
316
+ propagator: supplied.propagator || new W3CTraceContextPropagator(),
317
+ instrumentation: {
318
+ instrumentGlobalCache: supplied.instrumentation?.instrumentGlobalCache ?? true,
319
+ instrumentGlobalFetch: supplied.instrumentation?.instrumentGlobalFetch ?? true
320
+ }
321
+ };
322
+ } else {
323
+ const exporter = isSpanExporter(supplied.exporter) ? supplied.exporter : new OTLPExporter(supplied.exporter);
324
+ const spanProcessors = [new BatchTraceSpanProcessor(exporter)];
325
+ const newConfig = Object.assign(supplied, { exporter: void 0, spanProcessors });
326
+ return parseConfig(newConfig);
327
+ }
328
+ }
329
+
330
+ // src/provider.ts
331
+ import { context as context2, trace as trace2 } from "@opentelemetry/api";
332
+
333
+ // src/context.ts
334
+ import { ROOT_CONTEXT } from "@opentelemetry/api";
335
+ import { AsyncLocalStorage } from "node:async_hooks";
336
+ import { EventEmitter } from "node:events";
337
+ var ADD_LISTENER_METHODS = [
338
+ "addListener",
339
+ "on",
340
+ "once",
341
+ "prependListener",
342
+ "prependOnceListener"
343
+ ];
344
+ var AbstractAsyncHooksContextManager = class {
345
+ /**
346
+ * Binds a the certain context or the active one to the target function and then returns the target
347
+ * @param context A context (span) to be bind to target
348
+ * @param target a function or event emitter. When target or one of its callbacks is called,
349
+ * the provided context will be used as the active context for the duration of the call.
350
+ */
351
+ bind(context3, target) {
352
+ if (target instanceof EventEmitter) {
353
+ return this._bindEventEmitter(context3, target);
354
+ }
355
+ if (typeof target === "function") {
356
+ return this._bindFunction(context3, target);
357
+ }
358
+ return target;
359
+ }
360
+ _bindFunction(context3, target) {
361
+ const manager = this;
362
+ const contextWrapper = function(...args) {
363
+ return manager.with(context3, () => target.apply(this, args));
364
+ };
365
+ Object.defineProperty(contextWrapper, "length", {
366
+ enumerable: false,
367
+ configurable: true,
368
+ writable: false,
369
+ value: target.length
370
+ });
371
+ return contextWrapper;
372
+ }
373
+ /**
374
+ * By default, EventEmitter call their callback with their context, which we do
375
+ * not want, instead we will bind a specific context to all callbacks that
376
+ * go through it.
377
+ * @param context the context we want to bind
378
+ * @param ee EventEmitter an instance of EventEmitter to patch
379
+ */
380
+ _bindEventEmitter(context3, ee) {
381
+ const map = this._getPatchMap(ee);
382
+ if (map !== void 0) return ee;
383
+ this._createPatchMap(ee);
384
+ ADD_LISTENER_METHODS.forEach((methodName) => {
385
+ if (ee[methodName] === void 0) return;
386
+ ee[methodName] = this._patchAddListener(ee, ee[methodName], context3);
387
+ });
388
+ if (typeof ee.removeListener === "function") {
389
+ ee.removeListener = this._patchRemoveListener(ee, ee.removeListener);
390
+ }
391
+ if (typeof ee.off === "function") {
392
+ ee.off = this._patchRemoveListener(ee, ee.off);
393
+ }
394
+ if (typeof ee.removeAllListeners === "function") {
395
+ ee.removeAllListeners = this._patchRemoveAllListeners(ee, ee.removeAllListeners);
396
+ }
397
+ return ee;
398
+ }
399
+ /**
400
+ * Patch methods that remove a given listener so that we match the "patched"
401
+ * version of that listener (the one that propagate context).
402
+ * @param ee EventEmitter instance
403
+ * @param original reference to the patched method
404
+ */
405
+ _patchRemoveListener(ee, original) {
406
+ const contextManager = this;
407
+ return function(event, listener) {
408
+ const events = contextManager._getPatchMap(ee)?.[event];
409
+ if (events === void 0) {
410
+ return original.call(this, event, listener);
411
+ }
412
+ const patchedListener = events.get(listener);
413
+ return original.call(this, event, patchedListener || listener);
414
+ };
415
+ }
416
+ /**
417
+ * Patch methods that remove all listeners so we remove our
418
+ * internal references for a given event.
419
+ * @param ee EventEmitter instance
420
+ * @param original reference to the patched method
421
+ */
422
+ _patchRemoveAllListeners(ee, original) {
423
+ const contextManager = this;
424
+ return function(event) {
425
+ const map = contextManager._getPatchMap(ee);
426
+ if (map !== void 0) {
427
+ if (arguments.length === 0) {
428
+ contextManager._createPatchMap(ee);
429
+ } else if (map[event] !== void 0) {
430
+ delete map[event];
431
+ }
432
+ }
433
+ return original.apply(this, arguments);
434
+ };
435
+ }
436
+ /**
437
+ * Patch methods on an event emitter instance that can add listeners so we
438
+ * can force them to propagate a given context.
439
+ * @param ee EventEmitter instance
440
+ * @param original reference to the patched method
441
+ * @param [context] context to propagate when calling listeners
442
+ */
443
+ _patchAddListener(ee, original, context3) {
444
+ const contextManager = this;
445
+ return function(event, listener) {
446
+ if (contextManager._wrapped) {
447
+ return original.call(this, event, listener);
448
+ }
449
+ let map = contextManager._getPatchMap(ee);
450
+ if (map === void 0) {
451
+ map = contextManager._createPatchMap(ee);
452
+ }
453
+ let listeners = map[event];
454
+ if (listeners === void 0) {
455
+ listeners = /* @__PURE__ */ new WeakMap();
456
+ map[event] = listeners;
457
+ }
458
+ const patchedListener = contextManager.bind(context3, listener);
459
+ listeners.set(listener, patchedListener);
460
+ contextManager._wrapped = true;
461
+ try {
462
+ return original.call(this, event, patchedListener);
463
+ } finally {
464
+ contextManager._wrapped = false;
465
+ }
466
+ };
467
+ }
468
+ _createPatchMap(ee) {
469
+ const map = /* @__PURE__ */ Object.create(null);
470
+ ee[this._kOtListeners] = map;
471
+ return map;
472
+ }
473
+ _getPatchMap(ee) {
474
+ return ee[this._kOtListeners];
475
+ }
476
+ _kOtListeners = Symbol("OtListeners");
477
+ _wrapped = false;
478
+ };
479
+ var AsyncLocalStorageContextManager = class extends AbstractAsyncHooksContextManager {
480
+ _asyncLocalStorage;
481
+ constructor() {
482
+ super();
483
+ this._asyncLocalStorage = new AsyncLocalStorage();
484
+ }
485
+ active() {
486
+ return this._asyncLocalStorage.getStore() ?? ROOT_CONTEXT;
487
+ }
488
+ with(context3, fn, thisArg, ...args) {
489
+ const cb = thisArg == null ? fn : fn.bind(thisArg);
490
+ return this._asyncLocalStorage.run(context3, cb, ...args);
491
+ }
492
+ enable() {
493
+ return this;
494
+ }
495
+ disable() {
496
+ this._asyncLocalStorage.disable();
497
+ return this;
498
+ }
499
+ };
500
+
501
+ // src/tracer.ts
502
+ import {
503
+ TraceFlags as TraceFlags2,
504
+ SpanKind as SpanKind2,
505
+ context as api_context,
506
+ trace
507
+ } from "@opentelemetry/api";
508
+ import { sanitizeAttributes as sanitizeAttributes2 } from "@opentelemetry/core";
509
+ import { RandomIdGenerator, SamplingDecision } from "@opentelemetry/sdk-trace-base";
510
+
511
+ // src/span.ts
512
+ import {
513
+ SpanKind,
514
+ SpanStatusCode as SpanStatusCode2
515
+ } from "@opentelemetry/api";
516
+ import {
517
+ hrTimeDuration,
518
+ isAttributeValue,
519
+ isTimeInput,
520
+ sanitizeAttributes
521
+ } from "@opentelemetry/core";
522
+ import { SemanticAttributes } from "@opentelemetry/semantic-conventions";
523
+ function transformExceptionAttributes(exception) {
524
+ const attributes = {};
525
+ if (typeof exception === "string") {
526
+ attributes[SemanticAttributes.EXCEPTION_MESSAGE] = exception;
527
+ } else {
528
+ if (exception.code) {
529
+ attributes[SemanticAttributes.EXCEPTION_TYPE] = exception.code.toString();
530
+ } else if (exception.name) {
531
+ attributes[SemanticAttributes.EXCEPTION_TYPE] = exception.name;
532
+ }
533
+ if (exception.message) {
534
+ attributes[SemanticAttributes.EXCEPTION_MESSAGE] = exception.message;
535
+ }
536
+ if (exception.stack) {
537
+ attributes[SemanticAttributes.EXCEPTION_STACKTRACE] = exception.stack;
538
+ }
539
+ }
540
+ return attributes;
541
+ }
542
+ function millisToHr(millis) {
543
+ return [Math.trunc(millis / 1e3), millis % 1e3 * 1e6];
544
+ }
545
+ function getHrTime(input) {
546
+ const now = Date.now();
547
+ if (!input) {
548
+ return millisToHr(now);
549
+ } else if (input instanceof Date) {
550
+ return millisToHr(input.getTime());
551
+ } else if (typeof input === "number") {
552
+ return millisToHr(input);
553
+ } else if (Array.isArray(input)) {
554
+ return input;
555
+ }
556
+ const v = input;
557
+ throw new Error(`unreachable value: ${JSON.stringify(v)}`);
558
+ }
559
+ function isAttributeKey(key) {
560
+ return typeof key === "string" && key.length > 0;
561
+ }
562
+ var SpanImpl = class {
563
+ name;
564
+ _spanContext;
565
+ onEnd;
566
+ parentSpanId;
567
+ parentSpanContext;
568
+ kind;
569
+ attributes;
570
+ status = {
571
+ code: SpanStatusCode2.UNSET
572
+ };
573
+ endTime = [0, 0];
574
+ _duration = [0, 0];
575
+ startTime;
576
+ events = [];
577
+ links;
578
+ resource;
579
+ instrumentationScope = { name: "@mertdogar/otel-cf-workers" };
580
+ _ended = false;
581
+ _droppedAttributesCount = 0;
582
+ _droppedEventsCount = 0;
583
+ _droppedLinksCount = 0;
584
+ constructor(init2) {
585
+ this.name = init2.name;
586
+ this._spanContext = init2.spanContext;
587
+ this.parentSpanId = init2.parentSpanId;
588
+ this.parentSpanContext = init2.parentSpanContext;
589
+ this.kind = init2.spanKind || SpanKind.INTERNAL;
590
+ this.attributes = sanitizeAttributes(init2.attributes);
591
+ this.startTime = getHrTime(init2.startTime);
592
+ this.links = init2.links || [];
593
+ this.resource = init2.resource;
594
+ this.onEnd = init2.onEnd;
595
+ }
596
+ addLink(link) {
597
+ this.links.push(link);
598
+ return this;
599
+ }
600
+ addLinks(links) {
601
+ this.links.push(...links);
602
+ return this;
603
+ }
604
+ spanContext() {
605
+ return this._spanContext;
606
+ }
607
+ setAttribute(key, value) {
608
+ if (isAttributeKey(key) && isAttributeValue(value)) {
609
+ this.attributes[key] = value;
610
+ }
611
+ return this;
612
+ }
613
+ setAttributes(attributes) {
614
+ for (const [key, value] of Object.entries(attributes)) {
615
+ this.setAttribute(key, value);
616
+ }
617
+ return this;
618
+ }
619
+ addEvent(name, attributesOrStartTime, startTime) {
620
+ if (isTimeInput(attributesOrStartTime)) {
621
+ startTime = attributesOrStartTime;
622
+ attributesOrStartTime = void 0;
623
+ }
624
+ const attributes = sanitizeAttributes(attributesOrStartTime);
625
+ const time = getHrTime(startTime);
626
+ this.events.push({ name, attributes, time });
627
+ return this;
628
+ }
629
+ setStatus(status) {
630
+ this.status = status;
631
+ return this;
632
+ }
633
+ updateName(name) {
634
+ this.name = name;
635
+ return this;
636
+ }
637
+ end(endTime) {
638
+ if (this._ended) {
639
+ return;
640
+ }
641
+ this._ended = true;
642
+ this.endTime = getHrTime(endTime);
643
+ this._duration = hrTimeDuration(this.startTime, this.endTime);
644
+ this.onEnd(this);
645
+ }
646
+ isRecording() {
647
+ return !this._ended;
648
+ }
649
+ recordException(exception, time) {
650
+ const attributes = transformExceptionAttributes(exception);
651
+ this.addEvent("exception", attributes, time);
652
+ }
653
+ get duration() {
654
+ return this._duration;
655
+ }
656
+ get ended() {
657
+ return this._ended;
658
+ }
659
+ get droppedAttributesCount() {
660
+ return this._droppedAttributesCount;
661
+ }
662
+ get droppedEventsCount() {
663
+ return this._droppedEventsCount;
664
+ }
665
+ get droppedLinksCount() {
666
+ return this._droppedLinksCount;
667
+ }
668
+ };
669
+
670
+ // src/tracer.ts
671
+ var idGenerator = new RandomIdGenerator();
672
+ var withNextSpanAttributes;
673
+ function getFlagAt(flagSequence, position) {
674
+ return (flagSequence >> position - 1 & 1) * position;
675
+ }
676
+ var WorkerTracer = class {
677
+ spanProcessors;
678
+ resource;
679
+ constructor(spanProcessors, resource) {
680
+ this.spanProcessors = spanProcessors;
681
+ this.resource = resource;
682
+ }
683
+ async forceFlush(traceId) {
684
+ const promises = this.spanProcessors.map(async (spanProcessor) => {
685
+ await spanProcessor.forceFlush(traceId);
686
+ });
687
+ await Promise.allSettled(promises);
688
+ }
689
+ addToResource(extra) {
690
+ this.resource.merge(extra);
691
+ }
692
+ startSpan(name, options = {}, context3 = api_context.active()) {
693
+ if (options.root) {
694
+ context3 = trace.deleteSpan(context3);
695
+ }
696
+ const config = getActiveConfig();
697
+ if (!config) throw new Error("Config is undefined. This is a bug in the instrumentation logic");
698
+ const parentSpanContext = trace.getSpan(context3)?.spanContext();
699
+ const { traceId, randomTraceFlag } = getTraceInfo(parentSpanContext);
700
+ const spanKind = options.kind || SpanKind2.INTERNAL;
701
+ const sanitisedAttrs = sanitizeAttributes2(options.attributes);
702
+ const sampler = config.sampling.headSampler;
703
+ const samplingDecision = sampler.shouldSample(context3, traceId, name, spanKind, sanitisedAttrs, []);
704
+ const { decision, traceState, attributes: attrs } = samplingDecision;
705
+ const attributes = Object.assign({}, options.attributes, attrs, withNextSpanAttributes);
706
+ withNextSpanAttributes = {};
707
+ const spanId = idGenerator.generateSpanId();
708
+ const parentSpanId = parentSpanContext?.spanId;
709
+ const sampleFlag = decision === SamplingDecision.RECORD_AND_SAMPLED ? TraceFlags2.SAMPLED : TraceFlags2.NONE;
710
+ const traceFlags = sampleFlag + randomTraceFlag;
711
+ const spanContext = { traceId, spanId, traceFlags, traceState };
712
+ const span = new SpanImpl({
713
+ attributes: sanitizeAttributes2(attributes),
714
+ name,
715
+ onEnd: (span2) => {
716
+ this.spanProcessors.forEach((sp) => {
717
+ sp.onEnd(span2);
718
+ });
719
+ },
720
+ resource: this.resource,
721
+ spanContext,
722
+ parentSpanContext,
723
+ parentSpanId,
724
+ spanKind,
725
+ startTime: options.startTime
726
+ });
727
+ this.spanProcessors.forEach((sp) => {
728
+ sp.onStart(span, context3);
729
+ });
730
+ return span;
731
+ }
732
+ startActiveSpan(name, ...args) {
733
+ const options = args.length > 1 ? args[0] : void 0;
734
+ const parentContext = args.length > 2 ? args[1] : api_context.active();
735
+ const fn = args[args.length - 1];
736
+ const span = this.startSpan(name, options, parentContext);
737
+ const contextWithSpanSet = trace.setSpan(parentContext, span);
738
+ return api_context.with(contextWithSpanSet, fn, void 0, span);
739
+ }
740
+ };
741
+ function withNextSpan(attrs) {
742
+ withNextSpanAttributes = Object.assign({}, withNextSpanAttributes, attrs);
743
+ }
744
+ function getTraceInfo(parentSpanContext) {
745
+ if (parentSpanContext && trace.isSpanContextValid(parentSpanContext)) {
746
+ const { traceId, traceFlags } = parentSpanContext;
747
+ return { traceId, randomTraceFlag: getFlagAt(traceFlags, 2) };
748
+ } else {
749
+ return { traceId: idGenerator.generateTraceId(), randomTraceFlag: 2 /* RANDOM_TRACE_ID_SET */ };
750
+ }
751
+ }
752
+
753
+ // src/provider.ts
754
+ var WorkerTracerProvider = class {
755
+ spanProcessors;
756
+ resource;
757
+ tracers = {};
758
+ constructor(spanProcessors, resource) {
759
+ this.spanProcessors = spanProcessors;
760
+ this.resource = resource;
761
+ }
762
+ getTracer(name, version, options) {
763
+ const key = `${name}@${version || ""}:${options?.schemaUrl || ""}`;
764
+ if (!this.tracers[key]) {
765
+ this.tracers[key] = new WorkerTracer(this.spanProcessors, this.resource);
766
+ }
767
+ return this.tracers[key];
768
+ }
769
+ register() {
770
+ trace2.setGlobalTracerProvider(this);
771
+ context2.setGlobalContextManager(new AsyncLocalStorageContextManager());
772
+ }
773
+ };
774
+
775
+ // src/instrumentation/fetch.ts
776
+ import {
777
+ trace as trace3,
778
+ SpanKind as SpanKind3,
779
+ propagation,
780
+ context as api_context2,
781
+ SpanStatusCode as SpanStatusCode3
782
+ } from "@opentelemetry/api";
783
+ var netKeysFromCF = /* @__PURE__ */ new Set(["colo", "country", "request_priority", "tls_cipher", "tls_version", "asn", "tcp_rtt"]);
784
+ var camelToSnakeCase = (s) => {
785
+ return s.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
786
+ };
787
+ var gatherOutgoingCfAttributes = (cf) => {
788
+ const attrs = {};
789
+ Object.keys(cf).forEach((key) => {
790
+ const value = cf[key];
791
+ const destKey = camelToSnakeCase(key);
792
+ if (!netKeysFromCF.has(destKey)) {
793
+ if (typeof value === "string" || typeof value === "number") {
794
+ attrs[`cf.${destKey}`] = value;
795
+ } else {
796
+ attrs[`cf.${destKey}`] = JSON.stringify(value);
797
+ }
798
+ }
799
+ });
800
+ return attrs;
801
+ };
802
+ function gatherRequestAttributes(request) {
803
+ const attrs = {};
804
+ const headers = request.headers;
805
+ attrs["http.request.method"] = request.method.toUpperCase();
806
+ attrs["network.protocol.name"] = "http";
807
+ attrs["network.protocol.version"] = request.cf?.httpProtocol;
808
+ attrs["http.request.body.size"] = headers.get("content-length");
809
+ attrs["user_agent.original"] = headers.get("user-agent");
810
+ attrs["http.mime_type"] = headers.get("content-type");
811
+ attrs["http.accepts"] = request.cf?.clientAcceptEncoding;
812
+ const u = new URL(request.url);
813
+ attrs["url.full"] = `${u.protocol}//${u.host}${u.pathname}${u.search}`;
814
+ attrs["server.address"] = u.host;
815
+ attrs["url.scheme"] = u.protocol;
816
+ attrs["url.path"] = u.pathname;
817
+ attrs["url.query"] = u.search;
818
+ return attrs;
819
+ }
820
+ function gatherResponseAttributes(response) {
821
+ const attrs = {};
822
+ attrs["http.response.status_code"] = response.status;
823
+ if (response.headers.get("content-length") == null) {
824
+ attrs["http.response.body.size"] = response.headers.get("content-length");
825
+ }
826
+ attrs["http.mime_type"] = response.headers.get("content-type");
827
+ return attrs;
828
+ }
829
+ function gatherIncomingCfAttributes(request) {
830
+ const attrs = {};
831
+ attrs["net.colo"] = request.cf?.colo;
832
+ attrs["net.country"] = request.cf?.country;
833
+ attrs["net.request_priority"] = request.cf?.requestPriority;
834
+ attrs["net.tls_cipher"] = request.cf?.tlsCipher;
835
+ attrs["net.tls_version"] = request.cf?.tlsVersion;
836
+ attrs["net.asn"] = request.cf?.asn;
837
+ attrs["net.tcp_rtt"] = request.cf?.clientTcpRtt;
838
+ return attrs;
839
+ }
840
+ function getParentContextFromHeaders(headers) {
841
+ return propagation.extract(api_context2.active(), headers, {
842
+ get(headers2, key) {
843
+ return headers2.get(key) || void 0;
844
+ },
845
+ keys(headers2) {
846
+ return [...headers2.keys()];
847
+ }
848
+ });
849
+ }
850
+ function getParentContextFromRequest(request) {
851
+ const workerConfig = getActiveConfig();
852
+ if (workerConfig === void 0) {
853
+ return api_context2.active();
854
+ }
855
+ const acceptTraceContext = typeof workerConfig.handlers.fetch.acceptTraceContext === "function" ? workerConfig.handlers.fetch.acceptTraceContext(request) : workerConfig.handlers.fetch.acceptTraceContext ?? true;
856
+ return acceptTraceContext ? getParentContextFromHeaders(request.headers) : api_context2.active();
857
+ }
858
+ function updateSpanNameOnRoute(span, request) {
859
+ const readable = span;
860
+ if (readable.attributes["http.route"]) {
861
+ const method = request.method.toUpperCase();
862
+ span.updateName(`${method} ${readable.attributes["http.route"]}`);
863
+ }
864
+ }
865
+ var fetchInstrumentation = {
866
+ getInitialSpanInfo: (request) => {
867
+ const spanContext = getParentContextFromRequest(request);
868
+ const attributes = {
869
+ ["faas.trigger"]: "http",
870
+ ["faas.invocation_id"]: request.headers.get("cf-ray") ?? void 0
871
+ };
872
+ Object.assign(attributes, gatherRequestAttributes(request));
873
+ Object.assign(attributes, gatherIncomingCfAttributes(request));
874
+ const method = request.method.toUpperCase();
875
+ return {
876
+ name: `fetchHandler ${method}`,
877
+ options: {
878
+ attributes,
879
+ kind: SpanKind3.SERVER
880
+ },
881
+ context: spanContext
882
+ };
883
+ },
884
+ getAttributesFromResult: (response) => {
885
+ return gatherResponseAttributes(response);
886
+ },
887
+ executionSucces: updateSpanNameOnRoute,
888
+ executionFailed: updateSpanNameOnRoute
889
+ };
890
+ function instrumentClientFetch(fetchFn, configFn, attrs) {
891
+ const handler = {
892
+ apply: (target, thisArg, argArray) => {
893
+ const request = new Request(argArray[0], argArray[1]);
894
+ if (!request.url.startsWith("http")) {
895
+ return Reflect.apply(target, thisArg, argArray);
896
+ }
897
+ const workerConfig = getActiveConfig();
898
+ if (!workerConfig) {
899
+ return Reflect.apply(target, thisArg, [request]);
900
+ }
901
+ const config = configFn(workerConfig);
902
+ const tracer2 = trace3.getTracer("fetcher");
903
+ const options = { kind: SpanKind3.CLIENT, attributes: attrs };
904
+ const host = new URL(request.url).host;
905
+ const method = request.method.toUpperCase();
906
+ const spanName = typeof attrs?.["name"] === "string" ? attrs?.["name"] : `fetch ${method} ${host}`;
907
+ const promise = tracer2.startActiveSpan(spanName, options, async (span) => {
908
+ try {
909
+ const includeTraceContext = typeof config.includeTraceContext === "function" ? config.includeTraceContext(request) : config.includeTraceContext;
910
+ if (includeTraceContext ?? true) {
911
+ propagation.inject(api_context2.active(), request.headers, {
912
+ set: (h, k, v) => h.set(k, typeof v === "string" ? v : String(v))
913
+ });
914
+ }
915
+ span.setAttributes(gatherRequestAttributes(request));
916
+ if (request.cf) span.setAttributes(gatherOutgoingCfAttributes(request.cf));
917
+ const response = await Reflect.apply(target, thisArg, [request]);
918
+ span.setAttributes(gatherResponseAttributes(response));
919
+ return response;
920
+ } catch (error) {
921
+ span.recordException(error);
922
+ span.setStatus({ code: SpanStatusCode3.ERROR });
923
+ throw error;
924
+ } finally {
925
+ span.end();
926
+ }
927
+ });
928
+ return promise;
929
+ }
930
+ };
931
+ return wrap(fetchFn, handler, true);
932
+ }
933
+ function instrumentGlobalFetch() {
934
+ globalThis.fetch = instrumentClientFetch(globalThis.fetch, (config) => config.fetch);
935
+ }
936
+
937
+ // src/instrumentation/cache.ts
938
+ import { SpanKind as SpanKind4, trace as trace4 } from "@opentelemetry/api";
939
+ var tracer = trace4.getTracer("cache instrumentation");
940
+ function sanitiseURL(url) {
941
+ const u = new URL(url);
942
+ return `${u.protocol}//${u.host}${u.pathname}${u.search}`;
943
+ }
944
+ function instrumentFunction(fn, cacheName, op) {
945
+ const handler = {
946
+ async apply(target, thisArg, argArray) {
947
+ const attributes = {
948
+ "cache.name": cacheName,
949
+ "http.url": argArray[0].url ? sanitiseURL(argArray[0].url) : void 0,
950
+ "cache.operation": op
951
+ };
952
+ const options = { kind: SpanKind4.CLIENT, attributes };
953
+ return tracer.startActiveSpan(`Cache ${cacheName} ${op}`, options, async (span) => {
954
+ const result = await Reflect.apply(target, thisArg, argArray);
955
+ if (op === "match") {
956
+ span.setAttribute("cache.hit", !!result);
957
+ }
958
+ span.end();
959
+ return result;
960
+ });
961
+ }
962
+ };
963
+ return wrap(fn, handler);
964
+ }
965
+ function instrumentCache(cache, cacheName) {
966
+ const handler = {
967
+ get(target, prop) {
968
+ if (prop === "delete" || prop === "match" || prop === "put") {
969
+ const fn = Reflect.get(target, prop).bind(target);
970
+ return instrumentFunction(fn, cacheName, prop);
971
+ } else {
972
+ return Reflect.get(target, prop);
973
+ }
974
+ }
975
+ };
976
+ return wrap(cache, handler);
977
+ }
978
+ function instrumentOpen(openFn) {
979
+ const handler = {
980
+ async apply(target, thisArg, argArray) {
981
+ const cacheName = argArray[0];
982
+ const cache = await Reflect.apply(target, thisArg, argArray);
983
+ return instrumentCache(cache, cacheName);
984
+ }
985
+ };
986
+ return wrap(openFn, handler);
987
+ }
988
+ function _instrumentGlobalCache() {
989
+ const handler = {
990
+ get(target, prop) {
991
+ if (prop === "default") {
992
+ const cache = target.default;
993
+ return instrumentCache(cache, "default");
994
+ } else if (prop === "open") {
995
+ const openFn = Reflect.get(target, prop).bind(target);
996
+ return instrumentOpen(openFn);
997
+ } else {
998
+ return Reflect.get(target, prop);
999
+ }
1000
+ }
1001
+ };
1002
+ globalThis.caches = wrap(caches, handler);
1003
+ }
1004
+ function instrumentGlobalCache() {
1005
+ return _instrumentGlobalCache();
1006
+ }
1007
+
1008
+ // src/instrumentation/queue.ts
1009
+ import { trace as trace5, SpanKind as SpanKind5 } from "@opentelemetry/api";
1010
+ import { ATTR_FAAS_TRIGGER, FAAS_TRIGGER_VALUE_PUBSUB } from "@opentelemetry/semantic-conventions/incubating";
1011
+ var MessageStatusCount = class {
1012
+ succeeded = 0;
1013
+ failed = 0;
1014
+ implicitly_acked = 0;
1015
+ implicitly_retried = 0;
1016
+ total;
1017
+ constructor(total) {
1018
+ this.total = total;
1019
+ }
1020
+ ack() {
1021
+ this.succeeded = this.succeeded + 1;
1022
+ }
1023
+ ackRemaining() {
1024
+ this.implicitly_acked = this.total - this.succeeded - this.failed;
1025
+ this.succeeded = this.total - this.failed;
1026
+ }
1027
+ retry() {
1028
+ this.failed = this.failed + 1;
1029
+ }
1030
+ retryRemaining() {
1031
+ this.implicitly_retried = this.total - this.succeeded - this.failed;
1032
+ this.failed = this.total - this.succeeded;
1033
+ }
1034
+ toAttributes() {
1035
+ return {
1036
+ "queue.messages_count": this.total,
1037
+ "queue.messages_success": this.succeeded,
1038
+ "queue.messages_failed": this.failed,
1039
+ "queue.batch_success": this.succeeded === this.total,
1040
+ "queue.implicitly_acked": this.implicitly_acked,
1041
+ "queue.implicitly_retried": this.implicitly_retried
1042
+ };
1043
+ }
1044
+ };
1045
+ var addEvent = (name, msg) => {
1046
+ const attrs = {};
1047
+ if (msg) {
1048
+ attrs["queue.message_id"] = msg.id;
1049
+ attrs["queue.message_timestamp"] = msg.timestamp.toISOString();
1050
+ }
1051
+ trace5.getActiveSpan()?.addEvent(name, attrs);
1052
+ };
1053
+ var proxyQueueMessage = (msg, count) => {
1054
+ const msgHandler = {
1055
+ get: (target, prop) => {
1056
+ if (prop === "ack") {
1057
+ const ackFn = Reflect.get(target, prop);
1058
+ return new Proxy(ackFn, {
1059
+ apply: (fnTarget) => {
1060
+ addEvent("messageAck", msg);
1061
+ count.ack();
1062
+ Reflect.apply(fnTarget, msg, []);
1063
+ }
1064
+ });
1065
+ } else if (prop === "retry") {
1066
+ const retryFn = Reflect.get(target, prop);
1067
+ return new Proxy(retryFn, {
1068
+ apply: (fnTarget) => {
1069
+ addEvent("messageRetry", msg);
1070
+ count.retry();
1071
+ const result = Reflect.apply(fnTarget, msg, []);
1072
+ return result;
1073
+ }
1074
+ });
1075
+ } else {
1076
+ return Reflect.get(target, prop, msg);
1077
+ }
1078
+ }
1079
+ };
1080
+ return wrap(msg, msgHandler);
1081
+ };
1082
+ var proxyMessageBatch = (batch, count) => {
1083
+ const batchHandler = {
1084
+ get: (target, prop) => {
1085
+ if (prop === "messages") {
1086
+ const messages = Reflect.get(target, prop);
1087
+ const messagesHandler = {
1088
+ get: (target2, prop2) => {
1089
+ if (typeof prop2 === "string" && !isNaN(parseInt(prop2))) {
1090
+ const message = Reflect.get(target2, prop2);
1091
+ return proxyQueueMessage(message, count);
1092
+ } else {
1093
+ return Reflect.get(target2, prop2);
1094
+ }
1095
+ }
1096
+ };
1097
+ return wrap(messages, messagesHandler);
1098
+ } else if (prop === "ackAll") {
1099
+ const ackFn = Reflect.get(target, prop);
1100
+ return new Proxy(ackFn, {
1101
+ apply: (fnTarget) => {
1102
+ addEvent("ackAll");
1103
+ count.ackRemaining();
1104
+ Reflect.apply(fnTarget, batch, []);
1105
+ }
1106
+ });
1107
+ } else if (prop === "retryAll") {
1108
+ const retryFn = Reflect.get(target, prop);
1109
+ return new Proxy(retryFn, {
1110
+ apply: (fnTarget) => {
1111
+ addEvent("retryAll");
1112
+ count.retryRemaining();
1113
+ Reflect.apply(fnTarget, batch, []);
1114
+ }
1115
+ });
1116
+ }
1117
+ return Reflect.get(target, prop);
1118
+ }
1119
+ };
1120
+ return wrap(batch, batchHandler);
1121
+ };
1122
+ var QueueInstrumentation = class {
1123
+ count;
1124
+ getInitialSpanInfo(batch) {
1125
+ return {
1126
+ name: `queueHandler ${batch.queue}`,
1127
+ options: {
1128
+ attributes: {
1129
+ [ATTR_FAAS_TRIGGER]: FAAS_TRIGGER_VALUE_PUBSUB,
1130
+ "queue.name": batch.queue
1131
+ },
1132
+ kind: SpanKind5.CONSUMER
1133
+ }
1134
+ };
1135
+ }
1136
+ instrumentTrigger(batch) {
1137
+ this.count = new MessageStatusCount(batch.messages.length);
1138
+ return proxyMessageBatch(batch, this.count);
1139
+ }
1140
+ executionSucces(span) {
1141
+ if (this.count) {
1142
+ this.count.ackRemaining();
1143
+ span.setAttributes(this.count.toAttributes());
1144
+ }
1145
+ }
1146
+ executionFailed(span) {
1147
+ if (this.count) {
1148
+ this.count.retryRemaining();
1149
+ span.setAttributes(this.count.toAttributes());
1150
+ }
1151
+ }
1152
+ };
1153
+ function instrumentQueueSend(fn, name) {
1154
+ const tracer2 = trace5.getTracer("queueSender");
1155
+ const handler = {
1156
+ apply: (target, thisArg, argArray) => {
1157
+ return tracer2.startActiveSpan(`Queues ${name} send`, async (span) => {
1158
+ span.setAttribute("queue.operation", "send");
1159
+ await Reflect.apply(target, unwrap(thisArg), argArray);
1160
+ span.end();
1161
+ });
1162
+ }
1163
+ };
1164
+ return wrap(fn, handler);
1165
+ }
1166
+ function instrumentQueueSendBatch(fn, name) {
1167
+ const tracer2 = trace5.getTracer("queueSender");
1168
+ const handler = {
1169
+ apply: (target, thisArg, argArray) => {
1170
+ return tracer2.startActiveSpan(`Queues ${name} sendBatch`, async (span) => {
1171
+ span.setAttribute("queue.operation", "sendBatch");
1172
+ await Reflect.apply(target, unwrap(thisArg), argArray);
1173
+ span.end();
1174
+ });
1175
+ }
1176
+ };
1177
+ return wrap(fn, handler);
1178
+ }
1179
+ function instrumentQueueSender(queue, name) {
1180
+ const queueHandler = {
1181
+ get: (target, prop) => {
1182
+ if (prop === "send") {
1183
+ const sendFn = Reflect.get(target, prop);
1184
+ return instrumentQueueSend(sendFn, name);
1185
+ } else if (prop === "sendBatch") {
1186
+ const sendFn = Reflect.get(target, prop);
1187
+ return instrumentQueueSendBatch(sendFn, name);
1188
+ } else {
1189
+ return Reflect.get(target, prop);
1190
+ }
1191
+ }
1192
+ };
1193
+ return wrap(queue, queueHandler);
1194
+ }
1195
+
1196
+ // src/instrumentation/do.ts
1197
+ import { context as api_context3, trace as trace10, SpanKind as SpanKind10, SpanStatusCode as SpanStatusCode5 } from "@opentelemetry/api";
1198
+ import { SemanticAttributes as SemanticAttributes6 } from "@opentelemetry/semantic-conventions";
1199
+
1200
+ // src/instrumentation/kv.ts
1201
+ import { SpanKind as SpanKind6, trace as trace6 } from "@opentelemetry/api";
1202
+ import { SemanticAttributes as SemanticAttributes2 } from "@opentelemetry/semantic-conventions";
1203
+ var dbSystem = "Cloudflare KV";
1204
+ var KVAttributes = {
1205
+ delete(_argArray) {
1206
+ return {};
1207
+ },
1208
+ get(argArray) {
1209
+ const attrs = {};
1210
+ const opts = argArray[1];
1211
+ if (typeof opts === "string") {
1212
+ attrs["db.cf.kv.type"] = opts;
1213
+ } else if (typeof opts === "object") {
1214
+ attrs["db.cf.kv.type"] = opts.type;
1215
+ attrs["db.cf.kv.cache_ttl"] = opts.cacheTtl;
1216
+ }
1217
+ return attrs;
1218
+ },
1219
+ getWithMetadata(argArray, result) {
1220
+ const attrs = {};
1221
+ const opts = argArray[1];
1222
+ if (typeof opts === "string") {
1223
+ attrs["db.cf.kv.type"] = opts;
1224
+ } else if (typeof opts === "object") {
1225
+ attrs["db.cf.kv.type"] = opts.type;
1226
+ attrs["db.cf.kv.cache_ttl"] = opts.cacheTtl;
1227
+ }
1228
+ attrs["db.cf.kv.metadata"] = true;
1229
+ const { cacheStatus } = result;
1230
+ if (typeof cacheStatus === "string") {
1231
+ attrs["db.cf.kv.cache_status"] = cacheStatus;
1232
+ }
1233
+ return attrs;
1234
+ },
1235
+ list(argArray, result) {
1236
+ const attrs = {};
1237
+ const opts = argArray[0] || {};
1238
+ const { cursor, limit } = opts;
1239
+ attrs["db.cf.kv.list_request_cursor"] = cursor || void 0;
1240
+ attrs["db.cf.kv.list_limit"] = limit || void 0;
1241
+ const { list_complete, cacheStatus } = result;
1242
+ attrs["db.cf.kv.list_complete"] = list_complete || void 0;
1243
+ if (!list_complete) {
1244
+ attrs["db.cf.kv.list_response_cursor"] = cursor || void 0;
1245
+ }
1246
+ if (typeof cacheStatus === "string") {
1247
+ attrs["db.cf.kv.cache_status"] = cacheStatus;
1248
+ }
1249
+ return attrs;
1250
+ },
1251
+ put(argArray) {
1252
+ const attrs = {};
1253
+ if (argArray.length > 2 && argArray[2]) {
1254
+ const { expiration, expirationTtl, metadata } = argArray[2];
1255
+ attrs["db.cf.kv.expiration"] = expiration;
1256
+ attrs["db.cf.kv.expiration_ttl"] = expirationTtl;
1257
+ attrs["db.cf.kv.metadata"] = !!metadata;
1258
+ }
1259
+ return attrs;
1260
+ }
1261
+ };
1262
+ function instrumentKVFn(fn, name, operation) {
1263
+ const tracer2 = trace6.getTracer("KV");
1264
+ const fnHandler = {
1265
+ apply: (target, thisArg, argArray) => {
1266
+ const attributes = {
1267
+ binding_type: "KV",
1268
+ [SemanticAttributes2.DB_NAME]: name,
1269
+ [SemanticAttributes2.DB_SYSTEM]: dbSystem,
1270
+ [SemanticAttributes2.DB_OPERATION]: operation
1271
+ };
1272
+ const options = {
1273
+ kind: SpanKind6.CLIENT,
1274
+ attributes
1275
+ };
1276
+ return tracer2.startActiveSpan(`KV ${name} ${operation}`, options, async (span) => {
1277
+ const result = await Reflect.apply(target, thisArg, argArray);
1278
+ const extraAttrsFn = KVAttributes[operation];
1279
+ const extraAttrs = extraAttrsFn ? extraAttrsFn(argArray, result) : {};
1280
+ span.setAttributes(extraAttrs);
1281
+ if (operation === "list") {
1282
+ const opts = argArray[0] || {};
1283
+ const { prefix } = opts;
1284
+ span.setAttribute(SemanticAttributes2.DB_STATEMENT, `${operation} ${prefix || void 0}`);
1285
+ } else {
1286
+ span.setAttribute(SemanticAttributes2.DB_STATEMENT, `${operation} ${argArray[0]}`);
1287
+ span.setAttribute("db.cf.kv.key", argArray[0]);
1288
+ }
1289
+ if (operation === "getWithMetadata") {
1290
+ const hasResults = !!result && !!result.value;
1291
+ span.setAttribute("db.cf.kv.has_result", hasResults);
1292
+ } else {
1293
+ span.setAttribute("db.cf.kv.has_result", !!result);
1294
+ }
1295
+ span.end();
1296
+ return result;
1297
+ });
1298
+ }
1299
+ };
1300
+ return wrap(fn, fnHandler);
1301
+ }
1302
+ function instrumentKV(kv, name) {
1303
+ const kvHandler = {
1304
+ get: (target, prop, receiver) => {
1305
+ const operation = String(prop);
1306
+ const fn = Reflect.get(target, prop, receiver);
1307
+ return instrumentKVFn(fn, name, operation);
1308
+ }
1309
+ };
1310
+ return wrap(kv, kvHandler);
1311
+ }
1312
+
1313
+ // src/instrumentation/service.ts
1314
+ function instrumentServiceBinding(fetcher, envName) {
1315
+ const fetcherHandler = {
1316
+ get(target, prop) {
1317
+ if (prop === "fetch") {
1318
+ const fetcher2 = Reflect.get(target, prop);
1319
+ const attrs = {
1320
+ name: `Service Binding ${envName}`
1321
+ };
1322
+ return instrumentClientFetch(fetcher2, () => ({ includeTraceContext: true }), attrs);
1323
+ } else {
1324
+ return passthroughGet(target, prop);
1325
+ }
1326
+ }
1327
+ };
1328
+ return wrap(fetcher, fetcherHandler);
1329
+ }
1330
+
1331
+ // src/instrumentation/d1.ts
1332
+ import { SpanKind as SpanKind7, SpanStatusCode as SpanStatusCode4, trace as trace7 } from "@opentelemetry/api";
1333
+ import { SemanticAttributes as SemanticAttributes3 } from "@opentelemetry/semantic-conventions";
1334
+ var dbSystem2 = "Cloudflare D1";
1335
+ function metaAttributes(meta) {
1336
+ return {
1337
+ "db.cf.d1.rows_read": meta.rows_read,
1338
+ "db.cf.d1.rows_written": meta.rows_written,
1339
+ "db.cf.d1.duration": meta.duration,
1340
+ "db.cf.d1.size_after": meta.size_after,
1341
+ "db.cf.d1.last_row_id": meta.last_row_id,
1342
+ "db.cf.d1.changed_db": meta.changed_db,
1343
+ "db.cf.d1.changes": meta.changes
1344
+ };
1345
+ }
1346
+ function spanOptions(dbName, operation, sql) {
1347
+ const attributes = {
1348
+ binding_type: "D1",
1349
+ [SemanticAttributes3.DB_NAME]: dbName,
1350
+ [SemanticAttributes3.DB_SYSTEM]: dbSystem2,
1351
+ [SemanticAttributes3.DB_OPERATION]: operation
1352
+ };
1353
+ if (sql) {
1354
+ attributes[SemanticAttributes3.DB_STATEMENT] = sql;
1355
+ }
1356
+ return {
1357
+ kind: SpanKind7.CLIENT,
1358
+ attributes
1359
+ };
1360
+ }
1361
+ function instrumentD1StatementFn(fn, dbName, operation, sql) {
1362
+ const tracer2 = trace7.getTracer("D1");
1363
+ const fnHandler = {
1364
+ apply: (target, thisArg, argArray) => {
1365
+ if (operation === "bind") {
1366
+ const newStmt = Reflect.apply(target, thisArg, argArray);
1367
+ return instrumentD1PreparedStatement(newStmt, dbName, sql);
1368
+ }
1369
+ const options = spanOptions(dbName, operation, sql);
1370
+ return tracer2.startActiveSpan(`${dbName} ${operation}`, options, async (span) => {
1371
+ try {
1372
+ const result = await Reflect.apply(target, thisArg, argArray);
1373
+ if (operation === "all" || operation === "run") {
1374
+ span.setAttributes(metaAttributes(result.meta));
1375
+ }
1376
+ span.setStatus({ code: SpanStatusCode4.OK });
1377
+ return result;
1378
+ } catch (error) {
1379
+ span.recordException(error);
1380
+ span.setStatus({ code: SpanStatusCode4.ERROR });
1381
+ throw error;
1382
+ } finally {
1383
+ span.end();
1384
+ }
1385
+ });
1386
+ }
1387
+ };
1388
+ return wrap(fn, fnHandler);
1389
+ }
1390
+ function instrumentD1PreparedStatement(stmt, dbName, statement) {
1391
+ const statementHandler = {
1392
+ get: (target, prop, receiver) => {
1393
+ const operation = String(prop);
1394
+ const fn = Reflect.get(target, prop, receiver);
1395
+ if (typeof fn === "function") {
1396
+ return instrumentD1StatementFn(fn, dbName, operation, statement);
1397
+ }
1398
+ return fn;
1399
+ }
1400
+ };
1401
+ return wrap(stmt, statementHandler);
1402
+ }
1403
+ function instrumentD1Fn(fn, dbName, operation) {
1404
+ const tracer2 = trace7.getTracer("D1");
1405
+ const fnHandler = {
1406
+ apply: (target, thisArg, argArray) => {
1407
+ if (operation === "prepare") {
1408
+ const sql = argArray[0];
1409
+ const stmt = Reflect.apply(target, thisArg, argArray);
1410
+ return instrumentD1PreparedStatement(stmt, dbName, sql);
1411
+ } else if (operation === "exec") {
1412
+ const sql = argArray[0];
1413
+ const options = spanOptions(dbName, operation, sql);
1414
+ return tracer2.startActiveSpan(`${dbName} ${operation}`, options, async (span) => {
1415
+ try {
1416
+ const result = await Reflect.apply(target, thisArg, argArray);
1417
+ span.setStatus({ code: SpanStatusCode4.OK });
1418
+ return result;
1419
+ } catch (error) {
1420
+ span.recordException(error);
1421
+ span.setStatus({ code: SpanStatusCode4.ERROR });
1422
+ throw error;
1423
+ } finally {
1424
+ span.end();
1425
+ }
1426
+ });
1427
+ } else if (operation === "batch") {
1428
+ const statements = argArray[0];
1429
+ return tracer2.startActiveSpan(`${dbName} ${operation}`, async (span) => {
1430
+ const subSpans = statements.map(
1431
+ (s) => tracer2.startSpan(`${dbName} ${operation} > query`, spanOptions(dbName, operation, s.statement))
1432
+ );
1433
+ try {
1434
+ const result = await Reflect.apply(target, thisArg, argArray);
1435
+ result.forEach((r, i) => subSpans[i]?.setAttributes(metaAttributes(r.meta)));
1436
+ span.setStatus({ code: SpanStatusCode4.OK });
1437
+ return result;
1438
+ } catch (error) {
1439
+ span.recordException(error);
1440
+ span.setStatus({ code: SpanStatusCode4.ERROR });
1441
+ throw error;
1442
+ } finally {
1443
+ subSpans.forEach((s) => s.end());
1444
+ span.end();
1445
+ }
1446
+ });
1447
+ } else {
1448
+ return Reflect.apply(target, thisArg, argArray);
1449
+ }
1450
+ }
1451
+ };
1452
+ return wrap(fn, fnHandler);
1453
+ }
1454
+ function instrumentD1(database, dbName) {
1455
+ const dbHandler = {
1456
+ get: (target, prop, receiver) => {
1457
+ const operation = String(prop);
1458
+ const fn = Reflect.get(target, prop, receiver);
1459
+ if (typeof fn === "function") {
1460
+ return instrumentD1Fn(fn, dbName, operation);
1461
+ }
1462
+ return fn;
1463
+ }
1464
+ };
1465
+ return wrap(database, dbHandler);
1466
+ }
1467
+
1468
+ // src/instrumentation/analytics-engine.ts
1469
+ import { SpanKind as SpanKind8, trace as trace8 } from "@opentelemetry/api";
1470
+ import { SemanticAttributes as SemanticAttributes4 } from "@opentelemetry/semantic-conventions";
1471
+ var dbSystem3 = "Cloudflare Analytics Engine";
1472
+ var AEAttributes = {
1473
+ writeDataPoint(argArray) {
1474
+ const attrs = {};
1475
+ const opts = argArray[0];
1476
+ if (typeof opts === "object") {
1477
+ attrs["db.cf.ae.indexes"] = opts.indexes.length;
1478
+ attrs["db.cf.ae.index"] = opts.indexes[0].toString();
1479
+ attrs["db.cf.ae.doubles"] = opts.doubles.length;
1480
+ attrs["db.cf.ae.blobs"] = opts.blobs.length;
1481
+ }
1482
+ return attrs;
1483
+ }
1484
+ };
1485
+ function instrumentAEFn(fn, name, operation) {
1486
+ const tracer2 = trace8.getTracer("AnalyticsEngine");
1487
+ const fnHandler = {
1488
+ apply: (target, thisArg, argArray) => {
1489
+ const attributes = {
1490
+ binding_type: "AnalyticsEngine",
1491
+ [SemanticAttributes4.DB_NAME]: name,
1492
+ [SemanticAttributes4.DB_SYSTEM]: dbSystem3,
1493
+ [SemanticAttributes4.DB_OPERATION]: operation
1494
+ };
1495
+ const options = {
1496
+ kind: SpanKind8.CLIENT,
1497
+ attributes
1498
+ };
1499
+ return tracer2.startActiveSpan(`Analytics Engine ${name} ${operation}`, options, async (span) => {
1500
+ const result = await Reflect.apply(target, thisArg, argArray);
1501
+ const extraAttrsFn = AEAttributes[operation];
1502
+ const extraAttrs = extraAttrsFn ? extraAttrsFn(argArray, result) : {};
1503
+ span.setAttributes(extraAttrs);
1504
+ span.setAttribute(SemanticAttributes4.DB_STATEMENT, `${operation} ${argArray[0]}`);
1505
+ span.end();
1506
+ return result;
1507
+ });
1508
+ }
1509
+ };
1510
+ return wrap(fn, fnHandler);
1511
+ }
1512
+ function instrumentAnalyticsEngineDataset(dataset, name) {
1513
+ const datasetHandler = {
1514
+ get: (target, prop, receiver) => {
1515
+ const operation = String(prop);
1516
+ const fn = Reflect.get(target, prop, receiver);
1517
+ return instrumentAEFn(fn, name, operation);
1518
+ }
1519
+ };
1520
+ return wrap(dataset, datasetHandler);
1521
+ }
1522
+
1523
+ // src/instrumentation/env.ts
1524
+ var isJSRPC = (item) => {
1525
+ return !!item?.["__some_property_that_will_never_exist" + Math.random()];
1526
+ };
1527
+ var isKVNamespace = (item) => {
1528
+ return !isJSRPC(item) && !!item?.getWithMetadata;
1529
+ };
1530
+ var isQueue = (item) => {
1531
+ return !isJSRPC(item) && !!item?.sendBatch;
1532
+ };
1533
+ var isDurableObject = (item) => {
1534
+ return !isJSRPC(item) && !!item?.idFromName;
1535
+ };
1536
+ var isVersionMetadata = (item) => {
1537
+ return !isJSRPC(item) && typeof item?.id === "string" && typeof item?.tag === "string";
1538
+ };
1539
+ var isAnalyticsEngineDataset = (item) => {
1540
+ return !isJSRPC(item) && !!item?.writeDataPoint;
1541
+ };
1542
+ var isD1Database = (item) => {
1543
+ return !!item?.exec && !!item?.prepare;
1544
+ };
1545
+ var instrumentEnv = (env2) => {
1546
+ const envHandler = {
1547
+ get: (target, prop, receiver) => {
1548
+ const item = Reflect.get(target, prop, receiver);
1549
+ if (!isProxyable(item)) {
1550
+ return item;
1551
+ }
1552
+ if (isJSRPC(item)) {
1553
+ return instrumentServiceBinding(item, String(prop));
1554
+ } else if (isKVNamespace(item)) {
1555
+ return instrumentKV(item, String(prop));
1556
+ } else if (isQueue(item)) {
1557
+ return instrumentQueueSender(item, String(prop));
1558
+ } else if (isDurableObject(item)) {
1559
+ return instrumentDOBinding(item, String(prop));
1560
+ } else if (isVersionMetadata(item)) {
1561
+ return item;
1562
+ } else if (isAnalyticsEngineDataset(item)) {
1563
+ return instrumentAnalyticsEngineDataset(item, String(prop));
1564
+ } else if (isD1Database(item)) {
1565
+ return instrumentD1(item, String(prop));
1566
+ } else {
1567
+ return item;
1568
+ }
1569
+ }
1570
+ };
1571
+ return wrap(env2, envHandler);
1572
+ };
1573
+
1574
+ // src/instrumentation/do-storage.ts
1575
+ import { SpanKind as SpanKind9, trace as trace9 } from "@opentelemetry/api";
1576
+ import { SemanticAttributes as SemanticAttributes5 } from "@opentelemetry/semantic-conventions";
1577
+ var dbSystem4 = "Cloudflare DO";
1578
+ function isDurableObjectCommonOptions(options) {
1579
+ return typeof options === "object" && ("allowConcurrency" in options || "allowUnconfirmed" in options || "noCache" in options);
1580
+ }
1581
+ function applyOptionsAttributes(attrs, options) {
1582
+ if ("allowConcurrency" in options) {
1583
+ attrs["db.cf.do.allow_concurrency"] = options.allowConcurrency;
1584
+ }
1585
+ if ("allowUnconfirmed" in options) {
1586
+ attrs["db.cf.do.allow_unconfirmed"] = options.allowUnconfirmed;
1587
+ }
1588
+ if ("noCache" in options) {
1589
+ attrs["db.cf.do.no_cache"] = options.noCache;
1590
+ }
1591
+ }
1592
+ var StorageAttributes = {
1593
+ delete(argArray, result) {
1594
+ const args = argArray;
1595
+ let attrs = {};
1596
+ if (Array.isArray(args[0])) {
1597
+ const keys = args[0];
1598
+ attrs = {
1599
+ // todo: Maybe set db.cf.do.keys to the whole array here?
1600
+ "db.cf.do.key": keys[0],
1601
+ "db.cf.do.number_of_keys": keys.length,
1602
+ "db.cf.do.keys_deleted": result
1603
+ };
1604
+ } else {
1605
+ attrs = {
1606
+ "db.cf.do.key": args[0],
1607
+ "db.cf.do.success": result
1608
+ };
1609
+ }
1610
+ if (args[1]) {
1611
+ applyOptionsAttributes(attrs, args[1]);
1612
+ }
1613
+ return attrs;
1614
+ },
1615
+ deleteAll(argArray) {
1616
+ const args = argArray;
1617
+ let attrs = {};
1618
+ if (args[0]) {
1619
+ applyOptionsAttributes(attrs, args[0]);
1620
+ }
1621
+ return attrs;
1622
+ },
1623
+ get(argArray) {
1624
+ const args = argArray;
1625
+ let attrs = {};
1626
+ if (Array.isArray(args[0])) {
1627
+ const keys = args[0];
1628
+ attrs = {
1629
+ // todo: Maybe set db.cf.do.keys to the whole array here?
1630
+ "db.cf.do.key": keys[0],
1631
+ "db.cf.do.number_of_keys": keys.length
1632
+ };
1633
+ } else {
1634
+ attrs = {
1635
+ "db.cf.do.key": args[0]
1636
+ };
1637
+ }
1638
+ if (args[1]) {
1639
+ applyOptionsAttributes(attrs, args[1]);
1640
+ }
1641
+ return attrs;
1642
+ },
1643
+ list(argArray, result) {
1644
+ const args = argArray;
1645
+ const attrs = {
1646
+ "db.cf.do.number_of_results": result.size
1647
+ };
1648
+ if (args[0]) {
1649
+ const options = args[0];
1650
+ applyOptionsAttributes(attrs, options);
1651
+ if ("start" in options) {
1652
+ attrs["db.cf.do.start"] = options.start;
1653
+ }
1654
+ if ("startAfter" in options) {
1655
+ attrs["db.cf.do.start_after"] = options.startAfter;
1656
+ }
1657
+ if ("end" in options) {
1658
+ attrs["db.cf.do.end"] = options.end;
1659
+ }
1660
+ if ("prefix" in options) {
1661
+ attrs["db.cf.do.prefix"] = options.prefix;
1662
+ }
1663
+ if ("reverse" in options) {
1664
+ attrs["db.cf.do.reverse"] = options.reverse;
1665
+ }
1666
+ if ("limit" in options) {
1667
+ attrs["db.cf.do.limit"] = options.limit;
1668
+ }
1669
+ }
1670
+ return attrs;
1671
+ },
1672
+ put(argArray) {
1673
+ const args = argArray;
1674
+ const attrs = {};
1675
+ if (typeof args[0] === "string") {
1676
+ attrs["db.cf.do.key"] = args[0];
1677
+ if (args[2]) {
1678
+ applyOptionsAttributes(attrs, args[2]);
1679
+ }
1680
+ } else {
1681
+ const keys = Object.keys(args[0]);
1682
+ attrs["db.cf.do.key"] = keys[0];
1683
+ attrs["db.cf.do.number_of_keys"] = keys.length;
1684
+ if (isDurableObjectCommonOptions(args[1])) {
1685
+ applyOptionsAttributes(attrs, args[1]);
1686
+ }
1687
+ }
1688
+ return attrs;
1689
+ },
1690
+ getAlarm(argArray) {
1691
+ const args = argArray;
1692
+ const attrs = {};
1693
+ if (args[0]) {
1694
+ applyOptionsAttributes(attrs, args[0]);
1695
+ }
1696
+ return attrs;
1697
+ },
1698
+ setAlarm(argArray) {
1699
+ const args = argArray;
1700
+ const attrs = {};
1701
+ if (args[0] instanceof Date) {
1702
+ attrs["db.cf.do.alarm_time"] = args[0].getTime();
1703
+ } else {
1704
+ attrs["db.cf.do.alarm_time"] = args[0];
1705
+ }
1706
+ if (args[1]) {
1707
+ applyOptionsAttributes(attrs, args[1]);
1708
+ }
1709
+ return attrs;
1710
+ },
1711
+ deleteAlarm(argArray) {
1712
+ const args = argArray;
1713
+ const attrs = {};
1714
+ if (args[0]) {
1715
+ applyOptionsAttributes(attrs, args[0]);
1716
+ }
1717
+ return attrs;
1718
+ }
1719
+ };
1720
+ function instrumentStorageFn(fn, operation) {
1721
+ const tracer2 = trace9.getTracer("do_storage");
1722
+ const fnHandler = {
1723
+ apply: (target, thisArg, argArray) => {
1724
+ const attributes = {
1725
+ [SemanticAttributes5.DB_SYSTEM]: dbSystem4,
1726
+ [SemanticAttributes5.DB_OPERATION]: operation,
1727
+ [SemanticAttributes5.DB_STATEMENT]: `${operation} ${argArray[0]}`
1728
+ };
1729
+ const options = {
1730
+ kind: SpanKind9.CLIENT,
1731
+ attributes: {
1732
+ ...attributes,
1733
+ operation
1734
+ }
1735
+ };
1736
+ return tracer2.startActiveSpan(`Durable Object Storage ${operation}`, options, async (span) => {
1737
+ const result = await Reflect.apply(target, thisArg, argArray);
1738
+ const extraAttrsFn = StorageAttributes[operation];
1739
+ const extraAttrs = extraAttrsFn ? extraAttrsFn(argArray, result) : {};
1740
+ span.setAttributes(extraAttrs);
1741
+ span.setAttribute("db.cf.do.has_result", !!result);
1742
+ span.end();
1743
+ return result;
1744
+ });
1745
+ }
1746
+ };
1747
+ return wrap(fn, fnHandler);
1748
+ }
1749
+ function instrumentStorage(storage) {
1750
+ const storageHandler = {
1751
+ get: (target, prop, receiver) => {
1752
+ const operation = String(prop);
1753
+ const fn = Reflect.get(target, prop, receiver);
1754
+ return instrumentStorageFn(fn, operation);
1755
+ }
1756
+ };
1757
+ return wrap(storage, storageHandler);
1758
+ }
1759
+
1760
+ // src/instrumentation/do.ts
1761
+ import { DurableObject as DurableObjectClass } from "cloudflare:workers";
1762
+ function instrumentBindingStub(stub, nsName) {
1763
+ const stubHandler = {
1764
+ get(target, prop, receiver) {
1765
+ if (prop === "fetch") {
1766
+ const fetcher = Reflect.get(target, prop);
1767
+ const attrs = {
1768
+ name: `Durable Object ${nsName}`,
1769
+ "do.namespace": nsName,
1770
+ "do.id": target.id.toString(),
1771
+ "do.id.name": target.id.name
1772
+ };
1773
+ return instrumentClientFetch(fetcher, () => ({ includeTraceContext: true }), attrs);
1774
+ } else {
1775
+ return passthroughGet(target, prop, receiver);
1776
+ }
1777
+ }
1778
+ };
1779
+ return wrap(stub, stubHandler);
1780
+ }
1781
+ function instrumentBindingGet(getFn, nsName) {
1782
+ const getHandler = {
1783
+ apply(target, thisArg, argArray) {
1784
+ const stub = Reflect.apply(target, thisArg, argArray);
1785
+ return instrumentBindingStub(stub, nsName);
1786
+ }
1787
+ };
1788
+ return wrap(getFn, getHandler);
1789
+ }
1790
+ function instrumentDOBinding(ns, nsName) {
1791
+ const nsHandler = {
1792
+ get(target, prop, receiver) {
1793
+ if (prop === "get") {
1794
+ const fn = Reflect.get(ns, prop, receiver);
1795
+ return instrumentBindingGet(fn, nsName);
1796
+ } else {
1797
+ return passthroughGet(target, prop, receiver);
1798
+ }
1799
+ }
1800
+ };
1801
+ return wrap(ns, nsHandler);
1802
+ }
1803
+ function instrumentState(state) {
1804
+ const stateHandler = {
1805
+ get(target, prop, receiver) {
1806
+ const result = Reflect.get(target, prop, unwrap(receiver));
1807
+ if (prop === "storage") {
1808
+ return instrumentStorage(result);
1809
+ } else if (typeof result === "function") {
1810
+ return result.bind(target);
1811
+ } else {
1812
+ return result;
1813
+ }
1814
+ }
1815
+ };
1816
+ return wrap(state, stateHandler);
1817
+ }
1818
+ var cold_start = true;
1819
+ function executeDOFetch(fetchFn, request, id) {
1820
+ const spanContext = getParentContextFromHeaders(request.headers);
1821
+ const tracer2 = trace10.getTracer("DO fetchHandler");
1822
+ const attributes = {
1823
+ [SemanticAttributes6.FAAS_TRIGGER]: "http",
1824
+ [SemanticAttributes6.FAAS_COLDSTART]: cold_start
1825
+ };
1826
+ cold_start = false;
1827
+ Object.assign(attributes, gatherRequestAttributes(request));
1828
+ Object.assign(attributes, gatherIncomingCfAttributes(request));
1829
+ const options = {
1830
+ attributes,
1831
+ kind: SpanKind10.SERVER
1832
+ };
1833
+ const name = id.name || "";
1834
+ const promise = tracer2.startActiveSpan(`Durable Object Fetch ${name}`, options, spanContext, async (span) => {
1835
+ try {
1836
+ const response = await fetchFn(request);
1837
+ if (response.ok) {
1838
+ span.setStatus({ code: SpanStatusCode5.OK });
1839
+ }
1840
+ span.setAttributes(gatherResponseAttributes(response));
1841
+ span.end();
1842
+ return response;
1843
+ } catch (error) {
1844
+ span.recordException(error);
1845
+ span.setStatus({ code: SpanStatusCode5.ERROR });
1846
+ span.end();
1847
+ throw error;
1848
+ }
1849
+ });
1850
+ return promise;
1851
+ }
1852
+ function executeDOAlarm(alarmFn, id) {
1853
+ const tracer2 = trace10.getTracer("DO alarmHandler");
1854
+ const name = id.name || "";
1855
+ const promise = tracer2.startActiveSpan(`Durable Object Alarm ${name}`, async (span) => {
1856
+ span.setAttribute(SemanticAttributes6.FAAS_COLDSTART, cold_start);
1857
+ cold_start = false;
1858
+ span.setAttribute("do.id", id.toString());
1859
+ if (id.name) span.setAttribute("do.name", id.name);
1860
+ try {
1861
+ await alarmFn();
1862
+ span.end();
1863
+ } catch (error) {
1864
+ span.recordException(error);
1865
+ span.setStatus({ code: SpanStatusCode5.ERROR });
1866
+ span.end();
1867
+ throw error;
1868
+ }
1869
+ });
1870
+ return promise;
1871
+ }
1872
+ function instrumentFetchFn(fetchFn, initialiser, env2, id) {
1873
+ const fetchHandler = {
1874
+ async apply(target, thisArg, argArray) {
1875
+ const request = argArray[0];
1876
+ const config = initialiser(env2, request);
1877
+ const context3 = setConfig(config);
1878
+ try {
1879
+ const bound = target.bind(unwrap(thisArg));
1880
+ return await api_context3.with(context3, executeDOFetch, void 0, bound, request, id);
1881
+ } catch (error) {
1882
+ throw error;
1883
+ }
1884
+ }
1885
+ };
1886
+ return wrap(fetchFn, fetchHandler);
1887
+ }
1888
+ function instrumentAlarmFn(alarmFn, initialiser, env2, id) {
1889
+ if (!alarmFn) return void 0;
1890
+ const alarmHandler = {
1891
+ async apply(target, thisArg) {
1892
+ const config = initialiser(env2, "do-alarm");
1893
+ const context3 = setConfig(config);
1894
+ try {
1895
+ const bound = target.bind(unwrap(thisArg));
1896
+ return await api_context3.with(context3, executeDOAlarm, void 0, bound, id);
1897
+ } catch (error) {
1898
+ throw error;
1899
+ }
1900
+ }
1901
+ };
1902
+ return wrap(alarmFn, alarmHandler);
1903
+ }
1904
+ function instrumentAnyFn(fn, initialiser, env2, _id) {
1905
+ if (!fn) return void 0;
1906
+ const fnHandler = {
1907
+ async apply(target, thisArg, argArray) {
1908
+ thisArg = unwrap(thisArg);
1909
+ const config = initialiser(env2, "do-alarm");
1910
+ const context3 = setConfig(config);
1911
+ try {
1912
+ const bound = target.bind(unwrap(thisArg));
1913
+ return await api_context3.with(context3, () => bound.apply(thisArg, argArray), void 0);
1914
+ } catch (error) {
1915
+ throw error;
1916
+ }
1917
+ }
1918
+ };
1919
+ return wrap(fn, fnHandler);
1920
+ }
1921
+ function instrumentDurableObject(doObj, initialiser, env2, state, classStyle) {
1922
+ const objHandler = {
1923
+ get(target, prop) {
1924
+ if (classStyle && prop === "ctx") {
1925
+ return state;
1926
+ } else if (classStyle && prop === "env") {
1927
+ return env2;
1928
+ } else if (prop === "fetch") {
1929
+ const fetchFn = Reflect.get(target, prop);
1930
+ return instrumentFetchFn(fetchFn, initialiser, env2, state.id);
1931
+ } else if (prop === "alarm") {
1932
+ const alarmFn = Reflect.get(target, prop);
1933
+ return instrumentAlarmFn(alarmFn, initialiser, env2, state.id);
1934
+ } else {
1935
+ const result = Reflect.get(target, prop);
1936
+ if (typeof result === "function") {
1937
+ result.bind(doObj);
1938
+ return instrumentAnyFn(result, initialiser, env2, state.id);
1939
+ }
1940
+ return result;
1941
+ }
1942
+ }
1943
+ };
1944
+ return wrap(doObj, objHandler);
1945
+ }
1946
+ function instrumentDOClass(doClass, initialiser) {
1947
+ const classHandler = {
1948
+ construct(target, [orig_state, orig_env]) {
1949
+ const trigger = {
1950
+ id: orig_state.id.toString(),
1951
+ name: orig_state.id.name
1952
+ };
1953
+ const constructorConfig = initialiser(orig_env, trigger);
1954
+ const context3 = setConfig(constructorConfig);
1955
+ const state = instrumentState(orig_state);
1956
+ const env2 = instrumentEnv(orig_env);
1957
+ const classStyle = doClass.prototype instanceof DurableObjectClass;
1958
+ const createDO = () => {
1959
+ if (classStyle) {
1960
+ return new target(orig_state, orig_env);
1961
+ } else {
1962
+ return new target(state, env2);
1963
+ }
1964
+ };
1965
+ const doObj = api_context3.with(context3, createDO);
1966
+ return instrumentDurableObject(doObj, initialiser, env2, state, classStyle);
1967
+ }
1968
+ };
1969
+ return wrap(doClass, classHandler);
1970
+ }
1971
+
1972
+ // src/instrumentation/scheduled.ts
1973
+ import { SpanKind as SpanKind11 } from "@opentelemetry/api";
1974
+ import {
1975
+ ATTR_FAAS_CRON,
1976
+ ATTR_FAAS_TIME,
1977
+ ATTR_FAAS_TRIGGER as ATTR_FAAS_TRIGGER2,
1978
+ FAAS_TRIGGER_VALUE_TIMER
1979
+ } from "@opentelemetry/semantic-conventions/incubating";
1980
+ var scheduledInstrumentation = {
1981
+ getInitialSpanInfo: function(controller) {
1982
+ return {
1983
+ name: `scheduledHandler ${controller.cron}`,
1984
+ options: {
1985
+ attributes: {
1986
+ [ATTR_FAAS_TRIGGER2]: FAAS_TRIGGER_VALUE_TIMER,
1987
+ [ATTR_FAAS_CRON]: controller.cron,
1988
+ [ATTR_FAAS_TIME]: new Date(controller.scheduledTime).toISOString()
1989
+ },
1990
+ kind: SpanKind11.INTERNAL
1991
+ }
1992
+ };
1993
+ }
1994
+ };
1995
+
1996
+ // src/instrumentation/version.ts
1997
+ function versionAttributes(env2) {
1998
+ const attributes = {};
1999
+ if (typeof env2 === "object" && env2 !== null) {
2000
+ for (const [binding, data] of Object.entries(env2)) {
2001
+ if (isVersionMetadata(data)) {
2002
+ attributes["cf.workers_version_metadata.binding"] = binding;
2003
+ attributes["cf.workers_version_metadata.id"] = data.id;
2004
+ attributes["cf.workers_version_metadata.tag"] = data.tag;
2005
+ break;
2006
+ }
2007
+ }
2008
+ }
2009
+ return attributes;
2010
+ }
2011
+
2012
+ // src/instrumentation/common.ts
2013
+ import { trace as trace11 } from "@opentelemetry/api";
2014
+ var PromiseTracker = class {
2015
+ _outstandingPromises = [];
2016
+ get outstandingPromiseCount() {
2017
+ return this._outstandingPromises.length;
2018
+ }
2019
+ track(promise) {
2020
+ this._outstandingPromises.push(promise);
2021
+ }
2022
+ async wait() {
2023
+ await allSettledMutable(this._outstandingPromises);
2024
+ }
2025
+ };
2026
+ function createWaitUntil(fn, context3, tracker) {
2027
+ const handler = {
2028
+ apply(target, _thisArg, argArray) {
2029
+ tracker.track(argArray[0]);
2030
+ return Reflect.apply(target, context3, argArray);
2031
+ }
2032
+ };
2033
+ return wrap(fn, handler);
2034
+ }
2035
+ function proxyExecutionContext(context3) {
2036
+ const tracker = new PromiseTracker();
2037
+ const ctx = new Proxy(context3, {
2038
+ get(target, prop) {
2039
+ if (prop === "waitUntil") {
2040
+ const fn = Reflect.get(target, prop);
2041
+ return createWaitUntil(fn, context3, tracker);
2042
+ } else {
2043
+ return passthroughGet(target, prop);
2044
+ }
2045
+ }
2046
+ });
2047
+ return { ctx, tracker };
2048
+ }
2049
+ async function allSettledMutable(promises) {
2050
+ let values;
2051
+ do {
2052
+ values = await Promise.allSettled(promises);
2053
+ } while (values.length !== promises.length);
2054
+ return values;
2055
+ }
2056
+
2057
+ // src/instrumentation/email.ts
2058
+ import { SpanKind as SpanKind12 } from "@opentelemetry/api";
2059
+ import {
2060
+ ATTR_FAAS_TRIGGER as ATTR_FAAS_TRIGGER3,
2061
+ ATTR_MESSAGING_DESTINATION_NAME,
2062
+ ATTR_RPC_MESSAGE_ID
2063
+ } from "@opentelemetry/semantic-conventions/incubating";
2064
+ function headerAttributes(message) {
2065
+ return Object.fromEntries([...message.headers].map(([key, value]) => [`email.header.${key}`, value]));
2066
+ }
2067
+ var emailInstrumentation = {
2068
+ getInitialSpanInfo: (message) => {
2069
+ const attributes = {
2070
+ [ATTR_FAAS_TRIGGER3]: "other",
2071
+ [ATTR_RPC_MESSAGE_ID]: message.headers.get("Message-Id") ?? void 0,
2072
+ [ATTR_MESSAGING_DESTINATION_NAME]: message.to
2073
+ };
2074
+ Object.assign(attributes, headerAttributes(message));
2075
+ const options = {
2076
+ attributes,
2077
+ kind: SpanKind12.CONSUMER
2078
+ };
2079
+ return {
2080
+ name: `emailHandler ${message.to}`,
2081
+ options
2082
+ };
2083
+ }
2084
+ };
2085
+
2086
+ // src/sdk.ts
2087
+ import { env } from "cloudflare:workers";
2088
+ function isRequest(trigger) {
2089
+ return trigger instanceof Request;
2090
+ }
2091
+ function isMessageBatch(trigger) {
2092
+ return !!trigger.ackAll;
2093
+ }
2094
+ function isAlarm(trigger) {
2095
+ return trigger === "do-alarm";
2096
+ }
2097
+ function findVersionMeta() {
2098
+ return Object.values(env).find((binding) => {
2099
+ return Object.getPrototypeOf(binding).constructor.name === "Object" && binding.id !== void 0 && binding.tag !== void 0;
2100
+ });
2101
+ }
2102
+ var createResource = (config, versionMeta) => {
2103
+ console.log({ versionMeta });
2104
+ const workerResourceAttrs = {
2105
+ "cloud.provider": "cloudflare",
2106
+ "cloud.platform": "cloudflare.workers",
2107
+ "cloud.region": "earth",
2108
+ "faas.max_memory": 134217728,
2109
+ "telemetry.sdk.language": "js",
2110
+ "telemetry.sdk.name": "@mertdogar/otel-cf-workers",
2111
+ "telemetry.sdk.version": _mertdogar_otel_cf_workers,
2112
+ "telemetry.sdk.build.node_version": node,
2113
+ "cf.worker.version.id": versionMeta?.id,
2114
+ "cf.worker.version.tag": versionMeta?.tag,
2115
+ "cf.worker.version.timestamp": versionMeta?.timestamp
2116
+ };
2117
+ const serviceResource = resourceFromAttributes({
2118
+ "service.name": config.service.name,
2119
+ "service.namespace": config.service.namespace,
2120
+ "service.version": config.service.version
2121
+ });
2122
+ const resource = resourceFromAttributes(workerResourceAttrs);
2123
+ return resource.merge(serviceResource);
2124
+ };
2125
+ var initialised = false;
2126
+ function init(config) {
2127
+ if (!initialised) {
2128
+ if (config.instrumentation.instrumentGlobalCache) {
2129
+ instrumentGlobalCache();
2130
+ }
2131
+ if (config.instrumentation.instrumentGlobalFetch) {
2132
+ instrumentGlobalFetch();
2133
+ }
2134
+ propagation2.setGlobalPropagator(config.propagator);
2135
+ const resource = createResource(config, findVersionMeta());
2136
+ const provider = new WorkerTracerProvider(config.spanProcessors, resource);
2137
+ provider.register();
2138
+ initialised = true;
2139
+ }
2140
+ }
2141
+ function createInitialiser(config) {
2142
+ if (typeof config === "function") {
2143
+ return (env2, trigger) => {
2144
+ const conf = parseConfig(config(env2, trigger));
2145
+ init(conf);
2146
+ return conf;
2147
+ };
2148
+ } else {
2149
+ return () => {
2150
+ const conf = parseConfig(config);
2151
+ init(conf);
2152
+ return conf;
2153
+ };
2154
+ }
2155
+ }
2156
+ async function exportSpans(traceId, tracker) {
2157
+ const tracer2 = trace12.getTracer("export");
2158
+ if (tracer2 instanceof WorkerTracer) {
2159
+ await scheduler.wait(1);
2160
+ await tracker?.wait();
2161
+ await tracer2.forceFlush(traceId);
2162
+ } else {
2163
+ console.error("The global tracer is not of type WorkerTracer and can not export spans");
2164
+ }
2165
+ }
2166
+ var cold_start2 = true;
2167
+ function createHandlerFlowFn(instrumentation) {
2168
+ return (handlerFn, args) => {
2169
+ const [trigger, env2, context3] = args;
2170
+ const proxiedEnv = instrumentEnv(env2);
2171
+ const { ctx: proxiedCtx, tracker } = proxyExecutionContext(context3);
2172
+ const instrumentedTrigger = instrumentation.instrumentTrigger ? instrumentation.instrumentTrigger(trigger) : trigger;
2173
+ const tracer2 = trace12.getTracer("handler");
2174
+ const { name, options, context: spanContext } = instrumentation.getInitialSpanInfo(trigger);
2175
+ const attrs = options.attributes || {};
2176
+ attrs["faas.coldstart"] = cold_start2;
2177
+ options.attributes = attrs;
2178
+ Object.assign(attrs, versionAttributes(env2));
2179
+ cold_start2 = false;
2180
+ const parentContext = spanContext || api_context4.active();
2181
+ const result = tracer2.startActiveSpan(name, options, parentContext, async (span) => {
2182
+ try {
2183
+ const result2 = await handlerFn(instrumentedTrigger, proxiedEnv, proxiedCtx);
2184
+ if (instrumentation.getAttributesFromResult) {
2185
+ const attributes = instrumentation.getAttributesFromResult(result2);
2186
+ span.setAttributes(attributes);
2187
+ }
2188
+ if (instrumentation.executionSucces) {
2189
+ instrumentation.executionSucces(span, trigger, result2);
2190
+ }
2191
+ return result2;
2192
+ } catch (error) {
2193
+ span.recordException(error);
2194
+ span.setStatus({ code: SpanStatusCode6.ERROR });
2195
+ if (instrumentation.executionFailed) {
2196
+ instrumentation.executionFailed(span, trigger, error);
2197
+ }
2198
+ throw error;
2199
+ } finally {
2200
+ span.end();
2201
+ context3.waitUntil(exportSpans(span.spanContext().traceId, tracker));
2202
+ }
2203
+ });
2204
+ return result;
2205
+ };
2206
+ }
2207
+ function createHandlerProxy(handler, handlerFn, initialiser, instrumentation) {
2208
+ return (trigger, env2, ctx) => {
2209
+ const config = initialiser(env2, trigger);
2210
+ const context3 = setConfig(config);
2211
+ const flowFn = createHandlerFlowFn(instrumentation);
2212
+ return api_context4.with(context3, flowFn, handler, handlerFn, [trigger, env2, ctx]);
2213
+ };
2214
+ }
2215
+ function instrument(handler, config) {
2216
+ const initialiser = createInitialiser(config);
2217
+ if (handler.fetch) {
2218
+ const fetcher = unwrap(handler.fetch);
2219
+ handler.fetch = createHandlerProxy(handler, fetcher, initialiser, fetchInstrumentation);
2220
+ }
2221
+ if (handler.scheduled) {
2222
+ const scheduler2 = unwrap(handler.scheduled);
2223
+ handler.scheduled = createHandlerProxy(handler, scheduler2, initialiser, scheduledInstrumentation);
2224
+ }
2225
+ if (handler.queue) {
2226
+ const queuer = unwrap(handler.queue);
2227
+ handler.queue = createHandlerProxy(handler, queuer, initialiser, new QueueInstrumentation());
2228
+ }
2229
+ if (handler.email) {
2230
+ const emailer = unwrap(handler.email);
2231
+ handler.email = createHandlerProxy(handler, emailer, initialiser, emailInstrumentation);
2232
+ }
2233
+ return handler;
2234
+ }
2235
+ function instrumentDO(doClass, config) {
2236
+ const initialiser = createInitialiser(config);
2237
+ return instrumentDOClass(doClass, initialiser);
2238
+ }
2239
+ var __unwrappedFetch = unwrap(fetch);
2240
+
2241
+ // src/multiexporter.ts
2242
+ import { ExportResultCode as ExportResultCode3 } from "@opentelemetry/core";
2243
+ var MultiSpanExporter = class {
2244
+ exporters;
2245
+ constructor(exporters) {
2246
+ this.exporters = exporters;
2247
+ }
2248
+ export(items, resultCallback) {
2249
+ for (const exporter of this.exporters) {
2250
+ exporter.export(items, resultCallback);
2251
+ }
2252
+ }
2253
+ async shutdown() {
2254
+ for (const exporter of this.exporters) {
2255
+ await exporter.shutdown();
2256
+ }
2257
+ }
2258
+ };
2259
+ var MultiSpanExporterAsync = class {
2260
+ exporters;
2261
+ constructor(exporters) {
2262
+ this.exporters = exporters;
2263
+ }
2264
+ export(items, resultCallback) {
2265
+ const promises = this.exporters.map(
2266
+ (exporter) => new Promise((resolve) => {
2267
+ exporter.export(items, resolve);
2268
+ })
2269
+ );
2270
+ Promise.all(promises).then((results) => {
2271
+ const failed = results.filter((result) => result.code === ExportResultCode3.FAILED);
2272
+ if (failed.length > 0) {
2273
+ resultCallback({ code: ExportResultCode3.FAILED, error: failed[0].error });
2274
+ } else {
2275
+ resultCallback({ code: ExportResultCode3.SUCCESS });
2276
+ }
2277
+ });
2278
+ }
2279
+ async shutdown() {
2280
+ await Promise.all(this.exporters.map((exporter) => exporter.shutdown()));
2281
+ }
2282
+ };
2283
+ export {
2284
+ BatchTraceSpanProcessor,
2285
+ MultiSpanExporter,
2286
+ MultiSpanExporterAsync,
2287
+ OTLPExporter,
2288
+ SpanImpl,
2289
+ __unwrappedFetch,
2290
+ createSampler,
2291
+ exportSpans,
2292
+ instrument,
2293
+ instrumentDO,
2294
+ isAlarm,
2295
+ isHeadSampled,
2296
+ isMessageBatch,
2297
+ isRequest,
2298
+ isRootErrorSpan,
2299
+ multiTailSampler,
2300
+ withNextSpan
2301
+ };
2302
+ //# sourceMappingURL=index.js.map