@tanngo11/log 0.4.2 → 0.4.4
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 +20 -0
- package/CONTRACT.md +1 -0
- package/README.md +13 -4
- package/dist/{chunk-BVKAY2OK.js → chunk-6ANRIB5B.js} +11 -2
- package/dist/{chunk-BVKAY2OK.js.map → chunk-6ANRIB5B.js.map} +1 -1
- package/dist/index.cjs +15 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/next.cjs +14 -0
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +7 -1
- package/dist/next.d.ts +7 -1
- package/dist/next.js +8 -1
- package/dist/next.js.map +1 -1
- package/dist/strapi.cjs +10 -1
- package/dist/strapi.cjs.map +1 -1
- package/dist/strapi.js +10 -1
- package/dist/strapi.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.4
|
|
4
|
+
|
|
5
|
+
Added:
|
|
6
|
+
- `logProcessWarnings(log)`: logs Node process warnings (for example pg's "client.query() while
|
|
7
|
+
executing" deprecation) as `process.warning` lines. Their `err_stack` points at the code
|
|
8
|
+
that triggered the warning. `registerNext` installs it.
|
|
9
|
+
|
|
10
|
+
## 0.4.3
|
|
11
|
+
|
|
12
|
+
Fixed:
|
|
13
|
+
- `patchConsole` drops console calls that carry an error already written on a summary line, so a
|
|
14
|
+
failed request is not logged twice.
|
|
15
|
+
- The Strapi transport honours the winston logger's runtime level. Strapi's data export and
|
|
16
|
+
import commands set it to `error` to keep their output quiet.
|
|
17
|
+
|
|
18
|
+
Added:
|
|
19
|
+
- `patchConsole(log, { skip })`.
|
|
20
|
+
- `nextConsoleSkip` (`/next`): drops Next's console copy of a render error, which
|
|
21
|
+
`onRequestError` logs with route and digest.
|
|
22
|
+
|
|
3
23
|
## 0.4.2
|
|
4
24
|
|
|
5
25
|
Fixed:
|
package/CONTRACT.md
CHANGED
|
@@ -78,6 +78,7 @@ System events shared by all services:
|
|
|
78
78
|
| `app.stopping` | info | the app starts its own graceful shutdown |
|
|
79
79
|
| `app.crashed` | fatal | uncaught error, process exits |
|
|
80
80
|
| `app.unhandled_error` | error | uncaught error, process keeps running |
|
|
81
|
+
| `process.warning` | warn | a Node process warning (deprecation...); `err_stack` shows the call site |
|
|
81
82
|
| `config.invalid` | fatal | missing or invalid config at startup (never log the value) |
|
|
82
83
|
| `http.request` | by status | one summary line per inbound request |
|
|
83
84
|
| `http.outbound` | warn | an outbound call failed (network error or 5xx) or was slow (≥ 1 s) |
|
package/README.md
CHANGED
|
@@ -127,6 +127,7 @@ await runJob(log, { job_name: "sync_stock", job_id: id }, () => syncStock()); //
|
|
|
127
127
|
await queue.add("send_invoice", jobData({ invoice_id })); // carries the current request_id into the job
|
|
128
128
|
|
|
129
129
|
installProcessHandlers(log); // app.crashed on uncaught errors, then exit(1) after 1s so Sentry & co. can flush
|
|
130
|
+
logProcessWarnings(log); // Node warnings (deprecations...) as process.warning with the call-site stack
|
|
130
131
|
logStartup(log, { port: 3000 }); // app.started
|
|
131
132
|
|
|
132
133
|
process.once("SIGTERM", async () => {
|
|
@@ -217,12 +218,14 @@ Server components and anything not wrapped:
|
|
|
217
218
|
```ts
|
|
218
219
|
// instrumentation.ts
|
|
219
220
|
import { patchConsole } from "@tanngo11/log";
|
|
220
|
-
import { nextOnRequestError, registerNext } from "@tanngo11/log/next";
|
|
221
|
+
import { nextConsoleSkip, nextOnRequestError, registerNext } from "@tanngo11/log/next";
|
|
221
222
|
import { log } from "@/lib/log";
|
|
222
223
|
|
|
223
224
|
export function register() {
|
|
224
|
-
registerNext(log); // app.started
|
|
225
|
-
|
|
225
|
+
registerNext(log); // app.started, crash and process-warning logging (Next keeps serving, so no exit)
|
|
226
|
+
// Next prints render errors with console.error before onRequestError logs them:
|
|
227
|
+
// nextConsoleSkip drops that copy so each error is one line.
|
|
228
|
+
patchConsole(log, { skip: nextConsoleSkip });
|
|
226
229
|
}
|
|
227
230
|
export const onRequestError = nextOnRequestError(log);
|
|
228
231
|
```
|
|
@@ -301,10 +304,16 @@ return [
|
|
|
301
304
|
It is recorded as `upstream_request_id`, which links both services' logs. Set
|
|
302
305
|
`trustIncomingRequestId: true` to adopt it instead.
|
|
303
306
|
- Winston levels are mapped: `http` and `verbose` become `debug`, `silly` becomes `trace`.
|
|
304
|
-
`LOG_LEVEL` filters.
|
|
307
|
+
`LOG_LEVEL` filters. A level set on the winston logger at runtime is honoured too: Strapi's
|
|
308
|
+
data export/import commands set it to `error`.
|
|
305
309
|
|
|
306
310
|
Tested against the versions Strapi 5.51 uses: Koa 2, `@koa/router` 12 and winston 3.10.
|
|
307
311
|
|
|
312
|
+
For Strapi, call `logProcessWarnings(log)` in `register()` of `src/index.ts`.
|
|
313
|
+
|
|
314
|
+
Node also prints its own text copy of each warning to stderr. Run with
|
|
315
|
+
`NODE_OPTIONS=--no-warnings` to keep only the JSON line.
|
|
316
|
+
|
|
308
317
|
## Prisma (5 and 6)
|
|
309
318
|
|
|
310
319
|
```ts
|
|
@@ -44,10 +44,19 @@ function installProcessHandlers(log, opts = {}) {
|
|
|
44
44
|
process.on("uncaughtException", h.onUncaught);
|
|
45
45
|
process.on("unhandledRejection", h.onRejection);
|
|
46
46
|
}
|
|
47
|
+
var warningState = globalSingleton("warnings", () => ({ installed: false }));
|
|
48
|
+
function logProcessWarnings(log) {
|
|
49
|
+
if (warningState.installed || typeof process === "undefined" || typeof process.on !== "function") return;
|
|
50
|
+
warningState.installed = true;
|
|
51
|
+
process.on("warning", (warning) => {
|
|
52
|
+
log.warn("process warning", { event: "process.warning", err: warning });
|
|
53
|
+
});
|
|
54
|
+
}
|
|
47
55
|
|
|
48
56
|
export {
|
|
49
57
|
logStartup,
|
|
50
58
|
logShutdown,
|
|
51
|
-
installProcessHandlers
|
|
59
|
+
installProcessHandlers,
|
|
60
|
+
logProcessWarnings
|
|
52
61
|
};
|
|
53
|
-
//# sourceMappingURL=chunk-
|
|
62
|
+
//# sourceMappingURL=chunk-6ANRIB5B.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/process.ts"],"sourcesContent":["import { globalSingleton } from \"./global\";\nimport type { Logger } from \"./logger\";\nimport type { Fields } from \"./normalize\";\n\nexport function logStartup(log: Logger, fields: Fields = {}): void {\n log.info(\"app started\", {\n event: \"app.started\",\n runtime_version: `node ${process.versions.node}`,\n log_level: log.level,\n ...fields,\n });\n}\n\n/** Call at the start of your own shutdown handler (e.g. on SIGTERM). The library never handles signals. */\nexport function logShutdown(log: Logger, fields: Fields = {}): void {\n log.info(\"app stopping\", { event: \"app.stopping\", ...fields });\n}\n\nexport interface ProcessHandlerOptions {\n /** Exit with code 1 after an uncaught error. Next.js keeps serving, so its adapter passes false. */\n exitOnCrash?: boolean;\n /** Time other crash handlers (Sentry, APM) get to flush before exit. Default 1000 ms. */\n exitDelayMs?: number;\n exit?: (code: number) => void;\n}\n\nexport function crashHandlers(log: Logger, opts: ProcessHandlerOptions = {}) {\n const exitOnCrash = opts.exitOnCrash ?? true;\n const exitDelayMs = opts.exitDelayMs ?? 1000;\n const exit = opts.exit ?? ((code: number) => process.exit(code));\n let exiting = false;\n const crash = (source: string, err: unknown) => {\n if (!exitOnCrash) {\n log.error(\"unhandled error\", { event: \"app.unhandled_error\", crash_source: source, err });\n return;\n }\n log.fatal(\"app crashed\", { event: \"app.crashed\", crash_source: source, err });\n if (exiting) return;\n exiting = true;\n if (typeof process !== \"undefined\") process.exitCode = 1;\n // Deferred so listeners registered after ours still run; unref so a process with nothing\n // left to do exits on its own (with exitCode 1) without waiting.\n const timer = setTimeout(() => exit(1), exitDelayMs);\n (timer as { unref?: () => void }).unref?.();\n };\n return {\n onUncaught: (err: unknown) => crash(\"uncaughtException\", err),\n onRejection: (reason: unknown) => crash(\"unhandledRejection\", reason),\n };\n}\n\nconst state = globalSingleton(\"process\", () => ({ installed: false }));\n\n/** Logs uncaught exceptions and unhandled rejections. Does not touch SIGTERM/SIGINT. */\nexport function installProcessHandlers(log: Logger, opts: ProcessHandlerOptions = {}): void {\n if (state.installed || typeof process === \"undefined\" || typeof process.on !== \"function\") return;\n state.installed = true;\n const h = crashHandlers(log, opts);\n process.on(\"uncaughtException\", h.onUncaught);\n process.on(\"unhandledRejection\", h.onRejection);\n}\n"],"mappings":";;;;;AAIO,SAAS,WAAW,KAAa,SAAiB,CAAC,GAAS;AACjE,MAAI,KAAK,eAAe;AAAA,IACtB,OAAO;AAAA,IACP,iBAAiB,QAAQ,QAAQ,SAAS,IAAI;AAAA,IAC9C,WAAW,IAAI;AAAA,IACf,GAAG;AAAA,EACL,CAAC;AACH;AAGO,SAAS,YAAY,KAAa,SAAiB,CAAC,GAAS;AAClE,MAAI,KAAK,gBAAgB,EAAE,OAAO,gBAAgB,GAAG,OAAO,CAAC;AAC/D;AAUO,SAAS,cAAc,KAAa,OAA8B,CAAC,GAAG;AAC3E,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,OAAO,KAAK,SAAS,CAAC,SAAiB,QAAQ,KAAK,IAAI;AAC9D,MAAI,UAAU;AACd,QAAM,QAAQ,CAAC,QAAgB,QAAiB;AAC9C,QAAI,CAAC,aAAa;AAChB,UAAI,MAAM,mBAAmB,EAAE,OAAO,uBAAuB,cAAc,QAAQ,IAAI,CAAC;AACxF;AAAA,IACF;AACA,QAAI,MAAM,eAAe,EAAE,OAAO,eAAe,cAAc,QAAQ,IAAI,CAAC;AAC5E,QAAI,QAAS;AACb,cAAU;AACV,QAAI,OAAO,YAAY,YAAa,SAAQ,WAAW;AAGvD,UAAM,QAAQ,WAAW,MAAM,KAAK,CAAC,GAAG,WAAW;AACnD,IAAC,MAAiC,QAAQ;AAAA,EAC5C;AACA,SAAO;AAAA,IACL,YAAY,CAAC,QAAiB,MAAM,qBAAqB,GAAG;AAAA,IAC5D,aAAa,CAAC,WAAoB,MAAM,sBAAsB,MAAM;AAAA,EACtE;AACF;AAEA,IAAM,QAAQ,gBAAgB,WAAW,OAAO,EAAE,WAAW,MAAM,EAAE;AAG9D,SAAS,uBAAuB,KAAa,OAA8B,CAAC,GAAS;AAC1F,MAAI,MAAM,aAAa,OAAO,YAAY,eAAe,OAAO,QAAQ,OAAO,WAAY;AAC3F,QAAM,YAAY;AAClB,QAAM,IAAI,cAAc,KAAK,IAAI;AACjC,UAAQ,GAAG,qBAAqB,EAAE,UAAU;AAC5C,UAAQ,GAAG,sBAAsB,EAAE,WAAW;AAChD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/process.ts"],"sourcesContent":["import { globalSingleton } from \"./global\";\nimport type { Logger } from \"./logger\";\nimport type { Fields } from \"./normalize\";\n\nexport function logStartup(log: Logger, fields: Fields = {}): void {\n log.info(\"app started\", {\n event: \"app.started\",\n runtime_version: `node ${process.versions.node}`,\n log_level: log.level,\n ...fields,\n });\n}\n\n/** Call at the start of your own shutdown handler (e.g. on SIGTERM). The library never handles signals. */\nexport function logShutdown(log: Logger, fields: Fields = {}): void {\n log.info(\"app stopping\", { event: \"app.stopping\", ...fields });\n}\n\nexport interface ProcessHandlerOptions {\n /** Exit with code 1 after an uncaught error. Next.js keeps serving, so its adapter passes false. */\n exitOnCrash?: boolean;\n /** Time other crash handlers (Sentry, APM) get to flush before exit. Default 1000 ms. */\n exitDelayMs?: number;\n exit?: (code: number) => void;\n}\n\nexport function crashHandlers(log: Logger, opts: ProcessHandlerOptions = {}) {\n const exitOnCrash = opts.exitOnCrash ?? true;\n const exitDelayMs = opts.exitDelayMs ?? 1000;\n const exit = opts.exit ?? ((code: number) => process.exit(code));\n let exiting = false;\n const crash = (source: string, err: unknown) => {\n if (!exitOnCrash) {\n log.error(\"unhandled error\", { event: \"app.unhandled_error\", crash_source: source, err });\n return;\n }\n log.fatal(\"app crashed\", { event: \"app.crashed\", crash_source: source, err });\n if (exiting) return;\n exiting = true;\n if (typeof process !== \"undefined\") process.exitCode = 1;\n // Deferred so listeners registered after ours still run; unref so a process with nothing\n // left to do exits on its own (with exitCode 1) without waiting.\n const timer = setTimeout(() => exit(1), exitDelayMs);\n (timer as { unref?: () => void }).unref?.();\n };\n return {\n onUncaught: (err: unknown) => crash(\"uncaughtException\", err),\n onRejection: (reason: unknown) => crash(\"unhandledRejection\", reason),\n };\n}\n\nconst state = globalSingleton(\"process\", () => ({ installed: false }));\n\n/** Logs uncaught exceptions and unhandled rejections. Does not touch SIGTERM/SIGINT. */\nexport function installProcessHandlers(log: Logger, opts: ProcessHandlerOptions = {}): void {\n if (state.installed || typeof process === \"undefined\" || typeof process.on !== \"function\") return;\n state.installed = true;\n const h = crashHandlers(log, opts);\n process.on(\"uncaughtException\", h.onUncaught);\n process.on(\"unhandledRejection\", h.onRejection);\n}\n\nconst warningState = globalSingleton(\"warnings\", () => ({ installed: false }));\n\n/**\n * Logs Node process warnings (deprecations, MaxListeners...) as `process.warning` lines whose\n * err_stack points at the code that triggered them. Node still prints its own stderr copy\n * unless the process runs with --no-warnings (NODE_OPTIONS=--no-warnings).\n */\nexport function logProcessWarnings(log: Logger): void {\n if (warningState.installed || typeof process === \"undefined\" || typeof process.on !== \"function\") return;\n warningState.installed = true;\n process.on(\"warning\", (warning: Error) => {\n log.warn(\"process warning\", { event: \"process.warning\", err: warning });\n });\n}\n"],"mappings":";;;;;AAIO,SAAS,WAAW,KAAa,SAAiB,CAAC,GAAS;AACjE,MAAI,KAAK,eAAe;AAAA,IACtB,OAAO;AAAA,IACP,iBAAiB,QAAQ,QAAQ,SAAS,IAAI;AAAA,IAC9C,WAAW,IAAI;AAAA,IACf,GAAG;AAAA,EACL,CAAC;AACH;AAGO,SAAS,YAAY,KAAa,SAAiB,CAAC,GAAS;AAClE,MAAI,KAAK,gBAAgB,EAAE,OAAO,gBAAgB,GAAG,OAAO,CAAC;AAC/D;AAUO,SAAS,cAAc,KAAa,OAA8B,CAAC,GAAG;AAC3E,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,OAAO,KAAK,SAAS,CAAC,SAAiB,QAAQ,KAAK,IAAI;AAC9D,MAAI,UAAU;AACd,QAAM,QAAQ,CAAC,QAAgB,QAAiB;AAC9C,QAAI,CAAC,aAAa;AAChB,UAAI,MAAM,mBAAmB,EAAE,OAAO,uBAAuB,cAAc,QAAQ,IAAI,CAAC;AACxF;AAAA,IACF;AACA,QAAI,MAAM,eAAe,EAAE,OAAO,eAAe,cAAc,QAAQ,IAAI,CAAC;AAC5E,QAAI,QAAS;AACb,cAAU;AACV,QAAI,OAAO,YAAY,YAAa,SAAQ,WAAW;AAGvD,UAAM,QAAQ,WAAW,MAAM,KAAK,CAAC,GAAG,WAAW;AACnD,IAAC,MAAiC,QAAQ;AAAA,EAC5C;AACA,SAAO;AAAA,IACL,YAAY,CAAC,QAAiB,MAAM,qBAAqB,GAAG;AAAA,IAC5D,aAAa,CAAC,WAAoB,MAAM,sBAAsB,MAAM;AAAA,EACtE;AACF;AAEA,IAAM,QAAQ,gBAAgB,WAAW,OAAO,EAAE,WAAW,MAAM,EAAE;AAG9D,SAAS,uBAAuB,KAAa,OAA8B,CAAC,GAAS;AAC1F,MAAI,MAAM,aAAa,OAAO,YAAY,eAAe,OAAO,QAAQ,OAAO,WAAY;AAC3F,QAAM,YAAY;AAClB,QAAM,IAAI,cAAc,KAAK,IAAI;AACjC,UAAQ,GAAG,qBAAqB,EAAE,UAAU;AAC5C,UAAQ,GAAG,sBAAsB,EAAE,WAAW;AAChD;AAEA,IAAM,eAAe,gBAAgB,YAAY,OAAO,EAAE,WAAW,MAAM,EAAE;AAOtE,SAAS,mBAAmB,KAAmB;AACpD,MAAI,aAAa,aAAa,OAAO,YAAY,eAAe,OAAO,QAAQ,OAAO,WAAY;AAClG,eAAa,YAAY;AACzB,UAAQ,GAAG,WAAW,CAAC,YAAmB;AACxC,QAAI,KAAK,mBAAmB,EAAE,OAAO,mBAAmB,KAAK,QAAQ,CAAC;AAAA,EACxE,CAAC;AACH;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ __export(src_exports, {
|
|
|
30
30
|
installProcessHandlers: () => installProcessHandlers,
|
|
31
31
|
jobData: () => jobData,
|
|
32
32
|
logHttpRequest: () => logHttpRequest,
|
|
33
|
+
logProcessWarnings: () => logProcessWarnings,
|
|
33
34
|
logShutdown: () => logShutdown,
|
|
34
35
|
logStartup: () => logStartup,
|
|
35
36
|
parseTraceparent: () => parseTraceparent,
|
|
@@ -228,6 +229,9 @@ var logged = globalSingleton("logged", () => /* @__PURE__ */ new WeakSet());
|
|
|
228
229
|
function markLogged(err) {
|
|
229
230
|
if (typeof err === "object" && err !== null) logged.add(err);
|
|
230
231
|
}
|
|
232
|
+
function isLogged(err) {
|
|
233
|
+
return typeof err === "object" && err !== null && logged.has(err);
|
|
234
|
+
}
|
|
231
235
|
|
|
232
236
|
// src/normalize.ts
|
|
233
237
|
var HOOK_EXEMPT = /* @__PURE__ */ new Set(["level", "message", "event"]);
|
|
@@ -575,7 +579,7 @@ function jobData(data) {
|
|
|
575
579
|
|
|
576
580
|
// src/console.ts
|
|
577
581
|
var METHODS = { log: "info", info: "info", warn: "warn", error: "error", debug: "debug", trace: "debug" };
|
|
578
|
-
function patchConsole(log) {
|
|
582
|
+
function patchConsole(log, opts = {}) {
|
|
579
583
|
const target = console;
|
|
580
584
|
const saved = {};
|
|
581
585
|
let inside = false;
|
|
@@ -587,6 +591,7 @@ function patchConsole(log) {
|
|
|
587
591
|
if (inside) return previous.apply(console, args);
|
|
588
592
|
inside = true;
|
|
589
593
|
try {
|
|
594
|
+
if (args.some((arg) => isErrorLike(arg) && isLogged(arg)) || opts.skip?.(args)) return;
|
|
590
595
|
let err;
|
|
591
596
|
const parts = [];
|
|
592
597
|
for (const arg of args) {
|
|
@@ -650,6 +655,14 @@ function installProcessHandlers(log, opts = {}) {
|
|
|
650
655
|
process.on("uncaughtException", h.onUncaught);
|
|
651
656
|
process.on("unhandledRejection", h.onRejection);
|
|
652
657
|
}
|
|
658
|
+
var warningState = globalSingleton("warnings", () => ({ installed: false }));
|
|
659
|
+
function logProcessWarnings(log) {
|
|
660
|
+
if (warningState.installed || typeof process === "undefined" || typeof process.on !== "function") return;
|
|
661
|
+
warningState.installed = true;
|
|
662
|
+
process.on("warning", (warning) => {
|
|
663
|
+
log.warn("process warning", { event: "process.warning", err: warning });
|
|
664
|
+
});
|
|
665
|
+
}
|
|
653
666
|
// Annotate the CommonJS export names for ESM import in node:
|
|
654
667
|
0 && (module.exports = {
|
|
655
668
|
DEFAULT_SKIP_PATHS,
|
|
@@ -662,6 +675,7 @@ function installProcessHandlers(log, opts = {}) {
|
|
|
662
675
|
installProcessHandlers,
|
|
663
676
|
jobData,
|
|
664
677
|
logHttpRequest,
|
|
678
|
+
logProcessWarnings,
|
|
665
679
|
logShutdown,
|
|
666
680
|
logStartup,
|
|
667
681
|
parseTraceparent,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/context.ts","../src/global.ts","../src/levels.ts","../src/redact.ts","../src/error.ts","../src/normalize.ts","../src/pretty.ts","../src/logger.ts","../src/request-id.ts","../src/http.ts","../src/fetch.ts","../src/job.ts","../src/console.ts","../src/process.ts"],"sourcesContent":["export { createLogger, type Logger, type LoggerOptions } from \"./logger\";\nexport { LEVELS, type Level } from \"./levels\";\nexport type { Fields, RedactHook } from \"./normalize\";\nexport { REDACT_PATTERNS, type KeyPattern } from \"./redact\";\nexport { serializeError } from \"./error\";\nexport { addContext, getContext, recordError, withContext } from \"./context\";\nexport {\n DEFAULT_SKIP_PATHS,\n logHttpRequest,\n parseTraceparent,\n propagationHeaders,\n requestContextFields,\n resolveRequestId,\n type HttpLogOptions,\n type HttpRequestInfo,\n} from \"./http\";\nexport { createFetch, type FetchLogOptions } from \"./fetch\";\nexport { jobData, runJob, type JobInfo } from \"./job\";\nexport { patchConsole } from \"./console\";\nexport { installProcessHandlers, logShutdown, logStartup, type ProcessHandlerOptions } from \"./process\";\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { globalSingleton } from \"./global\";\nimport type { Fields } from \"./normalize\";\n\nexport interface ContextStore {\n fields: Fields;\n error?: unknown;\n /** Route template captured while the router still knew it (Express error path). */\n route?: string;\n parent?: ContextStore;\n}\n\nconst als = globalSingleton(\"als\", () => new AsyncLocalStorage<ContextStore>());\n\nexport const STORE_KEY: symbol = Symbol.for(\"@tanngo11/log.store\");\n\nexport function runWithStore<T>(fields: Fields, fn: (store: ContextStore) => T): T {\n const parent = als.getStore();\n const store: ContextStore = { fields: { ...parent?.fields, ...fields }, parent };\n return als.run(store, () => fn(store));\n}\n\nexport function withContext<T>(fields: Fields, fn: () => T): T {\n return runWithStore(fields, () => fn());\n}\n\nexport function currentStore(): ContextStore | undefined {\n return als.getStore();\n}\n\nexport function getContext(): Fields {\n return als.getStore()?.fields ?? {};\n}\n\n// Applies to the current context and every enclosing one, so a field added inside a nested\n// withContext/runJob still reaches the request's http.request line.\nexport function addContext(fields: Fields): void {\n for (let s = als.getStore(); s; s = s.parent) Object.assign(s.fields, fields);\n}\n\n// Sets the error on the store and on enclosing stores that have none yet.\nexport function recordErrorIn(store: ContextStore, err: unknown): void {\n store.error = err;\n for (let s = store.parent; s; s = s.parent) if (s.error === undefined) s.error = err;\n}\n\n// Marks the error that the current request/job summary line should carry. Does not write a line.\nexport function recordError(err: unknown): void {\n const store = als.getStore();\n if (store) recordErrorIn(store, err);\n}\n\nexport function attachStore(target: object, store: ContextStore): void {\n (target as Record<symbol, ContextStore>)[STORE_KEY] = store;\n}\n\nexport function storeOf(target: unknown): ContextStore | undefined {\n if (typeof target !== \"object\" || target === null) return undefined;\n return (target as Record<symbol, ContextStore | undefined>)[STORE_KEY];\n}\n","// Singletons shared by every copy of this package loaded in the process (ESM and CJS builds,\n// or duplicated installs), so context and dedupe state never split.\nexport function globalSingleton<T>(name: string, make: () => T): T {\n const key = Symbol.for(`@tanngo11/log.${name}`);\n const g = globalThis as unknown as Record<symbol, T | undefined>;\n let value = g[key];\n if (value === undefined) {\n value = make();\n g[key] = value;\n }\n return value;\n}\n","export const LEVELS = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"] as const;\nexport type Level = (typeof LEVELS)[number];\n\nexport const LEVEL_RANK: Record<Level, number> = {\n trace: 10,\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n fatal: 60,\n};\n\nconst ALIASES: Record<string, Level> = { warning: \"warn\", err: \"error\", critical: \"fatal\", panic: \"fatal\" };\n\nexport function parseLevel(value: unknown, fallback: Level = \"info\"): Level {\n if (typeof value !== \"string\") return fallback;\n const v = value.trim().toLowerCase();\n if ((LEVELS as readonly string[]).includes(v)) return v as Level;\n return ALIASES[v] ?? fallback;\n}\n","// Redaction shared by the logger and the error serializer. The collector redacts again,\n// but it cannot see secrets inside JSON-encoded strings, so the app side must catch them.\n\nexport const DEFAULT_REDACT_KEYS = [\n \"password\", \"passwd\", \"pwd\", \"passphrase\", \"secret\", \"client_secret\",\n \"token\", \"access_token\", \"refresh_token\", \"id_token\", \"auth_token\",\n \"api_key\", \"apikey\", \"access_key\", \"secret_key\", \"private_key\",\n \"authorization\", \"cookie\", \"set_cookie\", \"session_id\", \"sessionid\",\n \"credential\", \"credentials\", \"dsn\", \"connection_string\", \"conn_string\", \"jwt\", \"bearer\",\n];\n\n/** Opt-in value patterns for `redactValues`. Not on by default: they can hit ordinary numbers. */\nexport const REDACT_PATTERNS = {\n /** Vietnamese mobile numbers: 0912345678, +84912345678, 84912345678. */\n phoneVN: /(?<![\\d+])(?:\\+?84|0)[35789]\\d{8}(?!\\d)/g,\n /** Visa, Mastercard, Amex, Discover-like card numbers, with optional spaces or dashes. */\n paymentCard: /(?<!\\d)(?:4\\d{3}|5[1-5]\\d{2}|2[2-7]\\d{2}|3[47]\\d{2}|6(?:011|5\\d{2}))(?:[ -]?\\d{4}){2}[ -]?\\d{1,4}(?!\\d)/g,\n /** IPv4 addresses. */\n ipv4: /(?<![\\d.])(?:\\d{1,3}\\.){3}\\d{1,3}(?![\\d.])/g,\n} as const;\n\n// Keys that only describe a secret (count, type, timestamps, flags) stay readable.\nconst SAFE_SUFFIXES = [\"_count\", \"_type\", \"_length\", \"_expires_at\", \"_expires_in\", \"_ttl\", \"_at\", \"_ms\", \"_enabled\"];\n\nexport const REDACTED = \"[REDACTED]\";\n\nexport function toSnakeCase(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1_$2\")\n .replace(/[^A-Za-z0-9_]+/g, \"_\")\n .toLowerCase();\n}\n\nconst URL_CREDENTIALS_RE = /([a-z][a-z0-9+.-]*:\\/\\/)[^\\s/@:\"']+:[^\\s/@\"']+@/gi;\nconst BEARER_RE = /\\bBearer\\s+[A-Za-z0-9._~+/=-]+/gi;\nconst JWT_RE = /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g;\nconst EMAIL_RE = /[A-Za-z0-9._%+-]+@([A-Za-z0-9-]+(?:\\.[A-Za-z0-9-]+)*\\.[A-Za-z]{2,})/g;\n\nexport type KeyPattern = string | RegExp;\n\nexport interface RedactorOptions {\n /** Extra sensitive keys: names (matched like the defaults) or patterns tested on the snake_case key. */\n keys?: readonly KeyPattern[];\n /** Extra value patterns; every match inside any string becomes [REDACTED]. */\n values?: readonly RegExp[];\n}\n\nexport interface Redactor {\n isSensitive(key: string): boolean;\n /** Masks secrets and emails that appear inside free text. */\n scrub(s: string): string;\n /** JSON.stringify that redacts sensitive keys at any depth and never throws. */\n json(value: unknown): string;\n}\n\nfunction globalize(re: RegExp): RegExp {\n return re.flags.includes(\"g\") ? new RegExp(re.source, re.flags) : new RegExp(re.source, `${re.flags}g`);\n}\n\nexport function createRedactor(opts: RedactorOptions = {}): Redactor {\n const words = [...DEFAULT_REDACT_KEYS];\n const keyPatterns: RegExp[] = [];\n for (const k of opts.keys ?? []) {\n if (typeof k === \"string\") words.push(toSnakeCase(k));\n else keyPatterns.push(new RegExp(k.source, k.flags.replace(\"g\", \"\")));\n }\n const valuePatterns = (opts.values ?? []).map(globalize);\n\n const isSensitive = (key: string): boolean => {\n const k = toSnakeCase(key);\n if (keyPatterns.some((re) => re.test(k))) return true;\n if (!words.includes(k) && SAFE_SUFFIXES.some((s) => k.endsWith(s))) return false;\n return words.some((w) => k === w || k.startsWith(`${w}_`) || k.endsWith(`_${w}`) || k.includes(`_${w}_`));\n };\n\n const scrub = (s: string): string => {\n let out = s\n .replace(URL_CREDENTIALS_RE, `$1${REDACTED}@`)\n .replace(BEARER_RE, `Bearer ${REDACTED}`)\n .replace(JWT_RE, \"[REDACTED_JWT]\")\n .replace(EMAIL_RE, \"***@$1\");\n for (const re of valuePatterns) out = out.replace(re, REDACTED);\n return out;\n };\n\n const json = (value: unknown): string => {\n if (typeof value === \"string\") return value;\n try {\n const text = JSON.stringify(value, (key, val: unknown) => {\n if (key && val !== null && val !== undefined && isSensitive(key)) return REDACTED;\n if (typeof val === \"bigint\") return val.toString();\n if (val instanceof Error) return { name: val.name, message: val.message };\n return val;\n });\n return text ?? String(value);\n } catch {\n return String(value);\n }\n };\n\n return { isSensitive, scrub, json };\n}\n\nexport const defaultRedactor: Redactor = createRedactor();\n","import { globalSingleton } from \"./global\";\nimport { defaultRedactor } from \"./redact\";\n\nexport interface ErrFields {\n err_type?: string;\n err_message?: string;\n err_code?: string;\n err_stack?: string;\n err_cause?: string;\n}\n\nconst MAX_CAUSE_DEPTH = 5;\n\nexport function isErrorLike(v: unknown): v is Error {\n if (v instanceof Error) return true;\n return (\n typeof v === \"object\" &&\n v !== null &&\n typeof (v as { message?: unknown }).message === \"string\" &&\n (\"stack\" in v || \"name\" in v)\n );\n}\n\nfunction errorType(e: Error): string {\n if (e.name && e.name !== \"Error\") return e.name;\n const ctor = (e as { constructor?: { name?: string } }).constructor?.name;\n return ctor && ctor !== \"Object\" ? ctor : \"Error\";\n}\n\nexport function serializeError(err: unknown): ErrFields {\n if (!isErrorLike(err)) {\n if (typeof err === \"string\") return { err_type: \"string\", err_message: err };\n return { err_type: typeof err, err_message: defaultRedactor.json(err) };\n }\n const e = err as Error & { code?: unknown; cause?: unknown };\n const out: ErrFields = { err_type: errorType(e), err_message: String(e.message ?? \"\") };\n if (e.code !== undefined && e.code !== null) out.err_code = String(e.code);\n if (typeof e.stack === \"string\") out.err_stack = e.stack;\n\n const causes: string[] = [];\n let cause = e.cause;\n while (cause !== undefined && cause !== null && causes.length < MAX_CAUSE_DEPTH) {\n if (isErrorLike(cause)) {\n causes.push(`${errorType(cause)}: ${cause.message}`);\n cause = (cause as { cause?: unknown }).cause;\n } else {\n causes.push(defaultRedactor.json(cause));\n cause = undefined;\n }\n }\n if (causes.length > 0) out.err_cause = causes.join(\" <- \");\n return out;\n}\n\nconst logged = globalSingleton(\"logged\", () => new WeakSet<object>());\n\n// Marks an error as already written, so a later boundary (e.g. Next's onRequestError)\n// does not log it a second time.\nexport function markLogged(err: unknown): void {\n if (typeof err === \"object\" && err !== null) logged.add(err);\n}\n\nexport function isLogged(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && logged.has(err);\n}\n","import { isErrorLike, serializeError } from \"./error\";\nimport type { Level } from \"./levels\";\nimport { REDACTED, toSnakeCase, type Redactor } from \"./redact\";\n\nexport { DEFAULT_REDACT_KEYS, toSnakeCase } from \"./redact\";\n\n/** Final per-field hook: return a replacement, or undefined to drop the field. */\nexport type RedactHook = (key: string, value: Primitive) => unknown;\n\nexport type Fields = Record<string, unknown>;\nexport type Primitive = string | number | boolean | null;\nexport type LogRecord = Record<string, Primitive>;\n\nexport interface NormalizeOptions {\n snakeCase: boolean;\n redactor: Redactor;\n hook?: RedactHook;\n}\n\n// Fields the redact hook never sees, so every line keeps its level, message and event.\nconst HOOK_EXEMPT = new Set([\"level\", \"message\", \"event\"]);\n\n// Keys owned by Vector (overwritten or deleted on ingest) or by the logger itself.\nexport const RESERVED_KEYS = new Set([\n \"project\", \"service\", \"vps\", \"version\", \"container_name\", \"container_id\", \"image\", \"stream\",\n \"_timestamp\", \"label\", \"host\", \"source_type\", \"msg\", \"lvl\", \"severity\", \"level\", \"message\",\n]);\n\nexport const MAX_LINE_BYTES = 16000;\nconst MAX_MESSAGE = 500;\nconst MAX_STACK = 4000;\nconst MAX_STRING = 1000;\nconst MAX_DEPTH = 3;\nconst TRUNCATED = \"…[truncated]\";\n\n// Fields kept when a line is too large.\nconst KEEP_ON_SHRINK = new Set([\n \"level\", \"message\", \"event\", \"request_id\", \"trace_id\", \"span_id\", \"job_name\", \"job_id\", \"job_attempt\",\n \"user_id\", \"tenant_id\", \"err_type\", \"err_message\", \"err_code\",\n]);\n\nexport function stripUrl(url: string): string {\n const noQuery = url.split(/[?#]/, 1)[0] ?? \"\";\n return noQuery.replace(/^([a-z][a-z0-9+.-]*:\\/\\/)[^/@\\s]*@/i, \"$1\");\n}\n\nexport function truncate(s: string, max: number): string {\n return s.length > max ? s.slice(0, max - TRUNCATED.length) + TRUNCATED : s;\n}\n\nfunction isPlainObject(v: unknown): v is Fields {\n if (typeof v !== \"object\" || v === null) return false;\n const proto = Object.getPrototypeOf(v);\n return proto === Object.prototype || proto === null;\n}\n\nfunction isUrlKey(key: string): boolean {\n return key === \"http_path\" || key === \"http_url\" || key.endsWith(\"_url\");\n}\n\nfunction flattenInto(out: LogRecord, prefix: string, obj: Fields, depth: number, opts: NormalizeOptions): void {\n for (const [rawKey, value] of Object.entries(obj)) {\n const key = opts.snakeCase ? toSnakeCase(rawKey) : rawKey;\n const full = prefix ? `${prefix}_${key}` : key;\n if (value === undefined || typeof value === \"function\" || typeof value === \"symbol\") continue;\n if (value !== null && (opts.redactor.isSensitive(rawKey) || opts.redactor.isSensitive(full))) {\n out[full] = REDACTED;\n continue;\n }\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") {\n out[full] = value;\n } else if (typeof value === \"number\") {\n out[full] = Number.isFinite(value) ? value : String(value);\n } else if (typeof value === \"bigint\") {\n out[full] = value.toString();\n } else if (value instanceof Date) {\n out[full] = Number.isNaN(value.getTime()) ? \"Invalid Date\" : value.toISOString();\n } else if (isErrorLike(value)) {\n out[full] = `${value.name}: ${value.message}`;\n } else if (isPlainObject(value) && depth < MAX_DEPTH - 1) {\n flattenInto(out, full, value, depth + 1, opts);\n } else {\n // Arrays, deep objects, class instances: stringified with sensitive keys redacted.\n out[full] = opts.redactor.json(value);\n }\n }\n}\n\nfunction finalize(key: string, value: Primitive, opts: NormalizeOptions): Primitive {\n if (typeof value !== \"string\") return value;\n const v = opts.redactor.scrub(isUrlKey(key) ? stripUrl(value) : value);\n return truncate(v, key === \"err_stack\" ? MAX_STACK : MAX_STRING);\n}\n\nexport function buildRecord(\n level: Level,\n message: unknown,\n sources: (Fields | undefined)[],\n opts: NormalizeOptions,\n): LogRecord {\n const merged: Fields = {};\n for (const source of sources) if (source) Object.assign(merged, source);\n\n let err: unknown;\n if (merged.err !== undefined && merged.err !== null) {\n err = merged.err;\n delete merged.err;\n } else if (isErrorLike(merged.error)) {\n err = merged.error;\n delete merged.error;\n }\n\n const flat: LogRecord = {};\n flattenInto(flat, \"\", merged, 0, opts);\n if (err !== undefined) Object.assign(flat, serializeError(err));\n\n const text = typeof message === \"string\" ? message : opts.redactor.json(message);\n const out: LogRecord = { level, message: truncate(opts.redactor.scrub(text), MAX_MESSAGE) };\n for (const [k, v] of Object.entries(flat)) {\n const key = RESERVED_KEYS.has(k) ? `app_${k}` : k;\n let value = finalize(key, v, opts);\n if (opts.hook && !HOOK_EXEMPT.has(key)) {\n const replaced = opts.hook(key, value);\n if (replaced === undefined) continue;\n value = typeof replaced === \"object\" && replaced !== null ? opts.redactor.json(replaced) : (replaced as Primitive);\n }\n out[key] = value;\n }\n return out;\n}\n\nfunction byteLength(s: string): number {\n // UTF-8 uses at most 3 bytes per UTF-16 code unit: skip encoding short lines.\n if (s.length * 3 <= MAX_LINE_BYTES) return s.length;\n return new TextEncoder().encode(s).length;\n}\n\nexport function serializeRecord(record: LogRecord): string {\n const line = JSON.stringify(record);\n if (byteLength(line) <= MAX_LINE_BYTES) return line;\n const small: LogRecord = {};\n for (const [k, v] of Object.entries(record)) {\n if (KEEP_ON_SHRINK.has(k) || k.startsWith(\"http_\")) small[k] = v;\n }\n small.log_truncated = true;\n return JSON.stringify(small);\n}\n","import type { LogRecord } from \"./normalize\";\n\n// Human-readable line for local development only (LOG_FORMAT=pretty).\nexport function formatPretty(record: LogRecord): string {\n const { level, message, err_stack, ...rest } = record;\n const time = new Date().toISOString().slice(11, 23);\n const extras = Object.entries(rest)\n .map(([k, v]) => `${k}=${typeof v === \"string\" && /\\s/.test(v) ? JSON.stringify(v) : String(v)}`)\n .join(\" \");\n let line = `${time} ${String(level).toUpperCase().padEnd(5)} ${String(message)}${extras ? ` ${extras}` : \"\"}`;\n if (typeof err_stack === \"string\") line += `\\n${err_stack}`;\n return line;\n}\n","import { getContext } from \"./context\";\nimport { LEVEL_RANK, parseLevel, type Level } from \"./levels\";\nimport {\n buildRecord,\n serializeRecord,\n type Fields,\n type NormalizeOptions,\n type RedactHook,\n} from \"./normalize\";\nimport { formatPretty } from \"./pretty\";\nimport { createRedactor, type KeyPattern } from \"./redact\";\n\ntype LogMethod = (message: string, fields?: Fields) => void;\n\nexport interface Logger {\n readonly level: Level;\n trace: LogMethod;\n debug: LogMethod;\n info: LogMethod;\n warn: LogMethod;\n error: LogMethod;\n fatal: LogMethod;\n child(fields: Fields): Logger;\n isLevelEnabled(level: Level): boolean;\n}\n\nexport interface LoggerOptions {\n level?: Level | string;\n format?: \"json\" | \"pretty\";\n base?: Fields;\n /** Extra sensitive keys: names (matched like the defaults) or RegExp tested on the snake_case key. */\n redactKeys?: KeyPattern[];\n /** Extra value patterns masked in every string, e.g. REDACT_PATTERNS.phoneVN. */\n redactValues?: RegExp[];\n /** Final per-field hook: return a replacement, or undefined to drop the field. */\n redact?: RedactHook;\n snakeCase?: boolean;\n write?: (line: string) => void;\n}\n\nfunction env(name: string): string | undefined {\n return typeof process !== \"undefined\" ? process.env?.[name] : undefined;\n}\n\n// Captured before patchConsole can replace it, so the fallback never loops into the logger.\nconst consoleLog = console.log.bind(console);\n\nfunction defaultWrite(line: string): void {\n if (typeof process !== \"undefined\" && typeof process.stdout?.write === \"function\") {\n process.stdout.write(`${line}\\n`);\n } else {\n consoleLog(line);\n }\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const level = parseLevel(options.level ?? env(\"LOG_LEVEL\"));\n const format = options.format ?? (env(\"LOG_FORMAT\") === \"pretty\" ? \"pretty\" : \"json\");\n const write = options.write ?? defaultWrite;\n const norm: NormalizeOptions = {\n snakeCase: options.snakeCase ?? true,\n redactor: createRedactor({ keys: options.redactKeys, values: options.redactValues }),\n hook: options.redact,\n };\n\n const make = (bound: Fields): Logger => {\n const emit = (lvl: Level, message: string, fields?: Fields) => {\n if (LEVEL_RANK[lvl] < LEVEL_RANK[level]) return;\n let line: string;\n try {\n const record = buildRecord(lvl, message, [options.base, getContext(), bound, fields], norm);\n line = format === \"pretty\" ? formatPretty(record) : serializeRecord(record);\n } catch (e) {\n line = JSON.stringify({\n level: \"error\",\n message: \"log serialize failed\",\n event: \"log.serialize_failed\",\n err_message: String((e as Error)?.message ?? e).slice(0, 1000),\n original_message: String(message).slice(0, 500),\n });\n }\n try {\n write(line);\n } catch {\n // Logging must never break the app.\n }\n };\n return {\n level,\n trace: (m, f) => emit(\"trace\", m, f),\n debug: (m, f) => emit(\"debug\", m, f),\n info: (m, f) => emit(\"info\", m, f),\n warn: (m, f) => emit(\"warn\", m, f),\n error: (m, f) => emit(\"error\", m, f),\n fatal: (m, f) => emit(\"fatal\", m, f),\n child: (fields) => make({ ...bound, ...fields }),\n isLevelEnabled: (l) => LEVEL_RANK[l] >= LEVEL_RANK[level],\n };\n };\n return make({});\n}\n","// No imports: this module is shared with the edge entry (next-edge).\nexport const REQUEST_ID_RE = /^[A-Za-z0-9._-]{1,64}$/;\nconst TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;\n\nexport function newRequestId(): string {\n return globalThis.crypto.randomUUID();\n}\n\nfunction first(header?: string | string[] | null): string | undefined {\n return Array.isArray(header) ? header[0] : (header ?? undefined);\n}\n\nexport function resolveRequestId(header?: string | string[] | null): string {\n const value = first(header);\n return value && REQUEST_ID_RE.test(value) ? value : newRequestId();\n}\n\nexport function parseTraceparent(header?: string | string[] | null): { trace_id: string; span_id: string } | undefined {\n const value = first(header)?.trim().toLowerCase();\n const m = value ? TRACEPARENT_RE.exec(value) : null;\n if (!m) return undefined;\n const [, version, traceId, spanId] = m as unknown as [string, string, string, string];\n if (version === \"ff\" || /^0+$/.test(traceId) || /^0+$/.test(spanId)) return undefined;\n return { trace_id: traceId, span_id: spanId };\n}\n","import { getContext } from \"./context\";\nimport { markLogged, serializeError } from \"./error\";\nimport type { Logger } from \"./logger\";\nimport { stripUrl, type Fields } from \"./normalize\";\nimport { parseTraceparent, resolveRequestId } from \"./request-id\";\n\nexport { newRequestId, parseTraceparent, REQUEST_ID_RE, resolveRequestId } from \"./request-id\";\n\nexport type HeaderSource = Headers | Record<string, string | string[] | undefined>;\n\nfunction header(headers: HeaderSource, name: string): string | string[] | undefined {\n if (typeof (headers as Headers).get === \"function\") return (headers as Headers).get(name) ?? undefined;\n return (headers as Record<string, string | string[] | undefined>)[name];\n}\n\nexport function requestContextFields(headers: HeaderSource): { request_id: string; trace_id?: string; span_id?: string } {\n const out: { request_id: string; trace_id?: string; span_id?: string } = {\n request_id: resolveRequestId(header(headers, \"x-request-id\")),\n };\n const tp = parseTraceparent(header(headers, \"traceparent\"));\n if (tp) Object.assign(out, tp);\n return out;\n}\n\n// Headers to forward to services we own, so their logs share request_id / trace_id.\nexport function propagationHeaders(): Record<string, string> {\n const ctx = getContext();\n const out: Record<string, string> = {};\n if (typeof ctx.request_id === \"string\") out[\"x-request-id\"] = ctx.request_id;\n if (typeof ctx.trace_id === \"string\" && typeof ctx.span_id === \"string\") {\n out.traceparent = `00-${ctx.trace_id}-${ctx.span_id}-01`;\n }\n return out;\n}\n\nexport const DEFAULT_SKIP_PATHS: (string | RegExp)[] = [\n /^\\/(health|healthz|ready|readyz|livez)\\/?$/,\n \"/favicon.ico\",\n /^\\/_next\\/static\\//,\n];\n\nexport interface HttpLogOptions {\n skipPaths?: (string | RegExp)[];\n}\n\nexport interface HttpRequestInfo {\n method: string;\n route?: string;\n path: string;\n status: number;\n duration_ms?: number;\n err?: unknown;\n fields?: Fields;\n}\n\nexport function shouldSkip(method: string, path: string, skipPaths: (string | RegExp)[] = DEFAULT_SKIP_PATHS): boolean {\n if (method.toUpperCase() === \"OPTIONS\") return true;\n const p = stripUrl(path);\n return skipPaths.some((s) => (typeof s === \"string\" ? p === s : s.test(p)));\n}\n\n// Writes the one `http.request` summary line for an inbound request.\nexport function logHttpRequest(log: Logger, info: HttpRequestInfo, opts: HttpLogOptions = {}): void {\n if (shouldSkip(info.method, info.path, opts.skipPaths)) return;\n const level = info.status >= 500 ? \"error\" : info.status >= 400 ? \"warn\" : \"info\";\n const path = stripUrl(info.path);\n const errFields: Fields = {};\n if (info.err !== undefined && info.err !== null) {\n Object.assign(errFields, serializeError(info.err));\n if (info.status < 500) delete errFields.err_stack;\n markLogged(info.err);\n }\n // Route templates keep the message bounded; the raw path would make one message per URL.\n const message = info.route ? `${info.method} ${info.route} ${info.status}` : `${info.method} ${info.status}`;\n log[level](message, {\n ...info.fields,\n event: \"http.request\",\n http_method: info.method,\n http_route: info.route,\n http_path: path,\n http_status: info.status,\n duration_ms: info.duration_ms === undefined ? undefined : Math.round(info.duration_ms),\n ...errFields,\n });\n}\n","import { propagationHeaders } from \"./http\";\nimport type { Logger } from \"./logger\";\n\nexport interface FetchLogOptions {\n peer_service: string;\n /** Forward x-request-id / traceparent. Only for services we own. */\n internal?: boolean;\n slowMs?: number;\n fetch?: typeof fetch;\n}\n\nfunction describeRequest(input: RequestInfo | URL, init?: RequestInit): { method: string; url: string } {\n const method = (init?.method ?? (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n return { method, url };\n}\n\nexport function createFetch(log: Logger, opts: FetchLogOptions): typeof fetch {\n const slowMs = opts.slowMs ?? 1000;\n const wrapped = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const base = opts.fetch ?? globalThis.fetch;\n const { method, url } = describeRequest(input, init);\n let requestInit = init;\n if (opts.internal) {\n const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined));\n for (const [k, v] of Object.entries(propagationHeaders())) if (!headers.has(k)) headers.set(k, v);\n requestInit = { ...init, headers };\n }\n const fields = { event: \"http.outbound\", peer_service: opts.peer_service, http_method: method, http_url: url };\n const start = performance.now();\n try {\n const res = await base(input, requestInit);\n const duration_ms = Math.round(performance.now() - start);\n if (res.status >= 500) {\n log.warn(\"outbound request failed\", { ...fields, http_status: res.status, duration_ms });\n } else if (duration_ms >= slowMs) {\n log.warn(\"outbound request slow\", { ...fields, http_status: res.status, duration_ms });\n }\n return res;\n } catch (err) {\n log.warn(\"outbound request failed\", { ...fields, duration_ms: Math.round(performance.now() - start), err });\n throw err;\n }\n };\n return wrapped as typeof fetch;\n}\n","import { getContext, withContext } from \"./context\";\nimport { markLogged } from \"./error\";\nimport type { Logger } from \"./logger\";\nimport type { Fields } from \"./normalize\";\n\nexport interface JobInfo {\n job_name: string;\n job_id?: string | number;\n job_attempt?: number;\n /** No retries left after this attempt (or decided per error). Defaults to true when unknown. */\n final_attempt?: boolean | ((err: unknown) => boolean);\n request_id?: string;\n fields?: Fields;\n}\n\nexport async function runJob<T>(log: Logger, info: JobInfo, fn: () => T | Promise<T>): Promise<T> {\n const ctx: Fields = { ...info.fields, job_name: info.job_name };\n if (info.job_id !== undefined) ctx.job_id = String(info.job_id);\n if (info.job_attempt !== undefined) ctx.job_attempt = info.job_attempt;\n if (info.request_id !== undefined) ctx.request_id = info.request_id;\n\n return withContext(ctx, async () => {\n const start = performance.now();\n try {\n const result = await fn();\n log.info(\"job completed\", { event: \"job.completed\", duration_ms: Math.round(performance.now() - start) });\n return result;\n } catch (err) {\n const final = typeof info.final_attempt === \"function\" ? info.final_attempt(err) : (info.final_attempt ?? true);\n log[final ? \"error\" : \"warn\"](\"job failed\", {\n event: \"job.failed\",\n duration_ms: Math.round(performance.now() - start),\n err,\n });\n markLogged(err);\n throw err;\n }\n });\n}\n\n/** Adds the current request_id to a job payload, so the job's logs link back to the request. */\nexport function jobData<T extends Record<string, unknown>>(data: T): T & { request_id?: string } {\n const requestId = getContext().request_id;\n if (typeof requestId !== \"string\" || data.request_id !== undefined) return data;\n return { ...data, request_id: requestId };\n}\n","import { isErrorLike } from \"./error\";\nimport type { Level } from \"./levels\";\nimport type { Logger } from \"./logger\";\nimport { defaultRedactor } from \"./redact\";\n\nconst METHODS = { log: \"info\", info: \"info\", warn: \"warn\", error: \"error\", debug: \"debug\", trace: \"debug\" } as const;\ntype Method = keyof typeof METHODS;\ntype ConsoleFn = (...args: unknown[]) => void;\n\n/**\n * Routes console.log/info/warn/error/debug/trace through the logger, so legacy console calls\n * and framework output (e.g. Next.js errors) become JSON lines with request context.\n * Returns a function that restores the previous console methods.\n */\nexport function patchConsole(log: Logger): () => void {\n const target = console as unknown as Record<Method, ConsoleFn>;\n const saved = {} as Record<Method, ConsoleFn>;\n let inside = false;\n\n for (const method of Object.keys(METHODS) as Method[]) {\n const previous = target[method];\n saved[method] = previous;\n const level: Level = METHODS[method];\n target[method] = (...args: unknown[]) => {\n // A write path that itself uses console must not loop back into the logger.\n if (inside) return previous.apply(console, args);\n inside = true;\n try {\n let err: unknown;\n const parts: string[] = [];\n for (const arg of args) {\n if (isErrorLike(arg)) {\n err ??= arg;\n parts.push(arg.message);\n } else {\n parts.push(typeof arg === \"string\" ? arg : defaultRedactor.json(arg));\n }\n }\n log[level](parts.join(\" \"), { event: \"console\", console_method: method, err });\n } finally {\n inside = false;\n }\n };\n }\n\n return () => {\n for (const method of Object.keys(saved) as Method[]) target[method] = saved[method];\n };\n}\n","import { globalSingleton } from \"./global\";\nimport type { Logger } from \"./logger\";\nimport type { Fields } from \"./normalize\";\n\nexport function logStartup(log: Logger, fields: Fields = {}): void {\n log.info(\"app started\", {\n event: \"app.started\",\n runtime_version: `node ${process.versions.node}`,\n log_level: log.level,\n ...fields,\n });\n}\n\n/** Call at the start of your own shutdown handler (e.g. on SIGTERM). The library never handles signals. */\nexport function logShutdown(log: Logger, fields: Fields = {}): void {\n log.info(\"app stopping\", { event: \"app.stopping\", ...fields });\n}\n\nexport interface ProcessHandlerOptions {\n /** Exit with code 1 after an uncaught error. Next.js keeps serving, so its adapter passes false. */\n exitOnCrash?: boolean;\n /** Time other crash handlers (Sentry, APM) get to flush before exit. Default 1000 ms. */\n exitDelayMs?: number;\n exit?: (code: number) => void;\n}\n\nexport function crashHandlers(log: Logger, opts: ProcessHandlerOptions = {}) {\n const exitOnCrash = opts.exitOnCrash ?? true;\n const exitDelayMs = opts.exitDelayMs ?? 1000;\n const exit = opts.exit ?? ((code: number) => process.exit(code));\n let exiting = false;\n const crash = (source: string, err: unknown) => {\n if (!exitOnCrash) {\n log.error(\"unhandled error\", { event: \"app.unhandled_error\", crash_source: source, err });\n return;\n }\n log.fatal(\"app crashed\", { event: \"app.crashed\", crash_source: source, err });\n if (exiting) return;\n exiting = true;\n if (typeof process !== \"undefined\") process.exitCode = 1;\n // Deferred so listeners registered after ours still run; unref so a process with nothing\n // left to do exits on its own (with exitCode 1) without waiting.\n const timer = setTimeout(() => exit(1), exitDelayMs);\n (timer as { unref?: () => void }).unref?.();\n };\n return {\n onUncaught: (err: unknown) => crash(\"uncaughtException\", err),\n onRejection: (reason: unknown) => crash(\"unhandledRejection\", reason),\n };\n}\n\nconst state = globalSingleton(\"process\", () => ({ installed: false }));\n\n/** Logs uncaught exceptions and unhandled rejections. Does not touch SIGTERM/SIGINT. */\nexport function installProcessHandlers(log: Logger, opts: ProcessHandlerOptions = {}): void {\n if (state.installed || typeof process === \"undefined\" || typeof process.on !== \"function\") return;\n state.installed = true;\n const h = crashHandlers(log, opts);\n process.on(\"uncaughtException\", h.onUncaught);\n process.on(\"unhandledRejection\", h.onRejection);\n}\n"],"mappings":"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","names":["header"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/context.ts","../src/global.ts","../src/levels.ts","../src/redact.ts","../src/error.ts","../src/normalize.ts","../src/pretty.ts","../src/logger.ts","../src/request-id.ts","../src/http.ts","../src/fetch.ts","../src/job.ts","../src/console.ts","../src/process.ts"],"sourcesContent":["export { createLogger, type Logger, type LoggerOptions } from \"./logger\";\nexport { LEVELS, type Level } from \"./levels\";\nexport type { Fields, RedactHook } from \"./normalize\";\nexport { REDACT_PATTERNS, type KeyPattern } from \"./redact\";\nexport { serializeError } from \"./error\";\nexport { addContext, getContext, recordError, withContext } from \"./context\";\nexport {\n DEFAULT_SKIP_PATHS,\n logHttpRequest,\n parseTraceparent,\n propagationHeaders,\n requestContextFields,\n resolveRequestId,\n type HttpLogOptions,\n type HttpRequestInfo,\n} from \"./http\";\nexport { createFetch, type FetchLogOptions } from \"./fetch\";\nexport { jobData, runJob, type JobInfo } from \"./job\";\nexport { patchConsole, type PatchConsoleOptions } from \"./console\";\nexport { installProcessHandlers, logProcessWarnings, logShutdown, logStartup, type ProcessHandlerOptions } from \"./process\";\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { globalSingleton } from \"./global\";\nimport type { Fields } from \"./normalize\";\n\nexport interface ContextStore {\n fields: Fields;\n error?: unknown;\n /** Route template captured while the router still knew it (Express error path). */\n route?: string;\n parent?: ContextStore;\n}\n\nconst als = globalSingleton(\"als\", () => new AsyncLocalStorage<ContextStore>());\n\nexport const STORE_KEY: symbol = Symbol.for(\"@tanngo11/log.store\");\n\nexport function runWithStore<T>(fields: Fields, fn: (store: ContextStore) => T): T {\n const parent = als.getStore();\n const store: ContextStore = { fields: { ...parent?.fields, ...fields }, parent };\n return als.run(store, () => fn(store));\n}\n\nexport function withContext<T>(fields: Fields, fn: () => T): T {\n return runWithStore(fields, () => fn());\n}\n\nexport function currentStore(): ContextStore | undefined {\n return als.getStore();\n}\n\nexport function getContext(): Fields {\n return als.getStore()?.fields ?? {};\n}\n\n// Applies to the current context and every enclosing one, so a field added inside a nested\n// withContext/runJob still reaches the request's http.request line.\nexport function addContext(fields: Fields): void {\n for (let s = als.getStore(); s; s = s.parent) Object.assign(s.fields, fields);\n}\n\n// Sets the error on the store and on enclosing stores that have none yet.\nexport function recordErrorIn(store: ContextStore, err: unknown): void {\n store.error = err;\n for (let s = store.parent; s; s = s.parent) if (s.error === undefined) s.error = err;\n}\n\n// Marks the error that the current request/job summary line should carry. Does not write a line.\nexport function recordError(err: unknown): void {\n const store = als.getStore();\n if (store) recordErrorIn(store, err);\n}\n\nexport function attachStore(target: object, store: ContextStore): void {\n (target as Record<symbol, ContextStore>)[STORE_KEY] = store;\n}\n\nexport function storeOf(target: unknown): ContextStore | undefined {\n if (typeof target !== \"object\" || target === null) return undefined;\n return (target as Record<symbol, ContextStore | undefined>)[STORE_KEY];\n}\n","// Singletons shared by every copy of this package loaded in the process (ESM and CJS builds,\n// or duplicated installs), so context and dedupe state never split.\nexport function globalSingleton<T>(name: string, make: () => T): T {\n const key = Symbol.for(`@tanngo11/log.${name}`);\n const g = globalThis as unknown as Record<symbol, T | undefined>;\n let value = g[key];\n if (value === undefined) {\n value = make();\n g[key] = value;\n }\n return value;\n}\n","export const LEVELS = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"] as const;\nexport type Level = (typeof LEVELS)[number];\n\nexport const LEVEL_RANK: Record<Level, number> = {\n trace: 10,\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n fatal: 60,\n};\n\nconst ALIASES: Record<string, Level> = { warning: \"warn\", err: \"error\", critical: \"fatal\", panic: \"fatal\" };\n\nexport function parseLevel(value: unknown, fallback: Level = \"info\"): Level {\n if (typeof value !== \"string\") return fallback;\n const v = value.trim().toLowerCase();\n if ((LEVELS as readonly string[]).includes(v)) return v as Level;\n return ALIASES[v] ?? fallback;\n}\n","// Redaction shared by the logger and the error serializer. The collector redacts again,\n// but it cannot see secrets inside JSON-encoded strings, so the app side must catch them.\n\nexport const DEFAULT_REDACT_KEYS = [\n \"password\", \"passwd\", \"pwd\", \"passphrase\", \"secret\", \"client_secret\",\n \"token\", \"access_token\", \"refresh_token\", \"id_token\", \"auth_token\",\n \"api_key\", \"apikey\", \"access_key\", \"secret_key\", \"private_key\",\n \"authorization\", \"cookie\", \"set_cookie\", \"session_id\", \"sessionid\",\n \"credential\", \"credentials\", \"dsn\", \"connection_string\", \"conn_string\", \"jwt\", \"bearer\",\n];\n\n/** Opt-in value patterns for `redactValues`. Not on by default: they can hit ordinary numbers. */\nexport const REDACT_PATTERNS = {\n /** Vietnamese mobile numbers: 0912345678, +84912345678, 84912345678. */\n phoneVN: /(?<![\\d+])(?:\\+?84|0)[35789]\\d{8}(?!\\d)/g,\n /** Visa, Mastercard, Amex, Discover-like card numbers, with optional spaces or dashes. */\n paymentCard: /(?<!\\d)(?:4\\d{3}|5[1-5]\\d{2}|2[2-7]\\d{2}|3[47]\\d{2}|6(?:011|5\\d{2}))(?:[ -]?\\d{4}){2}[ -]?\\d{1,4}(?!\\d)/g,\n /** IPv4 addresses. */\n ipv4: /(?<![\\d.])(?:\\d{1,3}\\.){3}\\d{1,3}(?![\\d.])/g,\n} as const;\n\n// Keys that only describe a secret (count, type, timestamps, flags) stay readable.\nconst SAFE_SUFFIXES = [\"_count\", \"_type\", \"_length\", \"_expires_at\", \"_expires_in\", \"_ttl\", \"_at\", \"_ms\", \"_enabled\"];\n\nexport const REDACTED = \"[REDACTED]\";\n\nexport function toSnakeCase(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1_$2\")\n .replace(/[^A-Za-z0-9_]+/g, \"_\")\n .toLowerCase();\n}\n\nconst URL_CREDENTIALS_RE = /([a-z][a-z0-9+.-]*:\\/\\/)[^\\s/@:\"']+:[^\\s/@\"']+@/gi;\nconst BEARER_RE = /\\bBearer\\s+[A-Za-z0-9._~+/=-]+/gi;\nconst JWT_RE = /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g;\nconst EMAIL_RE = /[A-Za-z0-9._%+-]+@([A-Za-z0-9-]+(?:\\.[A-Za-z0-9-]+)*\\.[A-Za-z]{2,})/g;\n\nexport type KeyPattern = string | RegExp;\n\nexport interface RedactorOptions {\n /** Extra sensitive keys: names (matched like the defaults) or patterns tested on the snake_case key. */\n keys?: readonly KeyPattern[];\n /** Extra value patterns; every match inside any string becomes [REDACTED]. */\n values?: readonly RegExp[];\n}\n\nexport interface Redactor {\n isSensitive(key: string): boolean;\n /** Masks secrets and emails that appear inside free text. */\n scrub(s: string): string;\n /** JSON.stringify that redacts sensitive keys at any depth and never throws. */\n json(value: unknown): string;\n}\n\nfunction globalize(re: RegExp): RegExp {\n return re.flags.includes(\"g\") ? new RegExp(re.source, re.flags) : new RegExp(re.source, `${re.flags}g`);\n}\n\nexport function createRedactor(opts: RedactorOptions = {}): Redactor {\n const words = [...DEFAULT_REDACT_KEYS];\n const keyPatterns: RegExp[] = [];\n for (const k of opts.keys ?? []) {\n if (typeof k === \"string\") words.push(toSnakeCase(k));\n else keyPatterns.push(new RegExp(k.source, k.flags.replace(\"g\", \"\")));\n }\n const valuePatterns = (opts.values ?? []).map(globalize);\n\n const isSensitive = (key: string): boolean => {\n const k = toSnakeCase(key);\n if (keyPatterns.some((re) => re.test(k))) return true;\n if (!words.includes(k) && SAFE_SUFFIXES.some((s) => k.endsWith(s))) return false;\n return words.some((w) => k === w || k.startsWith(`${w}_`) || k.endsWith(`_${w}`) || k.includes(`_${w}_`));\n };\n\n const scrub = (s: string): string => {\n let out = s\n .replace(URL_CREDENTIALS_RE, `$1${REDACTED}@`)\n .replace(BEARER_RE, `Bearer ${REDACTED}`)\n .replace(JWT_RE, \"[REDACTED_JWT]\")\n .replace(EMAIL_RE, \"***@$1\");\n for (const re of valuePatterns) out = out.replace(re, REDACTED);\n return out;\n };\n\n const json = (value: unknown): string => {\n if (typeof value === \"string\") return value;\n try {\n const text = JSON.stringify(value, (key, val: unknown) => {\n if (key && val !== null && val !== undefined && isSensitive(key)) return REDACTED;\n if (typeof val === \"bigint\") return val.toString();\n if (val instanceof Error) return { name: val.name, message: val.message };\n return val;\n });\n return text ?? String(value);\n } catch {\n return String(value);\n }\n };\n\n return { isSensitive, scrub, json };\n}\n\nexport const defaultRedactor: Redactor = createRedactor();\n","import { globalSingleton } from \"./global\";\nimport { defaultRedactor } from \"./redact\";\n\nexport interface ErrFields {\n err_type?: string;\n err_message?: string;\n err_code?: string;\n err_stack?: string;\n err_cause?: string;\n}\n\nconst MAX_CAUSE_DEPTH = 5;\n\nexport function isErrorLike(v: unknown): v is Error {\n if (v instanceof Error) return true;\n return (\n typeof v === \"object\" &&\n v !== null &&\n typeof (v as { message?: unknown }).message === \"string\" &&\n (\"stack\" in v || \"name\" in v)\n );\n}\n\nfunction errorType(e: Error): string {\n if (e.name && e.name !== \"Error\") return e.name;\n const ctor = (e as { constructor?: { name?: string } }).constructor?.name;\n return ctor && ctor !== \"Object\" ? ctor : \"Error\";\n}\n\nexport function serializeError(err: unknown): ErrFields {\n if (!isErrorLike(err)) {\n if (typeof err === \"string\") return { err_type: \"string\", err_message: err };\n return { err_type: typeof err, err_message: defaultRedactor.json(err) };\n }\n const e = err as Error & { code?: unknown; cause?: unknown };\n const out: ErrFields = { err_type: errorType(e), err_message: String(e.message ?? \"\") };\n if (e.code !== undefined && e.code !== null) out.err_code = String(e.code);\n if (typeof e.stack === \"string\") out.err_stack = e.stack;\n\n const causes: string[] = [];\n let cause = e.cause;\n while (cause !== undefined && cause !== null && causes.length < MAX_CAUSE_DEPTH) {\n if (isErrorLike(cause)) {\n causes.push(`${errorType(cause)}: ${cause.message}`);\n cause = (cause as { cause?: unknown }).cause;\n } else {\n causes.push(defaultRedactor.json(cause));\n cause = undefined;\n }\n }\n if (causes.length > 0) out.err_cause = causes.join(\" <- \");\n return out;\n}\n\nconst logged = globalSingleton(\"logged\", () => new WeakSet<object>());\n\n// Marks an error as already written, so a later boundary (e.g. Next's onRequestError)\n// does not log it a second time.\nexport function markLogged(err: unknown): void {\n if (typeof err === \"object\" && err !== null) logged.add(err);\n}\n\nexport function isLogged(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && logged.has(err);\n}\n","import { isErrorLike, serializeError } from \"./error\";\nimport type { Level } from \"./levels\";\nimport { REDACTED, toSnakeCase, type Redactor } from \"./redact\";\n\nexport { DEFAULT_REDACT_KEYS, toSnakeCase } from \"./redact\";\n\n/** Final per-field hook: return a replacement, or undefined to drop the field. */\nexport type RedactHook = (key: string, value: Primitive) => unknown;\n\nexport type Fields = Record<string, unknown>;\nexport type Primitive = string | number | boolean | null;\nexport type LogRecord = Record<string, Primitive>;\n\nexport interface NormalizeOptions {\n snakeCase: boolean;\n redactor: Redactor;\n hook?: RedactHook;\n}\n\n// Fields the redact hook never sees, so every line keeps its level, message and event.\nconst HOOK_EXEMPT = new Set([\"level\", \"message\", \"event\"]);\n\n// Keys owned by Vector (overwritten or deleted on ingest) or by the logger itself.\nexport const RESERVED_KEYS = new Set([\n \"project\", \"service\", \"vps\", \"version\", \"container_name\", \"container_id\", \"image\", \"stream\",\n \"_timestamp\", \"label\", \"host\", \"source_type\", \"msg\", \"lvl\", \"severity\", \"level\", \"message\",\n]);\n\nexport const MAX_LINE_BYTES = 16000;\nconst MAX_MESSAGE = 500;\nconst MAX_STACK = 4000;\nconst MAX_STRING = 1000;\nconst MAX_DEPTH = 3;\nconst TRUNCATED = \"…[truncated]\";\n\n// Fields kept when a line is too large.\nconst KEEP_ON_SHRINK = new Set([\n \"level\", \"message\", \"event\", \"request_id\", \"trace_id\", \"span_id\", \"job_name\", \"job_id\", \"job_attempt\",\n \"user_id\", \"tenant_id\", \"err_type\", \"err_message\", \"err_code\",\n]);\n\nexport function stripUrl(url: string): string {\n const noQuery = url.split(/[?#]/, 1)[0] ?? \"\";\n return noQuery.replace(/^([a-z][a-z0-9+.-]*:\\/\\/)[^/@\\s]*@/i, \"$1\");\n}\n\nexport function truncate(s: string, max: number): string {\n return s.length > max ? s.slice(0, max - TRUNCATED.length) + TRUNCATED : s;\n}\n\nfunction isPlainObject(v: unknown): v is Fields {\n if (typeof v !== \"object\" || v === null) return false;\n const proto = Object.getPrototypeOf(v);\n return proto === Object.prototype || proto === null;\n}\n\nfunction isUrlKey(key: string): boolean {\n return key === \"http_path\" || key === \"http_url\" || key.endsWith(\"_url\");\n}\n\nfunction flattenInto(out: LogRecord, prefix: string, obj: Fields, depth: number, opts: NormalizeOptions): void {\n for (const [rawKey, value] of Object.entries(obj)) {\n const key = opts.snakeCase ? toSnakeCase(rawKey) : rawKey;\n const full = prefix ? `${prefix}_${key}` : key;\n if (value === undefined || typeof value === \"function\" || typeof value === \"symbol\") continue;\n if (value !== null && (opts.redactor.isSensitive(rawKey) || opts.redactor.isSensitive(full))) {\n out[full] = REDACTED;\n continue;\n }\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") {\n out[full] = value;\n } else if (typeof value === \"number\") {\n out[full] = Number.isFinite(value) ? value : String(value);\n } else if (typeof value === \"bigint\") {\n out[full] = value.toString();\n } else if (value instanceof Date) {\n out[full] = Number.isNaN(value.getTime()) ? \"Invalid Date\" : value.toISOString();\n } else if (isErrorLike(value)) {\n out[full] = `${value.name}: ${value.message}`;\n } else if (isPlainObject(value) && depth < MAX_DEPTH - 1) {\n flattenInto(out, full, value, depth + 1, opts);\n } else {\n // Arrays, deep objects, class instances: stringified with sensitive keys redacted.\n out[full] = opts.redactor.json(value);\n }\n }\n}\n\nfunction finalize(key: string, value: Primitive, opts: NormalizeOptions): Primitive {\n if (typeof value !== \"string\") return value;\n const v = opts.redactor.scrub(isUrlKey(key) ? stripUrl(value) : value);\n return truncate(v, key === \"err_stack\" ? MAX_STACK : MAX_STRING);\n}\n\nexport function buildRecord(\n level: Level,\n message: unknown,\n sources: (Fields | undefined)[],\n opts: NormalizeOptions,\n): LogRecord {\n const merged: Fields = {};\n for (const source of sources) if (source) Object.assign(merged, source);\n\n let err: unknown;\n if (merged.err !== undefined && merged.err !== null) {\n err = merged.err;\n delete merged.err;\n } else if (isErrorLike(merged.error)) {\n err = merged.error;\n delete merged.error;\n }\n\n const flat: LogRecord = {};\n flattenInto(flat, \"\", merged, 0, opts);\n if (err !== undefined) Object.assign(flat, serializeError(err));\n\n const text = typeof message === \"string\" ? message : opts.redactor.json(message);\n const out: LogRecord = { level, message: truncate(opts.redactor.scrub(text), MAX_MESSAGE) };\n for (const [k, v] of Object.entries(flat)) {\n const key = RESERVED_KEYS.has(k) ? `app_${k}` : k;\n let value = finalize(key, v, opts);\n if (opts.hook && !HOOK_EXEMPT.has(key)) {\n const replaced = opts.hook(key, value);\n if (replaced === undefined) continue;\n value = typeof replaced === \"object\" && replaced !== null ? opts.redactor.json(replaced) : (replaced as Primitive);\n }\n out[key] = value;\n }\n return out;\n}\n\nfunction byteLength(s: string): number {\n // UTF-8 uses at most 3 bytes per UTF-16 code unit: skip encoding short lines.\n if (s.length * 3 <= MAX_LINE_BYTES) return s.length;\n return new TextEncoder().encode(s).length;\n}\n\nexport function serializeRecord(record: LogRecord): string {\n const line = JSON.stringify(record);\n if (byteLength(line) <= MAX_LINE_BYTES) return line;\n const small: LogRecord = {};\n for (const [k, v] of Object.entries(record)) {\n if (KEEP_ON_SHRINK.has(k) || k.startsWith(\"http_\")) small[k] = v;\n }\n small.log_truncated = true;\n return JSON.stringify(small);\n}\n","import type { LogRecord } from \"./normalize\";\n\n// Human-readable line for local development only (LOG_FORMAT=pretty).\nexport function formatPretty(record: LogRecord): string {\n const { level, message, err_stack, ...rest } = record;\n const time = new Date().toISOString().slice(11, 23);\n const extras = Object.entries(rest)\n .map(([k, v]) => `${k}=${typeof v === \"string\" && /\\s/.test(v) ? JSON.stringify(v) : String(v)}`)\n .join(\" \");\n let line = `${time} ${String(level).toUpperCase().padEnd(5)} ${String(message)}${extras ? ` ${extras}` : \"\"}`;\n if (typeof err_stack === \"string\") line += `\\n${err_stack}`;\n return line;\n}\n","import { getContext } from \"./context\";\nimport { LEVEL_RANK, parseLevel, type Level } from \"./levels\";\nimport {\n buildRecord,\n serializeRecord,\n type Fields,\n type NormalizeOptions,\n type RedactHook,\n} from \"./normalize\";\nimport { formatPretty } from \"./pretty\";\nimport { createRedactor, type KeyPattern } from \"./redact\";\n\ntype LogMethod = (message: string, fields?: Fields) => void;\n\nexport interface Logger {\n readonly level: Level;\n trace: LogMethod;\n debug: LogMethod;\n info: LogMethod;\n warn: LogMethod;\n error: LogMethod;\n fatal: LogMethod;\n child(fields: Fields): Logger;\n isLevelEnabled(level: Level): boolean;\n}\n\nexport interface LoggerOptions {\n level?: Level | string;\n format?: \"json\" | \"pretty\";\n base?: Fields;\n /** Extra sensitive keys: names (matched like the defaults) or RegExp tested on the snake_case key. */\n redactKeys?: KeyPattern[];\n /** Extra value patterns masked in every string, e.g. REDACT_PATTERNS.phoneVN. */\n redactValues?: RegExp[];\n /** Final per-field hook: return a replacement, or undefined to drop the field. */\n redact?: RedactHook;\n snakeCase?: boolean;\n write?: (line: string) => void;\n}\n\nfunction env(name: string): string | undefined {\n return typeof process !== \"undefined\" ? process.env?.[name] : undefined;\n}\n\n// Captured before patchConsole can replace it, so the fallback never loops into the logger.\nconst consoleLog = console.log.bind(console);\n\nfunction defaultWrite(line: string): void {\n if (typeof process !== \"undefined\" && typeof process.stdout?.write === \"function\") {\n process.stdout.write(`${line}\\n`);\n } else {\n consoleLog(line);\n }\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const level = parseLevel(options.level ?? env(\"LOG_LEVEL\"));\n const format = options.format ?? (env(\"LOG_FORMAT\") === \"pretty\" ? \"pretty\" : \"json\");\n const write = options.write ?? defaultWrite;\n const norm: NormalizeOptions = {\n snakeCase: options.snakeCase ?? true,\n redactor: createRedactor({ keys: options.redactKeys, values: options.redactValues }),\n hook: options.redact,\n };\n\n const make = (bound: Fields): Logger => {\n const emit = (lvl: Level, message: string, fields?: Fields) => {\n if (LEVEL_RANK[lvl] < LEVEL_RANK[level]) return;\n let line: string;\n try {\n const record = buildRecord(lvl, message, [options.base, getContext(), bound, fields], norm);\n line = format === \"pretty\" ? formatPretty(record) : serializeRecord(record);\n } catch (e) {\n line = JSON.stringify({\n level: \"error\",\n message: \"log serialize failed\",\n event: \"log.serialize_failed\",\n err_message: String((e as Error)?.message ?? e).slice(0, 1000),\n original_message: String(message).slice(0, 500),\n });\n }\n try {\n write(line);\n } catch {\n // Logging must never break the app.\n }\n };\n return {\n level,\n trace: (m, f) => emit(\"trace\", m, f),\n debug: (m, f) => emit(\"debug\", m, f),\n info: (m, f) => emit(\"info\", m, f),\n warn: (m, f) => emit(\"warn\", m, f),\n error: (m, f) => emit(\"error\", m, f),\n fatal: (m, f) => emit(\"fatal\", m, f),\n child: (fields) => make({ ...bound, ...fields }),\n isLevelEnabled: (l) => LEVEL_RANK[l] >= LEVEL_RANK[level],\n };\n };\n return make({});\n}\n","// No imports: this module is shared with the edge entry (next-edge).\nexport const REQUEST_ID_RE = /^[A-Za-z0-9._-]{1,64}$/;\nconst TRACEPARENT_RE = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;\n\nexport function newRequestId(): string {\n return globalThis.crypto.randomUUID();\n}\n\nfunction first(header?: string | string[] | null): string | undefined {\n return Array.isArray(header) ? header[0] : (header ?? undefined);\n}\n\nexport function resolveRequestId(header?: string | string[] | null): string {\n const value = first(header);\n return value && REQUEST_ID_RE.test(value) ? value : newRequestId();\n}\n\nexport function parseTraceparent(header?: string | string[] | null): { trace_id: string; span_id: string } | undefined {\n const value = first(header)?.trim().toLowerCase();\n const m = value ? TRACEPARENT_RE.exec(value) : null;\n if (!m) return undefined;\n const [, version, traceId, spanId] = m as unknown as [string, string, string, string];\n if (version === \"ff\" || /^0+$/.test(traceId) || /^0+$/.test(spanId)) return undefined;\n return { trace_id: traceId, span_id: spanId };\n}\n","import { getContext } from \"./context\";\nimport { markLogged, serializeError } from \"./error\";\nimport type { Logger } from \"./logger\";\nimport { stripUrl, type Fields } from \"./normalize\";\nimport { parseTraceparent, resolveRequestId } from \"./request-id\";\n\nexport { newRequestId, parseTraceparent, REQUEST_ID_RE, resolveRequestId } from \"./request-id\";\n\nexport type HeaderSource = Headers | Record<string, string | string[] | undefined>;\n\nfunction header(headers: HeaderSource, name: string): string | string[] | undefined {\n if (typeof (headers as Headers).get === \"function\") return (headers as Headers).get(name) ?? undefined;\n return (headers as Record<string, string | string[] | undefined>)[name];\n}\n\nexport function requestContextFields(headers: HeaderSource): { request_id: string; trace_id?: string; span_id?: string } {\n const out: { request_id: string; trace_id?: string; span_id?: string } = {\n request_id: resolveRequestId(header(headers, \"x-request-id\")),\n };\n const tp = parseTraceparent(header(headers, \"traceparent\"));\n if (tp) Object.assign(out, tp);\n return out;\n}\n\n// Headers to forward to services we own, so their logs share request_id / trace_id.\nexport function propagationHeaders(): Record<string, string> {\n const ctx = getContext();\n const out: Record<string, string> = {};\n if (typeof ctx.request_id === \"string\") out[\"x-request-id\"] = ctx.request_id;\n if (typeof ctx.trace_id === \"string\" && typeof ctx.span_id === \"string\") {\n out.traceparent = `00-${ctx.trace_id}-${ctx.span_id}-01`;\n }\n return out;\n}\n\nexport const DEFAULT_SKIP_PATHS: (string | RegExp)[] = [\n /^\\/(health|healthz|ready|readyz|livez)\\/?$/,\n \"/favicon.ico\",\n /^\\/_next\\/static\\//,\n];\n\nexport interface HttpLogOptions {\n skipPaths?: (string | RegExp)[];\n}\n\nexport interface HttpRequestInfo {\n method: string;\n route?: string;\n path: string;\n status: number;\n duration_ms?: number;\n err?: unknown;\n fields?: Fields;\n}\n\nexport function shouldSkip(method: string, path: string, skipPaths: (string | RegExp)[] = DEFAULT_SKIP_PATHS): boolean {\n if (method.toUpperCase() === \"OPTIONS\") return true;\n const p = stripUrl(path);\n return skipPaths.some((s) => (typeof s === \"string\" ? p === s : s.test(p)));\n}\n\n// Writes the one `http.request` summary line for an inbound request.\nexport function logHttpRequest(log: Logger, info: HttpRequestInfo, opts: HttpLogOptions = {}): void {\n if (shouldSkip(info.method, info.path, opts.skipPaths)) return;\n const level = info.status >= 500 ? \"error\" : info.status >= 400 ? \"warn\" : \"info\";\n const path = stripUrl(info.path);\n const errFields: Fields = {};\n if (info.err !== undefined && info.err !== null) {\n Object.assign(errFields, serializeError(info.err));\n if (info.status < 500) delete errFields.err_stack;\n markLogged(info.err);\n }\n // Route templates keep the message bounded; the raw path would make one message per URL.\n const message = info.route ? `${info.method} ${info.route} ${info.status}` : `${info.method} ${info.status}`;\n log[level](message, {\n ...info.fields,\n event: \"http.request\",\n http_method: info.method,\n http_route: info.route,\n http_path: path,\n http_status: info.status,\n duration_ms: info.duration_ms === undefined ? undefined : Math.round(info.duration_ms),\n ...errFields,\n });\n}\n","import { propagationHeaders } from \"./http\";\nimport type { Logger } from \"./logger\";\n\nexport interface FetchLogOptions {\n peer_service: string;\n /** Forward x-request-id / traceparent. Only for services we own. */\n internal?: boolean;\n slowMs?: number;\n fetch?: typeof fetch;\n}\n\nfunction describeRequest(input: RequestInfo | URL, init?: RequestInit): { method: string; url: string } {\n const method = (init?.method ?? (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n return { method, url };\n}\n\nexport function createFetch(log: Logger, opts: FetchLogOptions): typeof fetch {\n const slowMs = opts.slowMs ?? 1000;\n const wrapped = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const base = opts.fetch ?? globalThis.fetch;\n const { method, url } = describeRequest(input, init);\n let requestInit = init;\n if (opts.internal) {\n const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined));\n for (const [k, v] of Object.entries(propagationHeaders())) if (!headers.has(k)) headers.set(k, v);\n requestInit = { ...init, headers };\n }\n const fields = { event: \"http.outbound\", peer_service: opts.peer_service, http_method: method, http_url: url };\n const start = performance.now();\n try {\n const res = await base(input, requestInit);\n const duration_ms = Math.round(performance.now() - start);\n if (res.status >= 500) {\n log.warn(\"outbound request failed\", { ...fields, http_status: res.status, duration_ms });\n } else if (duration_ms >= slowMs) {\n log.warn(\"outbound request slow\", { ...fields, http_status: res.status, duration_ms });\n }\n return res;\n } catch (err) {\n log.warn(\"outbound request failed\", { ...fields, duration_ms: Math.round(performance.now() - start), err });\n throw err;\n }\n };\n return wrapped as typeof fetch;\n}\n","import { getContext, withContext } from \"./context\";\nimport { markLogged } from \"./error\";\nimport type { Logger } from \"./logger\";\nimport type { Fields } from \"./normalize\";\n\nexport interface JobInfo {\n job_name: string;\n job_id?: string | number;\n job_attempt?: number;\n /** No retries left after this attempt (or decided per error). Defaults to true when unknown. */\n final_attempt?: boolean | ((err: unknown) => boolean);\n request_id?: string;\n fields?: Fields;\n}\n\nexport async function runJob<T>(log: Logger, info: JobInfo, fn: () => T | Promise<T>): Promise<T> {\n const ctx: Fields = { ...info.fields, job_name: info.job_name };\n if (info.job_id !== undefined) ctx.job_id = String(info.job_id);\n if (info.job_attempt !== undefined) ctx.job_attempt = info.job_attempt;\n if (info.request_id !== undefined) ctx.request_id = info.request_id;\n\n return withContext(ctx, async () => {\n const start = performance.now();\n try {\n const result = await fn();\n log.info(\"job completed\", { event: \"job.completed\", duration_ms: Math.round(performance.now() - start) });\n return result;\n } catch (err) {\n const final = typeof info.final_attempt === \"function\" ? info.final_attempt(err) : (info.final_attempt ?? true);\n log[final ? \"error\" : \"warn\"](\"job failed\", {\n event: \"job.failed\",\n duration_ms: Math.round(performance.now() - start),\n err,\n });\n markLogged(err);\n throw err;\n }\n });\n}\n\n/** Adds the current request_id to a job payload, so the job's logs link back to the request. */\nexport function jobData<T extends Record<string, unknown>>(data: T): T & { request_id?: string } {\n const requestId = getContext().request_id;\n if (typeof requestId !== \"string\" || data.request_id !== undefined) return data;\n return { ...data, request_id: requestId };\n}\n","import { isErrorLike, isLogged } from \"./error\";\nimport type { Level } from \"./levels\";\nimport type { Logger } from \"./logger\";\nimport { defaultRedactor } from \"./redact\";\n\nconst METHODS = { log: \"info\", info: \"info\", warn: \"warn\", error: \"error\", debug: \"debug\", trace: \"debug\" } as const;\ntype Method = keyof typeof METHODS;\ntype ConsoleFn = (...args: unknown[]) => void;\n\nexport interface PatchConsoleOptions {\n /** Return true to drop a console call, e.g. errors a framework hook will log anyway. */\n skip?: (args: unknown[]) => boolean;\n}\n\n/**\n * Routes console.log/info/warn/error/debug/trace through the logger, so legacy console calls\n * and framework output (e.g. Next.js errors) become JSON lines with request context.\n * Calls carrying an error that is already on a summary line are dropped.\n * Returns a function that restores the previous console methods.\n */\nexport function patchConsole(log: Logger, opts: PatchConsoleOptions = {}): () => void {\n const target = console as unknown as Record<Method, ConsoleFn>;\n const saved = {} as Record<Method, ConsoleFn>;\n let inside = false;\n\n for (const method of Object.keys(METHODS) as Method[]) {\n const previous = target[method];\n saved[method] = previous;\n const level: Level = METHODS[method];\n target[method] = (...args: unknown[]) => {\n // A write path that itself uses console must not loop back into the logger.\n if (inside) return previous.apply(console, args);\n inside = true;\n try {\n if (args.some((arg) => isErrorLike(arg) && isLogged(arg)) || opts.skip?.(args)) return;\n let err: unknown;\n const parts: string[] = [];\n for (const arg of args) {\n if (isErrorLike(arg)) {\n err ??= arg;\n parts.push(arg.message);\n } else {\n parts.push(typeof arg === \"string\" ? arg : defaultRedactor.json(arg));\n }\n }\n log[level](parts.join(\" \"), { event: \"console\", console_method: method, err });\n } finally {\n inside = false;\n }\n };\n }\n\n return () => {\n for (const method of Object.keys(saved) as Method[]) target[method] = saved[method];\n };\n}\n","import { globalSingleton } from \"./global\";\nimport type { Logger } from \"./logger\";\nimport type { Fields } from \"./normalize\";\n\nexport function logStartup(log: Logger, fields: Fields = {}): void {\n log.info(\"app started\", {\n event: \"app.started\",\n runtime_version: `node ${process.versions.node}`,\n log_level: log.level,\n ...fields,\n });\n}\n\n/** Call at the start of your own shutdown handler (e.g. on SIGTERM). The library never handles signals. */\nexport function logShutdown(log: Logger, fields: Fields = {}): void {\n log.info(\"app stopping\", { event: \"app.stopping\", ...fields });\n}\n\nexport interface ProcessHandlerOptions {\n /** Exit with code 1 after an uncaught error. Next.js keeps serving, so its adapter passes false. */\n exitOnCrash?: boolean;\n /** Time other crash handlers (Sentry, APM) get to flush before exit. Default 1000 ms. */\n exitDelayMs?: number;\n exit?: (code: number) => void;\n}\n\nexport function crashHandlers(log: Logger, opts: ProcessHandlerOptions = {}) {\n const exitOnCrash = opts.exitOnCrash ?? true;\n const exitDelayMs = opts.exitDelayMs ?? 1000;\n const exit = opts.exit ?? ((code: number) => process.exit(code));\n let exiting = false;\n const crash = (source: string, err: unknown) => {\n if (!exitOnCrash) {\n log.error(\"unhandled error\", { event: \"app.unhandled_error\", crash_source: source, err });\n return;\n }\n log.fatal(\"app crashed\", { event: \"app.crashed\", crash_source: source, err });\n if (exiting) return;\n exiting = true;\n if (typeof process !== \"undefined\") process.exitCode = 1;\n // Deferred so listeners registered after ours still run; unref so a process with nothing\n // left to do exits on its own (with exitCode 1) without waiting.\n const timer = setTimeout(() => exit(1), exitDelayMs);\n (timer as { unref?: () => void }).unref?.();\n };\n return {\n onUncaught: (err: unknown) => crash(\"uncaughtException\", err),\n onRejection: (reason: unknown) => crash(\"unhandledRejection\", reason),\n };\n}\n\nconst state = globalSingleton(\"process\", () => ({ installed: false }));\n\n/** Logs uncaught exceptions and unhandled rejections. Does not touch SIGTERM/SIGINT. */\nexport function installProcessHandlers(log: Logger, opts: ProcessHandlerOptions = {}): void {\n if (state.installed || typeof process === \"undefined\" || typeof process.on !== \"function\") return;\n state.installed = true;\n const h = crashHandlers(log, opts);\n process.on(\"uncaughtException\", h.onUncaught);\n process.on(\"unhandledRejection\", h.onRejection);\n}\n\nconst warningState = globalSingleton(\"warnings\", () => ({ installed: false }));\n\n/**\n * Logs Node process warnings (deprecations, MaxListeners...) as `process.warning` lines whose\n * err_stack points at the code that triggered them. Node still prints its own stderr copy\n * unless the process runs with --no-warnings (NODE_OPTIONS=--no-warnings).\n */\nexport function logProcessWarnings(log: Logger): void {\n if (warningState.installed || typeof process === \"undefined\" || typeof process.on !== \"function\") return;\n warningState.installed = true;\n process.on(\"warning\", (warning: Error) => {\n log.warn(\"process warning\", { event: \"process.warning\", err: warning });\n });\n}\n"],"mappings":"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","names":["header"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -46,12 +46,17 @@ declare function jobData<T extends Record<string, unknown>>(data: T): T & {
|
|
|
46
46
|
request_id?: string;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
interface PatchConsoleOptions {
|
|
50
|
+
/** Return true to drop a console call, e.g. errors a framework hook will log anyway. */
|
|
51
|
+
skip?: (args: unknown[]) => boolean;
|
|
52
|
+
}
|
|
49
53
|
/**
|
|
50
54
|
* Routes console.log/info/warn/error/debug/trace through the logger, so legacy console calls
|
|
51
55
|
* and framework output (e.g. Next.js errors) become JSON lines with request context.
|
|
56
|
+
* Calls carrying an error that is already on a summary line are dropped.
|
|
52
57
|
* Returns a function that restores the previous console methods.
|
|
53
58
|
*/
|
|
54
|
-
declare function patchConsole(log: Logger): () => void;
|
|
59
|
+
declare function patchConsole(log: Logger, opts?: PatchConsoleOptions): () => void;
|
|
55
60
|
|
|
56
61
|
declare function logStartup(log: Logger, fields?: Fields): void;
|
|
57
62
|
/** Call at the start of your own shutdown handler (e.g. on SIGTERM). The library never handles signals. */
|
|
@@ -65,5 +70,11 @@ interface ProcessHandlerOptions {
|
|
|
65
70
|
}
|
|
66
71
|
/** Logs uncaught exceptions and unhandled rejections. Does not touch SIGTERM/SIGINT. */
|
|
67
72
|
declare function installProcessHandlers(log: Logger, opts?: ProcessHandlerOptions): void;
|
|
73
|
+
/**
|
|
74
|
+
* Logs Node process warnings (deprecations, MaxListeners...) as `process.warning` lines whose
|
|
75
|
+
* err_stack points at the code that triggered them. Node still prints its own stderr copy
|
|
76
|
+
* unless the process runs with --no-warnings (NODE_OPTIONS=--no-warnings).
|
|
77
|
+
*/
|
|
78
|
+
declare function logProcessWarnings(log: Logger): void;
|
|
68
79
|
|
|
69
|
-
export { type FetchLogOptions, Fields, type JobInfo, Logger, type ProcessHandlerOptions, addContext, createFetch, getContext, installProcessHandlers, jobData, logShutdown, logStartup, parseTraceparent, patchConsole, recordError, resolveRequestId, runJob, serializeError, withContext };
|
|
80
|
+
export { type FetchLogOptions, Fields, type JobInfo, Logger, type PatchConsoleOptions, type ProcessHandlerOptions, addContext, createFetch, getContext, installProcessHandlers, jobData, logProcessWarnings, logShutdown, logStartup, parseTraceparent, patchConsole, recordError, resolveRequestId, runJob, serializeError, withContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -46,12 +46,17 @@ declare function jobData<T extends Record<string, unknown>>(data: T): T & {
|
|
|
46
46
|
request_id?: string;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
interface PatchConsoleOptions {
|
|
50
|
+
/** Return true to drop a console call, e.g. errors a framework hook will log anyway. */
|
|
51
|
+
skip?: (args: unknown[]) => boolean;
|
|
52
|
+
}
|
|
49
53
|
/**
|
|
50
54
|
* Routes console.log/info/warn/error/debug/trace through the logger, so legacy console calls
|
|
51
55
|
* and framework output (e.g. Next.js errors) become JSON lines with request context.
|
|
56
|
+
* Calls carrying an error that is already on a summary line are dropped.
|
|
52
57
|
* Returns a function that restores the previous console methods.
|
|
53
58
|
*/
|
|
54
|
-
declare function patchConsole(log: Logger): () => void;
|
|
59
|
+
declare function patchConsole(log: Logger, opts?: PatchConsoleOptions): () => void;
|
|
55
60
|
|
|
56
61
|
declare function logStartup(log: Logger, fields?: Fields): void;
|
|
57
62
|
/** Call at the start of your own shutdown handler (e.g. on SIGTERM). The library never handles signals. */
|
|
@@ -65,5 +70,11 @@ interface ProcessHandlerOptions {
|
|
|
65
70
|
}
|
|
66
71
|
/** Logs uncaught exceptions and unhandled rejections. Does not touch SIGTERM/SIGINT. */
|
|
67
72
|
declare function installProcessHandlers(log: Logger, opts?: ProcessHandlerOptions): void;
|
|
73
|
+
/**
|
|
74
|
+
* Logs Node process warnings (deprecations, MaxListeners...) as `process.warning` lines whose
|
|
75
|
+
* err_stack points at the code that triggered them. Node still prints its own stderr copy
|
|
76
|
+
* unless the process runs with --no-warnings (NODE_OPTIONS=--no-warnings).
|
|
77
|
+
*/
|
|
78
|
+
declare function logProcessWarnings(log: Logger): void;
|
|
68
79
|
|
|
69
|
-
export { type FetchLogOptions, Fields, type JobInfo, Logger, type ProcessHandlerOptions, addContext, createFetch, getContext, installProcessHandlers, jobData, logShutdown, logStartup, parseTraceparent, patchConsole, recordError, resolveRequestId, runJob, serializeError, withContext };
|
|
80
|
+
export { type FetchLogOptions, Fields, type JobInfo, Logger, type PatchConsoleOptions, type ProcessHandlerOptions, addContext, createFetch, getContext, installProcessHandlers, jobData, logProcessWarnings, logShutdown, logStartup, parseTraceparent, patchConsole, recordError, resolveRequestId, runJob, serializeError, withContext };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
installProcessHandlers,
|
|
3
|
+
logProcessWarnings,
|
|
3
4
|
logShutdown,
|
|
4
5
|
logStartup
|
|
5
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6ANRIB5B.js";
|
|
6
7
|
import {
|
|
7
8
|
DEFAULT_SKIP_PATHS,
|
|
8
9
|
buildRecord,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
defaultRedactor,
|
|
27
28
|
getContext,
|
|
28
29
|
isErrorLike,
|
|
30
|
+
isLogged,
|
|
29
31
|
recordError,
|
|
30
32
|
serializeError,
|
|
31
33
|
withContext
|
|
@@ -156,7 +158,7 @@ function createFetch(log, opts) {
|
|
|
156
158
|
|
|
157
159
|
// src/console.ts
|
|
158
160
|
var METHODS = { log: "info", info: "info", warn: "warn", error: "error", debug: "debug", trace: "debug" };
|
|
159
|
-
function patchConsole(log) {
|
|
161
|
+
function patchConsole(log, opts = {}) {
|
|
160
162
|
const target = console;
|
|
161
163
|
const saved = {};
|
|
162
164
|
let inside = false;
|
|
@@ -168,6 +170,7 @@ function patchConsole(log) {
|
|
|
168
170
|
if (inside) return previous.apply(console, args);
|
|
169
171
|
inside = true;
|
|
170
172
|
try {
|
|
173
|
+
if (args.some((arg) => isErrorLike(arg) && isLogged(arg)) || opts.skip?.(args)) return;
|
|
171
174
|
let err;
|
|
172
175
|
const parts = [];
|
|
173
176
|
for (const arg of args) {
|
|
@@ -199,6 +202,7 @@ export {
|
|
|
199
202
|
installProcessHandlers,
|
|
200
203
|
jobData,
|
|
201
204
|
logHttpRequest,
|
|
205
|
+
logProcessWarnings,
|
|
202
206
|
logShutdown,
|
|
203
207
|
logStartup,
|
|
204
208
|
parseTraceparent,
|