@oconde/radar 0.2.0 → 0.4.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/CHANGELOG.md +27 -0
- package/README.md +21 -0
- package/dist/{client-CZHtsQAd.d.cts → client-DRZ7htMJ.d.cts} +27 -2
- package/dist/{client-DbBsXgpj.d.ts → client-FkXWx8sJ.d.ts} +27 -2
- package/dist/index.cjs +218 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +227 -30
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +218 -21
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +227 -30
- package/dist/nest/index.js.map +1 -1
- package/dist/sveltekit/index.cjs +220 -23
- package/dist/sveltekit/index.cjs.map +1 -1
- package/dist/sveltekit/index.d.cts +1 -1
- package/dist/sveltekit/index.d.ts +1 -1
- package/dist/sveltekit/index.js +231 -34
- package/dist/sveltekit/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
2
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3
3
|
import { hostname } from "os";
|
|
4
|
-
import { performance as
|
|
4
|
+
import { performance as performance4 } from "perf_hooks";
|
|
5
5
|
|
|
6
6
|
// src/context.ts
|
|
7
7
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -55,7 +55,7 @@ function requestIdFrom(incoming) {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// src/express.ts
|
|
58
|
-
import { performance } from "perf_hooks";
|
|
58
|
+
import { performance as performance2 } from "perf_hooks";
|
|
59
59
|
|
|
60
60
|
// src/redact.ts
|
|
61
61
|
import { createHash, createHmac, randomBytes } from "crypto";
|
|
@@ -253,9 +253,18 @@ function requestPath(req) {
|
|
|
253
253
|
const end = url.indexOf("?");
|
|
254
254
|
return end >= 0 ? url.slice(0, end) : url;
|
|
255
255
|
}
|
|
256
|
+
function matchesRequest(pattern, path, route) {
|
|
257
|
+
const candidates = route === void 0 ? [path] : [path, route];
|
|
258
|
+
if (pattern instanceof RegExp) return candidates.some((value) => value.search(pattern) !== -1);
|
|
259
|
+
const prefix = pattern.endsWith("/") ? pattern : `${pattern}/`;
|
|
260
|
+
return candidates.some((value) => value === pattern || value.startsWith(prefix));
|
|
261
|
+
}
|
|
256
262
|
function requestRoute(req, route) {
|
|
257
263
|
if (route) return route;
|
|
258
|
-
|
|
264
|
+
if (typeof req.route?.path !== "string") return void 0;
|
|
265
|
+
const base = typeof req.baseUrl === "string" ? req.baseUrl.replace(/\/+$/, "") : "";
|
|
266
|
+
if (!base) return req.route.path;
|
|
267
|
+
return req.route.path === "/" ? base : `${base}${req.route.path}`;
|
|
259
268
|
}
|
|
260
269
|
var ROUTE_PARAM = /^:([A-Za-z_$][\w$]*)/;
|
|
261
270
|
function pathSegments(value) {
|
|
@@ -375,7 +384,7 @@ function createMiddleware(logger) {
|
|
|
375
384
|
let context;
|
|
376
385
|
try {
|
|
377
386
|
const requestId = requestIdFrom(headerValue(req.headers["x-request-id"]));
|
|
378
|
-
context = { requestId, startedAt:
|
|
387
|
+
context = { requestId, startedAt: performance2.now(), req };
|
|
379
388
|
res.setHeader("x-request-id", requestId);
|
|
380
389
|
if (logger.shouldLogRequest(req)) res.once("finish", () => logger.logHttpRequest(context, res.statusCode));
|
|
381
390
|
} catch {
|
|
@@ -389,6 +398,25 @@ function createMiddleware(logger) {
|
|
|
389
398
|
// src/options.ts
|
|
390
399
|
var DEFAULT_ENDPOINT = "https://radar-ingest.oconde.dev";
|
|
391
400
|
var LEVELS = ["debug", "info", "warn", "error"];
|
|
401
|
+
function patterns(value) {
|
|
402
|
+
if (!Array.isArray(value)) return [];
|
|
403
|
+
return value.flatMap((item) => {
|
|
404
|
+
if (item instanceof RegExp) return [item];
|
|
405
|
+
if (typeof item === "string" && item.trim() !== "") return [item.trim()];
|
|
406
|
+
return [];
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
function resolveTraceFetch(value) {
|
|
410
|
+
if (!value) return { enabled: false, propagateTo: [], ignore: [] };
|
|
411
|
+
if (value === true) return { enabled: true, propagateTo: [], ignore: [] };
|
|
412
|
+
return { enabled: true, propagateTo: patterns(value.propagateTo), ignore: patterns(value.ignore) };
|
|
413
|
+
}
|
|
414
|
+
function resolveLogRequests(value) {
|
|
415
|
+
if (value === false) return { enabled: false, include: [], exclude: [], sample: 1 };
|
|
416
|
+
if (value === void 0 || value === true || typeof value !== "object" || value === null) return { enabled: true, include: [], exclude: [], sample: 1 };
|
|
417
|
+
const sample = typeof value.sample === "number" && Number.isFinite(value.sample) && value.sample >= 0 && value.sample <= 1 ? value.sample : 1;
|
|
418
|
+
return { enabled: true, include: patterns(value.include), exclude: patterns(value.exclude), sample };
|
|
419
|
+
}
|
|
392
420
|
function resolveOptions(options = {}, env = process.env) {
|
|
393
421
|
const key = options.key?.trim() || void 0;
|
|
394
422
|
return {
|
|
@@ -401,9 +429,10 @@ function resolveOptions(options = {}, env = process.env) {
|
|
|
401
429
|
minLevel: options.minLevel && LEVELS.includes(options.minLevel) ? options.minLevel : "info",
|
|
402
430
|
redact: options.redact === "none" ? "none" : "mask",
|
|
403
431
|
requestDetail: options.requestDetail === "route" ? "route" : "full",
|
|
404
|
-
logRequests: options.logRequests
|
|
432
|
+
logRequests: resolveLogRequests(options.logRequests),
|
|
405
433
|
ignorePaths: options.ignorePaths ?? ["/healthz", "/health"],
|
|
406
434
|
captureUnhandled: options.captureUnhandled ?? true,
|
|
435
|
+
traceFetch: resolveTraceFetch(options.traceFetch),
|
|
407
436
|
debug: options.debug ?? false
|
|
408
437
|
};
|
|
409
438
|
}
|
|
@@ -471,6 +500,7 @@ var IDENTIFIER = "[A-Za-z_$][\\w$]*";
|
|
|
471
500
|
var MAX_LINES_UP = 400;
|
|
472
501
|
var MAX_HEADER_LINES = 6;
|
|
473
502
|
var MAX_NAME_LENGTH = 100;
|
|
503
|
+
var MAX_COMMENT_LINES = 40;
|
|
474
504
|
var CONTROL_BLOCK = /^\s*(?:\}\s*)?(?:if|else|for|while|do|switch|try|catch|finally|with)\b/;
|
|
475
505
|
var CLASS_BODY = new RegExp(`\\bclass\\s+${IDENTIFIER}`);
|
|
476
506
|
var MARKUP_BOUNDARY = /<\/?(?:script|style|template)\b/i;
|
|
@@ -483,8 +513,58 @@ var NAME_PATTERNS = [
|
|
|
483
513
|
];
|
|
484
514
|
var METHOD_PATTERN = new RegExp(`^\\s*(?:(?:export|default|public|private|protected|static|async|override|readonly|get|set)\\s+)*\\*?\\s*(${IDENTIFIER})\\s*(?:<[^>]*>)?\\s*\\([^]*\\)\\s*(?::\\s*[^{]+)?$`);
|
|
485
515
|
var ANONYMOUS_FUNCTION = /\bfunction\b|=>/;
|
|
486
|
-
|
|
487
|
-
|
|
516
|
+
var STRING_LITERAL = /(["'`])(?:\\.|(?!\1)[^\\])*\1/g;
|
|
517
|
+
function lineCommentAt(text, from) {
|
|
518
|
+
for (let index = text.indexOf("//", from); index >= 0; index = text.indexOf("//", index + 1)) {
|
|
519
|
+
if (index === 0 || text[index - 1] !== ":") return index;
|
|
520
|
+
}
|
|
521
|
+
return -1;
|
|
522
|
+
}
|
|
523
|
+
function blockCommentAt(text, from) {
|
|
524
|
+
for (let index = text.indexOf("/*", from); index >= 0; index = text.indexOf("/*", index + 1)) {
|
|
525
|
+
if (index === 0 || text[index - 1] !== "\\") return index;
|
|
526
|
+
}
|
|
527
|
+
return -1;
|
|
528
|
+
}
|
|
529
|
+
function stripComments(text, insideComment, closesLater) {
|
|
530
|
+
let code = "";
|
|
531
|
+
let position = 0;
|
|
532
|
+
let inside = insideComment;
|
|
533
|
+
while (position < text.length) {
|
|
534
|
+
if (inside) {
|
|
535
|
+
const end = text.indexOf("*/", position);
|
|
536
|
+
if (end < 0) return { code, insideComment: true };
|
|
537
|
+
inside = false;
|
|
538
|
+
position = end + 2;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
const block = blockCommentAt(text, position);
|
|
542
|
+
const line = lineCommentAt(text, position);
|
|
543
|
+
if (line >= 0 && (block < 0 || line < block)) return { code: code + text.slice(position, line), insideComment: false };
|
|
544
|
+
if (block < 0) return { code: code + text.slice(position), insideComment: false };
|
|
545
|
+
if (text.indexOf("*/", block + 2) < 0 && !closesLater()) {
|
|
546
|
+
code += text.slice(position, block + 2);
|
|
547
|
+
position = block + 2;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
code += text.slice(position, block);
|
|
551
|
+
inside = true;
|
|
552
|
+
position = block + 2;
|
|
553
|
+
}
|
|
554
|
+
return { code, insideComment: inside };
|
|
555
|
+
}
|
|
556
|
+
function codeLines(lines, from, start, column) {
|
|
557
|
+
const plain = lines.slice(from, start + 1).map((line) => line.replace(STRING_LITERAL, '""'));
|
|
558
|
+
const closesWithin = (index) => plain.slice(index + 1, index + 1 + MAX_COMMENT_LINES).some((line) => line.includes("*/"));
|
|
559
|
+
const result = [];
|
|
560
|
+
let insideComment = false;
|
|
561
|
+
for (let index = 0; index < plain.length; index++) {
|
|
562
|
+
const text = index === plain.length - 1 && column ? (lines[start] ?? "").slice(0, Math.max(0, column - 1)).replace(STRING_LITERAL, '""') : plain[index] ?? "";
|
|
563
|
+
const stripped = stripComments(text, insideComment, () => closesWithin(index));
|
|
564
|
+
insideComment = stripped.insideComment;
|
|
565
|
+
result.push(stripped.code);
|
|
566
|
+
}
|
|
567
|
+
return result;
|
|
488
568
|
}
|
|
489
569
|
function parenBalance(text) {
|
|
490
570
|
let balance = 0;
|
|
@@ -494,17 +574,17 @@ function parenBalance(text) {
|
|
|
494
574
|
}
|
|
495
575
|
return balance;
|
|
496
576
|
}
|
|
497
|
-
function headerOf(
|
|
577
|
+
function headerOf(code, index, prefix) {
|
|
498
578
|
let header = prefix;
|
|
499
579
|
for (let previous = index - 1; previous >= 0 && previous >= index - MAX_HEADER_LINES; previous--) {
|
|
500
580
|
if (header.trim() !== "" && parenBalance(header) >= 0) break;
|
|
501
|
-
header = `${
|
|
581
|
+
header = `${code[previous] ?? ""} ${header}`;
|
|
502
582
|
}
|
|
503
583
|
return header;
|
|
504
584
|
}
|
|
505
585
|
function nameIn(header) {
|
|
506
|
-
const
|
|
507
|
-
for (const pattern of
|
|
586
|
+
const patterns2 = ANONYMOUS_FUNCTION.test(header) ? NAME_PATTERNS : [...NAME_PATTERNS, METHOD_PATTERN];
|
|
587
|
+
for (const pattern of patterns2) {
|
|
508
588
|
const name = pattern.exec(header)?.[1];
|
|
509
589
|
if (name && !KEYWORDS.has(name)) return name.slice(0, MAX_NAME_LENGTH);
|
|
510
590
|
}
|
|
@@ -513,11 +593,12 @@ function nameIn(header) {
|
|
|
513
593
|
function enclosingFunctionName(lines, line, column) {
|
|
514
594
|
const start = line - 1;
|
|
515
595
|
if (start < 0 || start >= lines.length) return void 0;
|
|
596
|
+
const from = Math.max(0, start - MAX_LINES_UP - MAX_HEADER_LINES);
|
|
597
|
+
const cleaned = codeLines(lines, from, start, column);
|
|
516
598
|
let depth = 0;
|
|
517
599
|
for (let index = start; index >= 0 && index >= start - MAX_LINES_UP; index--) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
const code = codeOnly(index === start && column ? raw.slice(0, Math.max(0, column - 1)) : raw);
|
|
600
|
+
if (index < start && MARKUP_BOUNDARY.test(lines[index] ?? "")) return void 0;
|
|
601
|
+
const code = cleaned[index - from] ?? "";
|
|
521
602
|
for (let position = code.length - 1; position >= 0; position--) {
|
|
522
603
|
const char = code[position];
|
|
523
604
|
if (char === "}") {
|
|
@@ -527,7 +608,7 @@ function enclosingFunctionName(lines, line, column) {
|
|
|
527
608
|
depth -= 1;
|
|
528
609
|
continue;
|
|
529
610
|
}
|
|
530
|
-
const header = headerOf(
|
|
611
|
+
const header = headerOf(cleaned, index - from, code.slice(0, position));
|
|
531
612
|
if (CLASS_BODY.test(header)) return void 0;
|
|
532
613
|
if (CONTROL_BLOCK.test(header)) continue;
|
|
533
614
|
const name = nameIn(header);
|
|
@@ -769,20 +850,118 @@ function safeStringify(value) {
|
|
|
769
850
|
}
|
|
770
851
|
}
|
|
771
852
|
|
|
772
|
-
// src/transport.ts
|
|
773
|
-
import { promisify } from "util";
|
|
774
|
-
import { gzip } from "zlib";
|
|
775
|
-
|
|
776
853
|
// src/util.ts
|
|
777
|
-
import { performance as
|
|
854
|
+
import { performance as performance3 } from "perf_hooks";
|
|
778
855
|
function describeError(error) {
|
|
779
856
|
return error instanceof Error ? error.message : String(error);
|
|
780
857
|
}
|
|
781
858
|
function elapsedSince(startedAt) {
|
|
782
|
-
return Math.round(
|
|
859
|
+
return Math.round(performance3.now() - startedAt);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// src/trace-fetch.ts
|
|
863
|
+
var WRAPPED = /* @__PURE__ */ Symbol.for("@oconde/radar.fetch");
|
|
864
|
+
var REQUEST_ID_HEADER = "x-request-id";
|
|
865
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
866
|
+
var TELEGRAM_BOT = /^bot\d{5,}:[\w-]{20,}$/;
|
|
867
|
+
var TOKEN_LIKE = /^[\w\-.~+=]{20,}$/;
|
|
868
|
+
function secretSegment(segment) {
|
|
869
|
+
if (UUID.test(segment)) return false;
|
|
870
|
+
if (TELEGRAM_BOT.test(segment) || looksLikeCredential(segment)) return true;
|
|
871
|
+
return TOKEN_LIKE.test(segment) && /[A-Za-z]/.test(segment) && /\d/.test(segment);
|
|
872
|
+
}
|
|
873
|
+
function outboundPath(pathname, mode) {
|
|
874
|
+
if (mode === "none") return pathname;
|
|
875
|
+
return pathname.split("/").map((segment) => {
|
|
876
|
+
let decoded = segment;
|
|
877
|
+
try {
|
|
878
|
+
decoded = decodeURIComponent(segment);
|
|
879
|
+
} catch {
|
|
880
|
+
decoded = segment;
|
|
881
|
+
}
|
|
882
|
+
return secretSegment(decoded) ? maskValue(decoded, false) : segment;
|
|
883
|
+
}).join("/");
|
|
884
|
+
}
|
|
885
|
+
function failureOf(error) {
|
|
886
|
+
const message = describeError(error);
|
|
887
|
+
const cause = error instanceof Error ? error.cause : void 0;
|
|
888
|
+
const detail = typeof cause?.code === "string" ? cause.code : typeof cause?.message === "string" ? cause.message : "";
|
|
889
|
+
return detail && !message.includes(detail) ? `${message} (${detail})` : message;
|
|
890
|
+
}
|
|
891
|
+
function urlOf(input) {
|
|
892
|
+
try {
|
|
893
|
+
if (typeof input === "string") return new URL(input);
|
|
894
|
+
if (input instanceof URL) return input;
|
|
895
|
+
return new URL(input.url);
|
|
896
|
+
} catch {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
function originOf(value) {
|
|
901
|
+
try {
|
|
902
|
+
return new URL(value).origin;
|
|
903
|
+
} catch {
|
|
904
|
+
return null;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
function hostMatches(url, host) {
|
|
908
|
+
const wanted = host.trim().toLowerCase();
|
|
909
|
+
if (wanted.startsWith(".")) return url.hostname.toLowerCase().endsWith(wanted);
|
|
910
|
+
return url.host.toLowerCase() === wanted || url.hostname.toLowerCase() === wanted;
|
|
911
|
+
}
|
|
912
|
+
function targets(url, target) {
|
|
913
|
+
if (target instanceof RegExp) return url.host.search(target) !== -1;
|
|
914
|
+
return hostMatches(url, target);
|
|
915
|
+
}
|
|
916
|
+
function ignored(url, target) {
|
|
917
|
+
if (target instanceof RegExp) return `${url.host}${url.pathname}`.search(target) !== -1;
|
|
918
|
+
return hostMatches(url, target);
|
|
919
|
+
}
|
|
920
|
+
function isPlainObject(value) {
|
|
921
|
+
if (value === null || typeof value !== "object") return false;
|
|
922
|
+
const prototype = Object.getPrototypeOf(value);
|
|
923
|
+
return prototype === Object.prototype || prototype === null;
|
|
924
|
+
}
|
|
925
|
+
function withRequestId(input, init, requestId) {
|
|
926
|
+
const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : void 0));
|
|
927
|
+
if (headers.has(REQUEST_ID_HEADER)) return [input, init];
|
|
928
|
+
headers.set(REQUEST_ID_HEADER, requestId);
|
|
929
|
+
if (init === void 0 || isPlainObject(init)) return [input, { ...init, headers }];
|
|
930
|
+
return [new Request(input, init), { headers }];
|
|
931
|
+
}
|
|
932
|
+
function traceFetch(config) {
|
|
933
|
+
const current = globalThis.fetch;
|
|
934
|
+
if (typeof current !== "function" || current[WRAPPED]) return () => void 0;
|
|
935
|
+
const original = current;
|
|
936
|
+
const radarOrigin = originOf(config.endpoint);
|
|
937
|
+
const traced = async (input, init) => {
|
|
938
|
+
const url = urlOf(input);
|
|
939
|
+
if (!url || url.origin === radarOrigin || url.protocol !== "http:" && url.protocol !== "https:") return original(input, init);
|
|
940
|
+
const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
|
|
941
|
+
const context = currentContext();
|
|
942
|
+
const [nextInput, nextInit] = context && config.propagateTo.some((target) => targets(url, target)) ? withRequestId(input, init, context.requestId) : [input, init];
|
|
943
|
+
if (config.ignore?.some((target) => ignored(url, target))) return original(nextInput, nextInit);
|
|
944
|
+
const attrs = { method, host: url.host, path: outboundPath(url.pathname, config.redact) };
|
|
945
|
+
const started = performance.now();
|
|
946
|
+
try {
|
|
947
|
+
const response = await original(nextInput, nextInit);
|
|
948
|
+
config.record(response.status >= 500 ? "error" : response.status >= 400 ? "warn" : "info", { ...attrs, status: response.status, durationMs: elapsedSince(started) });
|
|
949
|
+
return response;
|
|
950
|
+
} catch (error) {
|
|
951
|
+
config.record("error", { ...attrs, error: failureOf(error), durationMs: elapsedSince(started) });
|
|
952
|
+
throw error;
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
Object.defineProperty(traced, WRAPPED, { value: original });
|
|
956
|
+
globalThis.fetch = traced;
|
|
957
|
+
return () => {
|
|
958
|
+
if (globalThis.fetch === traced) globalThis.fetch = original;
|
|
959
|
+
};
|
|
783
960
|
}
|
|
784
961
|
|
|
785
962
|
// src/transport.ts
|
|
963
|
+
import { promisify } from "util";
|
|
964
|
+
import { gzip } from "zlib";
|
|
786
965
|
var gzipAsync = promisify(gzip);
|
|
787
966
|
var MAX_BATCH_BYTES = 9e5;
|
|
788
967
|
var GZIP_THRESHOLD_BYTES = 8192;
|
|
@@ -1010,7 +1189,7 @@ function withTimeout(promise, ms) {
|
|
|
1010
1189
|
|
|
1011
1190
|
// src/version.ts
|
|
1012
1191
|
var SDK_NAME = "@oconde/radar";
|
|
1013
|
-
var SDK_VERSION = true ? "0.
|
|
1192
|
+
var SDK_VERSION = true ? "0.4.1" : "0.0.0-dev";
|
|
1014
1193
|
|
|
1015
1194
|
// src/client.ts
|
|
1016
1195
|
var MAX_CHECK_IN_DURATION_MS = 7 * 864e5;
|
|
@@ -1022,6 +1201,7 @@ var RadarClient = class {
|
|
|
1022
1201
|
initialized = false;
|
|
1023
1202
|
closed = false;
|
|
1024
1203
|
captured = /* @__PURE__ */ new WeakSet();
|
|
1204
|
+
restoreFetch = null;
|
|
1025
1205
|
get isEnabled() {
|
|
1026
1206
|
return this.transport !== null && !this.closed;
|
|
1027
1207
|
}
|
|
@@ -1049,6 +1229,15 @@ var RadarClient = class {
|
|
|
1049
1229
|
});
|
|
1050
1230
|
}
|
|
1051
1231
|
if (this.options.captureUnhandled && (this.transport || this.options.console)) installProcessHandlers(this);
|
|
1232
|
+
if (this.options.traceFetch.enabled && (this.transport || this.options.console)) {
|
|
1233
|
+
this.restoreFetch = traceFetch({
|
|
1234
|
+
endpoint: this.options.endpoint,
|
|
1235
|
+
propagateTo: this.options.traceFetch.propagateTo,
|
|
1236
|
+
ignore: this.options.traceFetch.ignore,
|
|
1237
|
+
redact: this.options.redact,
|
|
1238
|
+
record: (level, attrs) => this.safely(() => this.emitLog(level, "http.client", attrs))
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1052
1241
|
} catch (error) {
|
|
1053
1242
|
this.debugWarn(`radar.init falhou: ${describeError(error)}`);
|
|
1054
1243
|
}
|
|
@@ -1092,7 +1281,7 @@ var RadarClient = class {
|
|
|
1092
1281
|
}
|
|
1093
1282
|
async track(name, fn, data) {
|
|
1094
1283
|
const execute = async () => {
|
|
1095
|
-
const started =
|
|
1284
|
+
const started = performance4.now();
|
|
1096
1285
|
try {
|
|
1097
1286
|
const result = await fn();
|
|
1098
1287
|
this.info(name, { ...data, durationMs: elapsedSince(started), ok: true });
|
|
@@ -1104,10 +1293,10 @@ var RadarClient = class {
|
|
|
1104
1293
|
}
|
|
1105
1294
|
};
|
|
1106
1295
|
if (currentContext()) return execute();
|
|
1107
|
-
return runWithContext({ requestId: randomUUID2(), startedAt:
|
|
1296
|
+
return runWithContext({ requestId: randomUUID2(), startedAt: performance4.now() }, execute);
|
|
1108
1297
|
}
|
|
1109
1298
|
withContext(fn, options = {}) {
|
|
1110
|
-
return runWithContext({ requestId: requestIdFrom(options.requestId), startedAt:
|
|
1299
|
+
return runWithContext({ requestId: requestIdFrom(options.requestId), startedAt: performance4.now() }, fn);
|
|
1111
1300
|
}
|
|
1112
1301
|
async checkIn(slug, status, options = {}) {
|
|
1113
1302
|
try {
|
|
@@ -1135,7 +1324,7 @@ var RadarClient = class {
|
|
|
1135
1324
|
}
|
|
1136
1325
|
async cron(slug, fn) {
|
|
1137
1326
|
const checkInId = randomUUID2();
|
|
1138
|
-
const started =
|
|
1327
|
+
const started = performance4.now();
|
|
1139
1328
|
const execute = async () => {
|
|
1140
1329
|
await this.checkIn(slug, "in_progress", { checkInId });
|
|
1141
1330
|
try {
|
|
@@ -1155,22 +1344,28 @@ var RadarClient = class {
|
|
|
1155
1344
|
return createMiddleware(this);
|
|
1156
1345
|
}
|
|
1157
1346
|
shouldLogRequest(req) {
|
|
1158
|
-
return this.options.logRequests && !this.options.ignorePaths.includes(requestPath(req));
|
|
1347
|
+
return this.options.logRequests.enabled && !this.options.ignorePaths.includes(requestPath(req));
|
|
1159
1348
|
}
|
|
1160
1349
|
logHttpRequest(context, status) {
|
|
1161
1350
|
this.safely(() => {
|
|
1162
1351
|
const req = context.req;
|
|
1163
1352
|
if (!req) return;
|
|
1164
|
-
const level = status >= 500 ? "error" : status >= 400 ? "warn" : "info";
|
|
1165
1353
|
const route = requestRoute(req, context.route);
|
|
1354
|
+
const path = requestPath(req);
|
|
1355
|
+
const { include, exclude, sample } = this.options.logRequests;
|
|
1356
|
+
if (include.length > 0 && !include.some((pattern) => matchesRequest(pattern, path, route))) return;
|
|
1357
|
+
if (exclude.some((pattern) => matchesRequest(pattern, path, route))) return;
|
|
1358
|
+
if (sample < 1 && Math.random() >= sample) return;
|
|
1359
|
+
const level = status >= 500 ? "error" : status >= 400 ? "warn" : "info";
|
|
1166
1360
|
runWithContext(
|
|
1167
1361
|
context,
|
|
1168
1362
|
() => this.emitLog(level, "http.request", {
|
|
1169
1363
|
method: (req.method ?? "GET").toUpperCase(),
|
|
1170
1364
|
...route ? { route } : {},
|
|
1171
|
-
...this.options.requestDetail === "full" ? { path: redactPath(
|
|
1365
|
+
...this.options.requestDetail === "full" ? { path: redactPath(path, pathParams(req, path), this.options.redact) } : {},
|
|
1172
1366
|
status,
|
|
1173
|
-
durationMs: elapsedSince(context.startedAt)
|
|
1367
|
+
durationMs: elapsedSince(context.startedAt),
|
|
1368
|
+
...sample < 1 ? { sampleRate: sample } : {}
|
|
1174
1369
|
})
|
|
1175
1370
|
);
|
|
1176
1371
|
});
|
|
@@ -1185,6 +1380,8 @@ var RadarClient = class {
|
|
|
1185
1380
|
async close(timeoutMs = 2e3) {
|
|
1186
1381
|
if (this.closed) return;
|
|
1187
1382
|
await this.flush(timeoutMs);
|
|
1383
|
+
this.restoreFetch?.();
|
|
1384
|
+
this.restoreFetch = null;
|
|
1188
1385
|
this.closed = true;
|
|
1189
1386
|
this.transport?.stop();
|
|
1190
1387
|
}
|