@elysia/opentelemetry 1.4.12 → 2.0.0-exp.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +98 -246
- package/dist/index.d.ts +72 -84
- package/dist/index.js +511 -0
- package/dist/index.mjs +489 -663
- package/package.json +8 -12
- package/bunfig.toml +0 -2
- package/dist/cjs/index.d.ts +0 -98
- package/dist/cjs/index.js +0 -701
package/dist/cjs/index.js
DELETED
|
@@ -1,701 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
contextKeySpan: () => contextKeySpan,
|
|
24
|
-
getCurrentSpan: () => getCurrentSpan,
|
|
25
|
-
getTracer: () => getTracer,
|
|
26
|
-
opentelemetry: () => opentelemetry,
|
|
27
|
-
record: () => record,
|
|
28
|
-
setAttributes: () => setAttributes,
|
|
29
|
-
shouldStartNodeSDK: () => shouldStartNodeSDK,
|
|
30
|
-
startActiveSpan: () => startActiveSpan,
|
|
31
|
-
startSpan: () => startSpan
|
|
32
|
-
});
|
|
33
|
-
module.exports = __toCommonJS(index_exports);
|
|
34
|
-
var import_elysia = require("elysia");
|
|
35
|
-
var import_api = require("@opentelemetry/api");
|
|
36
|
-
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
37
|
-
var headerHasToJSON = typeof new Headers().toJSON === "function";
|
|
38
|
-
var toHeaderNameSet = (names) => new Set((names ?? []).map((name) => name.toLowerCase()));
|
|
39
|
-
var SENSITIVE_QUERY_KEYS = /* @__PURE__ */ new Set([
|
|
40
|
-
"token",
|
|
41
|
-
"access_token",
|
|
42
|
-
"refresh_token",
|
|
43
|
-
"id_token",
|
|
44
|
-
"password",
|
|
45
|
-
"passwd",
|
|
46
|
-
"pwd",
|
|
47
|
-
"secret",
|
|
48
|
-
"client_secret",
|
|
49
|
-
"api_key",
|
|
50
|
-
"apikey",
|
|
51
|
-
"api-key",
|
|
52
|
-
"authorization",
|
|
53
|
-
"credential",
|
|
54
|
-
"credentials",
|
|
55
|
-
"code",
|
|
56
|
-
"nonce"
|
|
57
|
-
]);
|
|
58
|
-
var parseNumericString = (message) => {
|
|
59
|
-
if (message.length < 16) {
|
|
60
|
-
if (message.length === 0) return null;
|
|
61
|
-
const length = Number(message);
|
|
62
|
-
if (Number.isNaN(length)) return null;
|
|
63
|
-
return length;
|
|
64
|
-
}
|
|
65
|
-
if (message.length === 16) {
|
|
66
|
-
const number = Number(message);
|
|
67
|
-
if (number.toString() !== message || message.trim().length === 0 || Number.isNaN(number))
|
|
68
|
-
return null;
|
|
69
|
-
return number;
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
};
|
|
73
|
-
var createActiveSpanHandler = (fn) => function(span) {
|
|
74
|
-
try {
|
|
75
|
-
const result = fn(span);
|
|
76
|
-
if (result instanceof Promise || typeof result?.then === "function")
|
|
77
|
-
return Promise.resolve(result).then(
|
|
78
|
-
(value) => {
|
|
79
|
-
span.end();
|
|
80
|
-
return value;
|
|
81
|
-
},
|
|
82
|
-
(rejectResult) => {
|
|
83
|
-
span.setStatus({
|
|
84
|
-
code: import_api.SpanStatusCode.ERROR,
|
|
85
|
-
message: rejectResult instanceof Error ? rejectResult.message : JSON.stringify(
|
|
86
|
-
rejectResult ?? "Unknown error"
|
|
87
|
-
)
|
|
88
|
-
});
|
|
89
|
-
span.recordException(rejectResult);
|
|
90
|
-
span.end();
|
|
91
|
-
throw rejectResult;
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
span.end();
|
|
95
|
-
return result;
|
|
96
|
-
} catch (error) {
|
|
97
|
-
const err = error;
|
|
98
|
-
span.setStatus({
|
|
99
|
-
code: import_api.SpanStatusCode.ERROR,
|
|
100
|
-
message: err?.message
|
|
101
|
-
});
|
|
102
|
-
span.recordException(err);
|
|
103
|
-
span.end();
|
|
104
|
-
throw error;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
var createContext = (parent) => ({
|
|
108
|
-
getValue() {
|
|
109
|
-
return parent;
|
|
110
|
-
},
|
|
111
|
-
setValue() {
|
|
112
|
-
return import_api.context.active();
|
|
113
|
-
},
|
|
114
|
-
deleteValue() {
|
|
115
|
-
return import_api.context.active();
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
var serializeBody = (body) => {
|
|
119
|
-
if (body instanceof Uint8Array) return { text: "", size: body.length };
|
|
120
|
-
if (body instanceof ArrayBuffer) return { text: "", size: body.byteLength };
|
|
121
|
-
if (body instanceof Blob) return { text: "", size: body.size };
|
|
122
|
-
let text;
|
|
123
|
-
try {
|
|
124
|
-
text = typeof body === "object" ? JSON.stringify(body) : String(body);
|
|
125
|
-
} catch {
|
|
126
|
-
text = "[Unserializable]";
|
|
127
|
-
}
|
|
128
|
-
return { text, size: text.length };
|
|
129
|
-
};
|
|
130
|
-
var redactQueryString = (query, keys) => {
|
|
131
|
-
if (query === "" || keys.size === 0) return query;
|
|
132
|
-
let out = "";
|
|
133
|
-
let partStart = 0;
|
|
134
|
-
let keyEnd = -1;
|
|
135
|
-
for (let i = 0; i <= query.length; i++) {
|
|
136
|
-
const ch = i === query.length ? 38 : query.charCodeAt(i);
|
|
137
|
-
if (ch === 61 && keyEnd === -1) {
|
|
138
|
-
keyEnd = i;
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
if (ch !== 38) continue;
|
|
142
|
-
const partEnd = i;
|
|
143
|
-
const rawKeyEnd = keyEnd === -1 ? partEnd : keyEnd;
|
|
144
|
-
const rawKey = query.slice(partStart, rawKeyEnd);
|
|
145
|
-
if (out) out += "&";
|
|
146
|
-
out += keys.has(rawKey.toLowerCase()) ? rawKey + "=[REDACTED]" : query.slice(partStart, partEnd);
|
|
147
|
-
partStart = i + 1;
|
|
148
|
-
keyEnd = -1;
|
|
149
|
-
}
|
|
150
|
-
return out;
|
|
151
|
-
};
|
|
152
|
-
var shouldStartNodeSDK = (provider) => {
|
|
153
|
-
return provider instanceof import_api.ProxyTracerProvider && provider.getDelegateTracer("check") === void 0;
|
|
154
|
-
};
|
|
155
|
-
var contextKeySpan = Symbol.for("OpenTelemetry Context Key SPAN");
|
|
156
|
-
var getTracer = () => {
|
|
157
|
-
const tracer = import_api.trace.getTracer("Elysia");
|
|
158
|
-
return {
|
|
159
|
-
...tracer,
|
|
160
|
-
startSpan(name, options, context) {
|
|
161
|
-
return tracer.startSpan(name, options, context);
|
|
162
|
-
},
|
|
163
|
-
startActiveSpan(...args) {
|
|
164
|
-
switch (args.length) {
|
|
165
|
-
case 2:
|
|
166
|
-
return tracer.startActiveSpan(
|
|
167
|
-
args[0],
|
|
168
|
-
createActiveSpanHandler(args[1])
|
|
169
|
-
);
|
|
170
|
-
case 3:
|
|
171
|
-
return tracer.startActiveSpan(
|
|
172
|
-
args[0],
|
|
173
|
-
args[1],
|
|
174
|
-
createActiveSpanHandler(args[2])
|
|
175
|
-
);
|
|
176
|
-
case 4:
|
|
177
|
-
return tracer.startActiveSpan(
|
|
178
|
-
args[0],
|
|
179
|
-
args[1],
|
|
180
|
-
args[2],
|
|
181
|
-
createActiveSpanHandler(args[3])
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
};
|
|
187
|
-
var startSpan = (name, options, context) => {
|
|
188
|
-
const tracer = getTracer();
|
|
189
|
-
return tracer.startSpan(name, options, context);
|
|
190
|
-
};
|
|
191
|
-
var startActiveSpan = (...args) => {
|
|
192
|
-
const tracer = getTracer();
|
|
193
|
-
switch (args.length) {
|
|
194
|
-
case 2:
|
|
195
|
-
return tracer.startActiveSpan(
|
|
196
|
-
args[0],
|
|
197
|
-
createActiveSpanHandler(args[1])
|
|
198
|
-
);
|
|
199
|
-
case 3:
|
|
200
|
-
return tracer.startActiveSpan(
|
|
201
|
-
args[0],
|
|
202
|
-
args[1],
|
|
203
|
-
createActiveSpanHandler(args[2])
|
|
204
|
-
);
|
|
205
|
-
case 4:
|
|
206
|
-
return tracer.startActiveSpan(
|
|
207
|
-
args[0],
|
|
208
|
-
args[1],
|
|
209
|
-
args[2],
|
|
210
|
-
createActiveSpanHandler(args[3])
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
var record = startActiveSpan;
|
|
215
|
-
var getCurrentSpan = () => import_api.trace.getActiveSpan();
|
|
216
|
-
var setAttributes = (attributes) => !!getCurrentSpan()?.setAttributes(attributes);
|
|
217
|
-
var opentelemetry = ({
|
|
218
|
-
serviceName = "Elysia",
|
|
219
|
-
instrumentations,
|
|
220
|
-
contextManager,
|
|
221
|
-
checkIfShouldTrace,
|
|
222
|
-
spanUrlRedaction,
|
|
223
|
-
recordBody,
|
|
224
|
-
headersToSpanAttributes,
|
|
225
|
-
...options
|
|
226
|
-
} = {}) => {
|
|
227
|
-
const spanRequestHeaderSet = toHeaderNameSet(
|
|
228
|
-
headersToSpanAttributes?.request
|
|
229
|
-
);
|
|
230
|
-
const spanResponseHeaderSet = toHeaderNameSet(
|
|
231
|
-
headersToSpanAttributes?.response
|
|
232
|
-
);
|
|
233
|
-
const requestHeaderWildcard = spanRequestHeaderSet.has("*");
|
|
234
|
-
const responseHeaderWildcard = spanResponseHeaderSet.has("*");
|
|
235
|
-
const recordRequestBody = recordBody === true || recordBody && recordBody.request || false;
|
|
236
|
-
const recordResponseBody = recordBody === true || recordBody && recordBody.response || false;
|
|
237
|
-
const urlRedactOpts = spanUrlRedaction === false ? null : spanUrlRedaction ?? {};
|
|
238
|
-
const sensitiveKeys = urlRedactOpts ? /* @__PURE__ */ new Set([
|
|
239
|
-
...SENSITIVE_QUERY_KEYS,
|
|
240
|
-
...(urlRedactOpts.sensitiveQueryParams ?? []).map(
|
|
241
|
-
(k) => k.toLowerCase()
|
|
242
|
-
)
|
|
243
|
-
]) : void 0;
|
|
244
|
-
const stripCreds = urlRedactOpts?.stripCredentials !== false;
|
|
245
|
-
let tracer = import_api.trace.getTracer(serviceName);
|
|
246
|
-
if (shouldStartNodeSDK(import_api.trace.getTracerProvider())) {
|
|
247
|
-
const sdk = new import_sdk_node.NodeSDK({
|
|
248
|
-
...options,
|
|
249
|
-
serviceName,
|
|
250
|
-
instrumentations
|
|
251
|
-
});
|
|
252
|
-
sdk.start();
|
|
253
|
-
tracer = import_api.trace.getTracer(serviceName);
|
|
254
|
-
} else {
|
|
255
|
-
}
|
|
256
|
-
if (!import_api.context._getContextManager?.() && contextManager)
|
|
257
|
-
try {
|
|
258
|
-
contextManager.enable();
|
|
259
|
-
import_api.context.setGlobalContextManager(contextManager);
|
|
260
|
-
} catch {
|
|
261
|
-
}
|
|
262
|
-
const meter = import_api.metrics.getMeter(serviceName);
|
|
263
|
-
const httpServerDuration = meter.createHistogram(
|
|
264
|
-
"http.server.request.duration",
|
|
265
|
-
{
|
|
266
|
-
description: "Duration of HTTP server requests.",
|
|
267
|
-
unit: "s",
|
|
268
|
-
advice: {
|
|
269
|
-
explicitBucketBoundaries: [
|
|
270
|
-
5e-3,
|
|
271
|
-
0.01,
|
|
272
|
-
0.025,
|
|
273
|
-
0.05,
|
|
274
|
-
0.075,
|
|
275
|
-
0.1,
|
|
276
|
-
0.25,
|
|
277
|
-
0.5,
|
|
278
|
-
0.75,
|
|
279
|
-
1,
|
|
280
|
-
2.5,
|
|
281
|
-
5,
|
|
282
|
-
7.5,
|
|
283
|
-
10,
|
|
284
|
-
30,
|
|
285
|
-
60,
|
|
286
|
-
120,
|
|
287
|
-
300,
|
|
288
|
-
600,
|
|
289
|
-
900,
|
|
290
|
-
1800
|
|
291
|
-
]
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
);
|
|
295
|
-
return new import_elysia.Elysia({
|
|
296
|
-
name: "@elysia/opentelemetry"
|
|
297
|
-
}).wrap((fn, request) => {
|
|
298
|
-
const shouldTrace = checkIfShouldTrace ? checkIfShouldTrace(request) : true;
|
|
299
|
-
if (!shouldTrace) return fn;
|
|
300
|
-
const headers = headerHasToJSON ? (
|
|
301
|
-
// @ts-ignore bun only
|
|
302
|
-
request.headers.toJSON()
|
|
303
|
-
) : Object.fromEntries(request.headers.entries());
|
|
304
|
-
const ctx = import_api.propagation.extract(import_api.context.active(), headers);
|
|
305
|
-
return tracer.startActiveSpan(
|
|
306
|
-
"Root",
|
|
307
|
-
{ kind: import_api.SpanKind.SERVER },
|
|
308
|
-
ctx,
|
|
309
|
-
(rootSpan) => {
|
|
310
|
-
const spanContext = import_api.trace.setSpan(ctx, rootSpan);
|
|
311
|
-
return (...args) => {
|
|
312
|
-
return import_api.context.with(spanContext, () => fn(...args));
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
);
|
|
316
|
-
}).trace(
|
|
317
|
-
{ as: "global" },
|
|
318
|
-
({
|
|
319
|
-
id,
|
|
320
|
-
onRequest,
|
|
321
|
-
onParse,
|
|
322
|
-
onTransform,
|
|
323
|
-
onBeforeHandle,
|
|
324
|
-
onHandle,
|
|
325
|
-
onAfterHandle,
|
|
326
|
-
onError,
|
|
327
|
-
onAfterResponse,
|
|
328
|
-
onMapResponse,
|
|
329
|
-
context,
|
|
330
|
-
context: {
|
|
331
|
-
path,
|
|
332
|
-
request: { method }
|
|
333
|
-
}
|
|
334
|
-
}) => {
|
|
335
|
-
const rootSpan = import_api.trace.getActiveSpan();
|
|
336
|
-
if (!rootSpan) return;
|
|
337
|
-
function setParent(span) {
|
|
338
|
-
if (span.ended) return;
|
|
339
|
-
if (rootSpan.ended) return void span.end();
|
|
340
|
-
const newContext = import_api.trace.setSpan(import_api.context.active(), span);
|
|
341
|
-
const currentContext = (
|
|
342
|
-
// @ts-expect-error private property
|
|
343
|
-
import_api.context.active()._currentContext
|
|
344
|
-
);
|
|
345
|
-
currentContext?.set(
|
|
346
|
-
contextKeySpan,
|
|
347
|
-
newContext.getValue(contextKeySpan)
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
function inspect(name) {
|
|
351
|
-
return function inspect2({
|
|
352
|
-
onEvent,
|
|
353
|
-
total,
|
|
354
|
-
onStop
|
|
355
|
-
}) {
|
|
356
|
-
if (total === 0 || // @ts-ignore
|
|
357
|
-
rootSpan.ended)
|
|
358
|
-
return;
|
|
359
|
-
tracer.startActiveSpan(
|
|
360
|
-
name,
|
|
361
|
-
{},
|
|
362
|
-
createContext(rootSpan),
|
|
363
|
-
(event) => {
|
|
364
|
-
if (
|
|
365
|
-
// @ts-ignore
|
|
366
|
-
rootSpan.ended
|
|
367
|
-
)
|
|
368
|
-
return;
|
|
369
|
-
onEvent(({ name: name2, onStop: onStop2 }) => {
|
|
370
|
-
const useChildSpan = total > 1;
|
|
371
|
-
let span;
|
|
372
|
-
if (useChildSpan) {
|
|
373
|
-
span = tracer.startSpan(
|
|
374
|
-
name2,
|
|
375
|
-
{},
|
|
376
|
-
createContext(event)
|
|
377
|
-
);
|
|
378
|
-
setParent(span);
|
|
379
|
-
} else {
|
|
380
|
-
setParent(event);
|
|
381
|
-
span = event;
|
|
382
|
-
}
|
|
383
|
-
onStop2(({ error }) => {
|
|
384
|
-
setParent(rootSpan);
|
|
385
|
-
if (span.ended || rootSpan.ended)
|
|
386
|
-
return;
|
|
387
|
-
if (error) {
|
|
388
|
-
span.setAttributes({
|
|
389
|
-
"error.type": error.constructor?.name ?? error.name,
|
|
390
|
-
"error.stack": error.stack
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
if (useChildSpan) span.end();
|
|
394
|
-
});
|
|
395
|
-
});
|
|
396
|
-
onStop(() => {
|
|
397
|
-
setParent(rootSpan);
|
|
398
|
-
if (event.ended) return;
|
|
399
|
-
event.end();
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
);
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
const rawUrl = context.url;
|
|
406
|
-
const qi = context.qi;
|
|
407
|
-
const hasQuery = qi !== void 0 && qi !== -1;
|
|
408
|
-
let urlQuery = hasQuery ? rawUrl.slice(qi + 1) : void 0;
|
|
409
|
-
let urlFull = rawUrl;
|
|
410
|
-
if (urlRedactOpts) {
|
|
411
|
-
if (urlQuery !== void 0) {
|
|
412
|
-
urlQuery = redactQueryString(urlQuery, sensitiveKeys);
|
|
413
|
-
urlFull = `${rawUrl.slice(0, qi)}?${urlQuery}`;
|
|
414
|
-
}
|
|
415
|
-
if (stripCreds && urlFull.indexOf("@") > 0) {
|
|
416
|
-
try {
|
|
417
|
-
const u = new URL(urlFull);
|
|
418
|
-
if (u.username || u.password) {
|
|
419
|
-
u.username = "";
|
|
420
|
-
u.password = "";
|
|
421
|
-
urlFull = u.href;
|
|
422
|
-
}
|
|
423
|
-
} catch {
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
const attributes = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
428
|
-
// ? Elysia Custom attribute
|
|
429
|
-
"http.request.id": id,
|
|
430
|
-
"http.request.method": method,
|
|
431
|
-
"url.path": path,
|
|
432
|
-
"url.full": urlFull
|
|
433
|
-
});
|
|
434
|
-
if (urlQuery !== void 0) attributes["url.query"] = urlQuery;
|
|
435
|
-
const protocolSeparator = urlFull.indexOf("://");
|
|
436
|
-
if (protocolSeparator > 0)
|
|
437
|
-
attributes["url.scheme"] = urlFull.slice(
|
|
438
|
-
0,
|
|
439
|
-
protocolSeparator
|
|
440
|
-
);
|
|
441
|
-
const requestStartTime = performance.now();
|
|
442
|
-
let durationRecorded = false;
|
|
443
|
-
const recordDuration = () => {
|
|
444
|
-
if (durationRecorded) return;
|
|
445
|
-
durationRecorded = true;
|
|
446
|
-
const durationS = (performance.now() - requestStartTime) / 1e3;
|
|
447
|
-
const statusCode = attributes["http.response.status_code"];
|
|
448
|
-
const metricAttributes = {
|
|
449
|
-
"http.request.method": attributes["http.request.method"] ?? method,
|
|
450
|
-
"url.scheme": attributes["url.scheme"],
|
|
451
|
-
"http.response.status_code": statusCode,
|
|
452
|
-
"http.route": attributes["http.route"]
|
|
453
|
-
};
|
|
454
|
-
if (typeof statusCode === "number" && statusCode >= 500)
|
|
455
|
-
metricAttributes["error.type"] = String(statusCode);
|
|
456
|
-
httpServerDuration.record(durationS, metricAttributes);
|
|
457
|
-
};
|
|
458
|
-
onRequest(inspect("Request"));
|
|
459
|
-
onParse(inspect("Parse"));
|
|
460
|
-
onTransform(inspect("Transform"));
|
|
461
|
-
onBeforeHandle(inspect("BeforeHandle"));
|
|
462
|
-
onHandle(({ onStop }) => {
|
|
463
|
-
const span = tracer.startSpan(
|
|
464
|
-
"Handle",
|
|
465
|
-
{},
|
|
466
|
-
createContext(rootSpan)
|
|
467
|
-
);
|
|
468
|
-
setParent(span);
|
|
469
|
-
onStop(({ error }) => {
|
|
470
|
-
setParent(rootSpan);
|
|
471
|
-
if (span.ended || rootSpan.ended) return;
|
|
472
|
-
if (error) {
|
|
473
|
-
span.recordException(error);
|
|
474
|
-
rootSpan.recordException(error);
|
|
475
|
-
}
|
|
476
|
-
span.end();
|
|
477
|
-
});
|
|
478
|
-
});
|
|
479
|
-
onAfterHandle(inspect("AfterHandle"));
|
|
480
|
-
onError((event) => {
|
|
481
|
-
inspect("Error")(event);
|
|
482
|
-
event.onStop(({ error }) => {
|
|
483
|
-
setParent(rootSpan);
|
|
484
|
-
if (rootSpan.ended) return;
|
|
485
|
-
{
|
|
486
|
-
let status = context.set.status;
|
|
487
|
-
if (typeof status === "string") {
|
|
488
|
-
status = import_elysia.StatusMap[status];
|
|
489
|
-
} else if (typeof status !== "number" && // @ts-ignore
|
|
490
|
-
typeof error?.status === "number")
|
|
491
|
-
status = error.status;
|
|
492
|
-
if (typeof status === "number") {
|
|
493
|
-
attributes["http.response.status_code"] = status;
|
|
494
|
-
if (status >= 500)
|
|
495
|
-
rootSpan.setStatus({
|
|
496
|
-
code: import_api.SpanStatusCode.ERROR
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
rootSpan.setAttributes(attributes);
|
|
500
|
-
}
|
|
501
|
-
if (
|
|
502
|
-
// @ts-ignore
|
|
503
|
-
!rootSpan.ended
|
|
504
|
-
) {
|
|
505
|
-
recordDuration();
|
|
506
|
-
rootSpan.end();
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
});
|
|
510
|
-
onMapResponse(inspect("MapResponse"));
|
|
511
|
-
onTransform(() => {
|
|
512
|
-
const { cookie, request, route, path: path2 } = context;
|
|
513
|
-
if (route)
|
|
514
|
-
rootSpan.updateName(
|
|
515
|
-
// @ts-ignore private property
|
|
516
|
-
`${method} ${route || path2}`
|
|
517
|
-
);
|
|
518
|
-
if (context.route) attributes["http.route"] = context.route;
|
|
519
|
-
const contentLength = request.headers.get("content-length");
|
|
520
|
-
if (contentLength) {
|
|
521
|
-
const number = parseNumericString(contentLength);
|
|
522
|
-
if (number !== null)
|
|
523
|
-
attributes["http.request_content_length"] = number;
|
|
524
|
-
}
|
|
525
|
-
const userAgent = request.headers.get("User-Agent");
|
|
526
|
-
if (userAgent) attributes["user_agent.original"] = userAgent;
|
|
527
|
-
const server = context.server;
|
|
528
|
-
if (server) {
|
|
529
|
-
attributes["server.port"] = server.port ?? 80;
|
|
530
|
-
attributes["server.address"] = server.url.hostname;
|
|
531
|
-
}
|
|
532
|
-
let headers;
|
|
533
|
-
{
|
|
534
|
-
let hasHeaders;
|
|
535
|
-
let _headers;
|
|
536
|
-
if (context.headers) {
|
|
537
|
-
hasHeaders = true;
|
|
538
|
-
headers = context.headers;
|
|
539
|
-
_headers = Object.entries(context.headers);
|
|
540
|
-
} else if (hasHeaders = headerHasToJSON) {
|
|
541
|
-
headers = request.headers.toJSON();
|
|
542
|
-
_headers = Object.entries(headers);
|
|
543
|
-
} else {
|
|
544
|
-
headers = {};
|
|
545
|
-
_headers = request.headers.entries();
|
|
546
|
-
}
|
|
547
|
-
for (let [key, value] of _headers) {
|
|
548
|
-
key = key.toLowerCase();
|
|
549
|
-
if (hasHeaders) {
|
|
550
|
-
if (!requestHeaderWildcard && !spanRequestHeaderSet.has(key))
|
|
551
|
-
continue;
|
|
552
|
-
if (typeof value === "object")
|
|
553
|
-
attributes[`http.request.header.${key}`] = JSON.stringify(value);
|
|
554
|
-
else if (value !== void 0)
|
|
555
|
-
attributes[`http.request.header.${key}`] = value;
|
|
556
|
-
continue;
|
|
557
|
-
}
|
|
558
|
-
if (typeof value === "object") {
|
|
559
|
-
const serialized = JSON.stringify(value);
|
|
560
|
-
headers[key] = serialized;
|
|
561
|
-
if (requestHeaderWildcard || spanRequestHeaderSet.has(key))
|
|
562
|
-
attributes[`http.request.header.${key}`] = serialized;
|
|
563
|
-
} else if (value !== void 0) {
|
|
564
|
-
headers[key] = value;
|
|
565
|
-
if (requestHeaderWildcard || spanRequestHeaderSet.has(key))
|
|
566
|
-
attributes[`http.request.header.${key}`] = value;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
{
|
|
571
|
-
let headers2;
|
|
572
|
-
if (context.set.headers instanceof Headers) {
|
|
573
|
-
if (headerHasToJSON)
|
|
574
|
-
headers2 = Object.entries(
|
|
575
|
-
// @ts-ignore bun only
|
|
576
|
-
context.set.headers.toJSON()
|
|
577
|
-
);
|
|
578
|
-
else headers2 = context.set.headers.entries();
|
|
579
|
-
} else headers2 = Object.entries(context.set.headers);
|
|
580
|
-
for (let [key, value] of headers2) {
|
|
581
|
-
key = key.toLowerCase();
|
|
582
|
-
if (!responseHeaderWildcard && !spanResponseHeaderSet.has(key))
|
|
583
|
-
continue;
|
|
584
|
-
if (typeof value === "object")
|
|
585
|
-
attributes[`http.response.header.${key}`] = JSON.stringify(value);
|
|
586
|
-
else
|
|
587
|
-
attributes[`http.response.header.${key}`] = value;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
if (context.ip)
|
|
591
|
-
attributes["client.address"] = context.ip;
|
|
592
|
-
else {
|
|
593
|
-
const ip = headers["true-client-ip"] ?? headers["cf-connection-ip"] ?? headers["x-forwarded-for"] ?? headers["x-real-ip"] ?? server?.requestIP(request);
|
|
594
|
-
if (ip)
|
|
595
|
-
attributes["client.address"] = typeof ip === "string" ? ip : ip.address ?? ip.toString();
|
|
596
|
-
}
|
|
597
|
-
if ((requestHeaderWildcard || spanRequestHeaderSet.has("cookie")) && cookie) {
|
|
598
|
-
const _cookie = {};
|
|
599
|
-
for (const [key, { value }] of Object.entries(cookie))
|
|
600
|
-
_cookie[key] = JSON.stringify(value);
|
|
601
|
-
attributes["http.request.cookie"] = JSON.stringify(_cookie);
|
|
602
|
-
}
|
|
603
|
-
rootSpan.setAttributes(attributes);
|
|
604
|
-
});
|
|
605
|
-
onParse(() => {
|
|
606
|
-
const body = context.body;
|
|
607
|
-
if (body === void 0 || body === null || !recordRequestBody)
|
|
608
|
-
return;
|
|
609
|
-
const { text, size } = serializeBody(body);
|
|
610
|
-
if (text) attributes["http.request.body"] = text;
|
|
611
|
-
attributes["http.request.body.size"] = size;
|
|
612
|
-
});
|
|
613
|
-
onMapResponse(() => {
|
|
614
|
-
const body = context.body;
|
|
615
|
-
if (body !== void 0 && body !== null && recordRequestBody) {
|
|
616
|
-
const { text, size } = serializeBody(body);
|
|
617
|
-
if (text) attributes["http.request.body"] = text;
|
|
618
|
-
attributes["http.request.body.size"] = size;
|
|
619
|
-
}
|
|
620
|
-
{
|
|
621
|
-
let status = context.set.status ?? 200;
|
|
622
|
-
if (typeof status === "string")
|
|
623
|
-
status = import_elysia.StatusMap[status] ?? 200;
|
|
624
|
-
attributes["http.response.status_code"] = status;
|
|
625
|
-
}
|
|
626
|
-
const response = context.responseValue;
|
|
627
|
-
if (response !== void 0 && recordResponseBody) {
|
|
628
|
-
const { text, size } = serializeBody(response);
|
|
629
|
-
if (text) attributes["http.response.body"] = text;
|
|
630
|
-
attributes["http.response.body.size"] = size;
|
|
631
|
-
}
|
|
632
|
-
if (!rootSpan.ended) {
|
|
633
|
-
const statusCode = attributes["http.response.status_code"];
|
|
634
|
-
if (typeof statusCode === "number" && statusCode >= 500) {
|
|
635
|
-
rootSpan.setStatus({
|
|
636
|
-
code: import_api.SpanStatusCode.ERROR
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
rootSpan.setAttributes(attributes);
|
|
640
|
-
}
|
|
641
|
-
});
|
|
642
|
-
onAfterResponse((event) => {
|
|
643
|
-
inspect("AfterResponse")(event);
|
|
644
|
-
{
|
|
645
|
-
let status = context.set.status ?? 200;
|
|
646
|
-
if (typeof status === "string")
|
|
647
|
-
status = import_elysia.StatusMap[status] ?? 200;
|
|
648
|
-
attributes["http.response.status_code"] = status;
|
|
649
|
-
}
|
|
650
|
-
const body = context.body;
|
|
651
|
-
if (body !== void 0 && body !== null && recordRequestBody) {
|
|
652
|
-
const { text, size } = serializeBody(body);
|
|
653
|
-
if (text) attributes["http.request.body"] = text;
|
|
654
|
-
attributes["http.request.body.size"] = size;
|
|
655
|
-
}
|
|
656
|
-
if (!rootSpan.ended) {
|
|
657
|
-
const statusCode = attributes["http.response.status_code"];
|
|
658
|
-
if (typeof statusCode === "number" && statusCode >= 500)
|
|
659
|
-
rootSpan.setStatus({
|
|
660
|
-
code: import_api.SpanStatusCode.ERROR
|
|
661
|
-
});
|
|
662
|
-
rootSpan.setAttributes(attributes);
|
|
663
|
-
}
|
|
664
|
-
event.onStop(() => {
|
|
665
|
-
setParent(rootSpan);
|
|
666
|
-
if (rootSpan.ended) return;
|
|
667
|
-
if (
|
|
668
|
-
// @ts-ignore
|
|
669
|
-
!rootSpan.ended
|
|
670
|
-
) {
|
|
671
|
-
recordDuration();
|
|
672
|
-
rootSpan.end();
|
|
673
|
-
}
|
|
674
|
-
});
|
|
675
|
-
});
|
|
676
|
-
context.request.signal.addEventListener("abort", () => {
|
|
677
|
-
const active = import_api.trace.getActiveSpan();
|
|
678
|
-
if (active && !active.ended) active.end();
|
|
679
|
-
if (rootSpan.ended) return;
|
|
680
|
-
rootSpan.setStatus({
|
|
681
|
-
code: import_api.SpanStatusCode.ERROR,
|
|
682
|
-
message: "Request aborted"
|
|
683
|
-
});
|
|
684
|
-
recordDuration();
|
|
685
|
-
rootSpan.end();
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
);
|
|
689
|
-
};
|
|
690
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
691
|
-
0 && (module.exports = {
|
|
692
|
-
contextKeySpan,
|
|
693
|
-
getCurrentSpan,
|
|
694
|
-
getTracer,
|
|
695
|
-
opentelemetry,
|
|
696
|
-
record,
|
|
697
|
-
setAttributes,
|
|
698
|
-
shouldStartNodeSDK,
|
|
699
|
-
startActiveSpan,
|
|
700
|
-
startSpan
|
|
701
|
-
});
|