@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/LICENSE +28 -0
- package/README.md +308 -0
- package/dist/index.d.ts +235 -0
- package/dist/index.js +2302 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
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
|