lograil 0.1.0 → 0.1.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 +105 -1
- package/README.md +3 -1
- package/dist/cjs/context/async-context.browser.d.ts +1 -7
- package/dist/cjs/context/async-context.browser.d.ts.map +1 -1
- package/dist/cjs/context/async-context.browser.js +4 -1
- package/dist/cjs/context/async-context.browser.js.map +1 -1
- package/dist/cjs/context/context.js +1 -1
- package/dist/cjs/context/context.js.map +1 -1
- package/dist/cjs/core/logger.d.ts +20 -16
- package/dist/cjs/core/logger.d.ts.map +1 -1
- package/dist/cjs/core/logger.js +115 -48
- package/dist/cjs/core/logger.js.map +1 -1
- package/dist/cjs/pipeline/formatter.d.ts.map +1 -1
- package/dist/cjs/pipeline/formatter.js +64 -31
- package/dist/cjs/pipeline/formatter.js.map +1 -1
- package/dist/cjs/pipeline/pipeline.d.ts.map +1 -1
- package/dist/cjs/pipeline/pipeline.js +2 -1
- package/dist/cjs/pipeline/pipeline.js.map +1 -1
- package/dist/cjs/pipeline/processor.d.ts.map +1 -1
- package/dist/cjs/pipeline/processor.js +18 -6
- package/dist/cjs/pipeline/processor.js.map +1 -1
- package/dist/cjs/pipeline/sampler.d.ts.map +1 -1
- package/dist/cjs/pipeline/sampler.js +5 -0
- package/dist/cjs/pipeline/sampler.js.map +1 -1
- package/dist/cjs/plugin/manager.d.ts.map +1 -1
- package/dist/cjs/plugin/manager.js +9 -1
- package/dist/cjs/plugin/manager.js.map +1 -1
- package/dist/cjs/plugin/otel-trace.d.ts.map +1 -1
- package/dist/cjs/plugin/otel-trace.js +4 -7
- package/dist/cjs/plugin/otel-trace.js.map +1 -1
- package/dist/cjs/runtime/electron-binding.d.ts +4 -0
- package/dist/cjs/runtime/electron-binding.d.ts.map +1 -1
- package/dist/cjs/runtime/electron-binding.js +24 -2
- package/dist/cjs/runtime/electron-binding.js.map +1 -1
- package/dist/cjs/runtime/electron.d.ts.map +1 -1
- package/dist/cjs/runtime/electron.js +7 -1
- package/dist/cjs/runtime/electron.js.map +1 -1
- package/dist/cjs/runtime/process-lifecycle.d.ts.map +1 -1
- package/dist/cjs/runtime/process-lifecycle.js +11 -0
- package/dist/cjs/runtime/process-lifecycle.js.map +1 -1
- package/dist/cjs/transport/cluster-ipc.d.ts +2 -0
- package/dist/cjs/transport/cluster-ipc.d.ts.map +1 -1
- package/dist/cjs/transport/cluster-ipc.js +53 -5
- package/dist/cjs/transport/cluster-ipc.js.map +1 -1
- package/dist/cjs/transport/console.d.ts.map +1 -1
- package/dist/cjs/transport/console.js +10 -9
- package/dist/cjs/transport/console.js.map +1 -1
- package/dist/cjs/transport/electron-ipc.d.ts +4 -17
- package/dist/cjs/transport/electron-ipc.d.ts.map +1 -1
- package/dist/cjs/transport/electron-ipc.js +42 -73
- package/dist/cjs/transport/electron-ipc.js.map +1 -1
- package/dist/cjs/transport/file.d.ts +10 -4
- package/dist/cjs/transport/file.d.ts.map +1 -1
- package/dist/cjs/transport/file.js +28 -8
- package/dist/cjs/transport/file.js.map +1 -1
- package/dist/cjs/transport/live.d.ts +2 -1
- package/dist/cjs/transport/live.d.ts.map +1 -1
- package/dist/cjs/transport/live.js +4 -1
- package/dist/cjs/transport/live.js.map +1 -1
- package/dist/cjs/transport/otlp.d.ts +1 -1
- package/dist/cjs/transport/otlp.d.ts.map +1 -1
- package/dist/cjs/transport/otlp.js +24 -21
- package/dist/cjs/transport/otlp.js.map +1 -1
- package/dist/cjs/transport/worker-ipc.d.ts +3 -0
- package/dist/cjs/transport/worker-ipc.d.ts.map +1 -1
- package/dist/cjs/transport/worker-ipc.js +76 -8
- package/dist/cjs/transport/worker-ipc.js.map +1 -1
- package/dist/cjs/types.d.ts +16 -5
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js +5 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/context/async-context.browser.d.ts +1 -7
- package/dist/esm/context/async-context.browser.d.ts.map +1 -1
- package/dist/esm/context/async-context.browser.js +4 -1
- package/dist/esm/context/async-context.browser.js.map +1 -1
- package/dist/esm/context/context.js +1 -1
- package/dist/esm/context/context.js.map +1 -1
- package/dist/esm/core/logger.d.ts +20 -16
- package/dist/esm/core/logger.d.ts.map +1 -1
- package/dist/esm/core/logger.js +115 -48
- package/dist/esm/core/logger.js.map +1 -1
- package/dist/esm/pipeline/formatter.d.ts.map +1 -1
- package/dist/esm/pipeline/formatter.js +64 -31
- package/dist/esm/pipeline/formatter.js.map +1 -1
- package/dist/esm/pipeline/pipeline.d.ts.map +1 -1
- package/dist/esm/pipeline/pipeline.js +2 -1
- package/dist/esm/pipeline/pipeline.js.map +1 -1
- package/dist/esm/pipeline/processor.d.ts.map +1 -1
- package/dist/esm/pipeline/processor.js +18 -6
- package/dist/esm/pipeline/processor.js.map +1 -1
- package/dist/esm/pipeline/sampler.d.ts.map +1 -1
- package/dist/esm/pipeline/sampler.js +5 -0
- package/dist/esm/pipeline/sampler.js.map +1 -1
- package/dist/esm/plugin/manager.d.ts.map +1 -1
- package/dist/esm/plugin/manager.js +9 -1
- package/dist/esm/plugin/manager.js.map +1 -1
- package/dist/esm/plugin/otel-trace.d.ts.map +1 -1
- package/dist/esm/plugin/otel-trace.js +4 -7
- package/dist/esm/plugin/otel-trace.js.map +1 -1
- package/dist/esm/runtime/electron-binding.d.ts +4 -0
- package/dist/esm/runtime/electron-binding.d.ts.map +1 -1
- package/dist/esm/runtime/electron-binding.js +24 -2
- package/dist/esm/runtime/electron-binding.js.map +1 -1
- package/dist/esm/runtime/electron.d.ts.map +1 -1
- package/dist/esm/runtime/electron.js +7 -1
- package/dist/esm/runtime/electron.js.map +1 -1
- package/dist/esm/runtime/process-lifecycle.d.ts.map +1 -1
- package/dist/esm/runtime/process-lifecycle.js +11 -0
- package/dist/esm/runtime/process-lifecycle.js.map +1 -1
- package/dist/esm/transport/cluster-ipc.d.ts +2 -0
- package/dist/esm/transport/cluster-ipc.d.ts.map +1 -1
- package/dist/esm/transport/cluster-ipc.js +52 -5
- package/dist/esm/transport/cluster-ipc.js.map +1 -1
- package/dist/esm/transport/console.d.ts.map +1 -1
- package/dist/esm/transport/console.js +10 -9
- package/dist/esm/transport/console.js.map +1 -1
- package/dist/esm/transport/electron-ipc.d.ts +4 -17
- package/dist/esm/transport/electron-ipc.d.ts.map +1 -1
- package/dist/esm/transport/electron-ipc.js +42 -71
- package/dist/esm/transport/electron-ipc.js.map +1 -1
- package/dist/esm/transport/file.d.ts +10 -4
- package/dist/esm/transport/file.d.ts.map +1 -1
- package/dist/esm/transport/file.js +28 -8
- package/dist/esm/transport/file.js.map +1 -1
- package/dist/esm/transport/live.d.ts +2 -1
- package/dist/esm/transport/live.d.ts.map +1 -1
- package/dist/esm/transport/live.js +4 -1
- package/dist/esm/transport/live.js.map +1 -1
- package/dist/esm/transport/otlp.d.ts +1 -1
- package/dist/esm/transport/otlp.d.ts.map +1 -1
- package/dist/esm/transport/otlp.js +24 -21
- package/dist/esm/transport/otlp.js.map +1 -1
- package/dist/esm/transport/worker-ipc.d.ts +3 -0
- package/dist/esm/transport/worker-ipc.d.ts.map +1 -1
- package/dist/esm/transport/worker-ipc.js +75 -8
- package/dist/esm/transport/worker-ipc.js.map +1 -1
- package/dist/esm/types.d.ts +16 -5
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +5 -1
- package/dist/esm/types.js.map +1 -1
- package/package.json +12 -3
- package/dist/cjs/transport/rotating-file.d.ts +0 -67
- package/dist/cjs/transport/rotating-file.d.ts.map +0 -1
- package/dist/cjs/transport/rotating-file.js +0 -179
- package/dist/cjs/transport/rotating-file.js.map +0 -1
- package/dist/esm/transport/rotating-file.d.ts +0 -67
- package/dist/esm/transport/rotating-file.d.ts.map +0 -1
- package/dist/esm/transport/rotating-file.js +0 -175
- package/dist/esm/transport/rotating-file.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,107 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This file is generated from git history by `scripts/gen-changelog.mjs` (run via `yarn changelog`) and refreshed automatically on each release.
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [v0.1.4] - 2026-09-04
|
|
8
8
|
|
|
9
|
+
- chore: 在 package.json 补充 repository、homepage 与 bugs 元信息
|
|
10
|
+
- 0.1.4
|
|
11
|
+
- ci: 升级 actions/setup-node 至 v6,发布环境改用 Node 24 并简化 npm publish
|
|
12
|
+
|
|
13
|
+
## [v0.1.3] - 2026-09-04
|
|
14
|
+
|
|
15
|
+
- 0.1.3
|
|
16
|
+
- docs: 在 AGENTS.md 新增类型检查章节,记录 typecheck 双命令与常见测试类型陷阱
|
|
17
|
+
- fix: 修复测试类型定义与 OpenTelemetry 类型路径
|
|
18
|
+
|
|
19
|
+
## [v0.1.2] - 2026-09-04
|
|
20
|
+
|
|
21
|
+
- 0.1.2
|
|
22
|
+
- ci: 移除 Publish 步骤的 NODE_AUTH_TOKEN,改用 npm OIDC 可信发布
|
|
23
|
+
- test: 补充 PluginContext 移除 transport/卸载插件与 setOnLevelCommand 回调接线的用例
|
|
24
|
+
- fix: 处理缺失 Electron 二进制时的错误,返回最小存根以避免运行时崩溃
|
|
25
|
+
- fix: 安全审计修复 8 个隐患问题,补充 10 个回归测试
|
|
26
|
+
- fix: add global deduplication for cluster/worker/electron IPC receivers
|
|
27
|
+
- chore: remove zero-copy IPC path from ElectronIpcTransport and update docs
|
|
28
|
+
- feat: 添加 log 方法作为 info 的别名
|
|
29
|
+
- fix: inject ipcRenderer explicitly in createElectronRuntime renderer path
|
|
30
|
+
- fix: remove invalid buffer transfer arg from electron postMessage calls
|
|
31
|
+
- chore: bump @opentelemetry/api peer dependency to ^1.9.1 and simplify dynamic import
|
|
32
|
+
- Optimize sampler, console, and context for performance improvements (#2)
|
|
33
|
+
|
|
34
|
+
## [v0.1.1] - 2026-09-02
|
|
35
|
+
|
|
36
|
+
- 0.1.1
|
|
37
|
+
- test: increase timeout for single mode capacity caps no-op test
|
|
38
|
+
- docs: add Glossary page and clarify key terms in guides
|
|
39
|
+
- docs: add per-transport level filtering, clarify scope vs child, fix plugin immutability
|
|
40
|
+
- refactor: rename namespace options to scope for consistency
|
|
41
|
+
- docs: add Context & Metadata guide and cross-link across docs
|
|
42
|
+
- feat: accept non-Error values as error in log entries
|
|
43
|
+
- test: add coverage tests for serialize processors and jsonFormatter, simplify vitest config
|
|
44
|
+
- ci: simplify docs deploy to latest root only, drop versioned docs and versions.json
|
|
45
|
+
- ci: use orphan commits for docs branch deployments
|
|
46
|
+
- Harden logging pipeline edge cases: OTLP flush drain, rotation semantics, plugin rollback, and transport teardown (#1)
|
|
47
|
+
- test: add braces to arrow function callback in signal handler test
|
|
48
|
+
- test: add integration tests for Node runtime cluster and worker_threads
|
|
49
|
+
- test: add coverage for edge cases in printf, formatter, pipeline, serializer, and sampler
|
|
50
|
+
- test: add coverage for edge cases in formatter, lifecycle, processor, and runtime
|
|
51
|
+
- test: add integration tests for LiveTransport replay/buffer and Logger.destroy edge cases
|
|
52
|
+
- test: add process handler cleanup and fix LiveTransport buffer validation
|
|
53
|
+
- fix: properly restore previous onmessage handler and add close to WorkerIpcTransport
|
|
54
|
+
- perf: replace unbounded dispatch promise chain with bounded inflight counter
|
|
55
|
+
- perf: cache namespace filters and share mutable path in redactNode
|
|
56
|
+
- docs: translate pronunciation guide to English
|
|
57
|
+
- docs: add pronunciation guide for lograil
|
|
58
|
+
- fix: correct GitHub repo name in logo URL from electron-logger to lograil
|
|
59
|
+
- fix: update logo image URL to GitHub raw link in README.md
|
|
60
|
+
- chore: update logo SVG design to train wheel motif
|
|
61
|
+
|
|
62
|
+
## [v0.1.0] - 2026-09-01
|
|
63
|
+
|
|
64
|
+
- chore: add author field to package.json
|
|
65
|
+
- test: remove unused LOG_LEVELS import and _entry helper
|
|
66
|
+
- feat(core): getLevel() returns peer level for cross-process consistency
|
|
67
|
+
- feat(transport): add cross-process log level sync via IPC
|
|
68
|
+
- feat(transport): add FileTransport file inspection API and tests
|
|
69
|
+
- test: align write calls with updated Transport interface signature
|
|
70
|
+
- fix(electron-ipc,core): surface IPC transport errors and guard flush against stalls
|
|
71
|
+
- refactor(transport): align write signatures with Transport interface
|
|
72
|
+
- docs: enable Mermaid support in VitePress docs
|
|
73
|
+
- docs(plugins): expand lifecycle docs with flow diagrams and error handling
|
|
74
|
+
- feat(worker-threads): add automatic log forwarding from workers to main thread
|
|
75
|
+
- feat(node): add cluster support with automatic worker-to-primary log forwarding
|
|
76
|
+
- docs: add runtime-specific guides and update navigation
|
|
77
|
+
- docs(FileTransport): document name option semantics
|
|
78
|
+
- refactor(FileTransport): remove custom fileName option from rotate-size and rotate-time modes
|
|
79
|
+
- feat(runtime): apply disk-safety defaults to default file transports and add maxFilesPerBucket cap
|
|
80
|
+
- feat(FileTransport): split rotate-time buckets by maxSize and trim maxFiles by time bucket
|
|
81
|
+
- docs: document browser bundling and web runtime usage
|
|
82
|
+
- fix(test): ensure dist directory exists before writing browser bundle
|
|
83
|
+
- feat(shims): add browser-compatible Node API shims and enforce their use
|
|
84
|
+
- fix(FileTransport): clarify maxAge semantics, track owned files, and suppress repeated write errors
|
|
85
|
+
- feat(FileTransport): add global capacity caps (maxTotalSize / maxAge) with throttled checks
|
|
86
|
+
- feat(runtime): move Electron log dir to app.getPath('logs'), allow dir override
|
|
87
|
+
- refactor(FileTransport): split 5 modes into isolated Rotator strategies
|
|
88
|
+
- fix(FileTransport): harden single-truncate on Windows and resume rotate-time ring on restart
|
|
89
|
+
- feat: replace RotatingFileTransport with unified FileTransport (5 modes, appName required)
|
|
90
|
+
- docs: reposition as universal logging library with Web/Node/Electron as first-class runtimes, plugins for other platforms
|
|
91
|
+
- docs: document runtime lifecycle hooks and Electron app quit events
|
|
92
|
+
- feat: wire runtime lifecycle hooks and cover Electron app quit events
|
|
93
|
+
- ci(test): harden verify.yml, lift coverage past 90% and fix otel-trace crash
|
|
94
|
+
- feat: lightweight child/scope loggers and printf-style message formatting
|
|
95
|
+
- perf: eliminate per-call allocations on hot path and fix transport queue leak
|
|
96
|
+
- style(theme): flatten version map
|
|
97
|
+
- fix(core): flush logs on exit with timeout safety
|
|
98
|
+
- docs(agents): add documentation wording guidelines
|
|
99
|
+
- docs(guide): add Introduction chapter covering what/why/when and core concepts
|
|
100
|
+
- docs(transport): restructure LiveTransport guide into entity vs formatted-string rendering
|
|
101
|
+
- fix(test): close loggers before removing temp dir in node-file integration
|
|
102
|
+
- feat(transport): add LiveTransport for in-process log streaming
|
|
103
|
+
- fix(ci): pass boolean input only on workflow_dispatch
|
|
104
|
+
- ci: add coverage thresholds and CI coverage gate
|
|
105
|
+
- test: 新增分层集成测试(Node 落盘 / Web jsdom / Electron 真实 IPC)
|
|
106
|
+
- docs: 用更口语化的措辞重写文档术语
|
|
107
|
+
- docs: 补充项目文档并修正迁移/排查表述
|
|
9
108
|
- fix(docs): 更新 GitHub 链接以指向正确的仓库
|
|
10
109
|
- feat: define immutable LogEntry contract and zero-copy IPC transfer
|
|
11
110
|
- feat(logger): 添加异步插件拦截顺序处理,确保传输队列独立,避免阻塞
|
|
@@ -36,3 +135,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
36
135
|
- feat: init
|
|
37
136
|
- Create README.md
|
|
38
137
|
|
|
138
|
+
[v0.1.0]: https://github.com/axetroy/lograil/compare/v0.1.0...v0.1.0
|
|
139
|
+
[v0.1.1]: https://github.com/axetroy/lograil/compare/v0.1.0...v0.1.1
|
|
140
|
+
[v0.1.2]: https://github.com/axetroy/lograil/compare/v0.1.1...v0.1.2
|
|
141
|
+
[v0.1.3]: https://github.com/axetroy/lograil/compare/v0.1.2...v0.1.3
|
|
142
|
+
[v0.1.4]: https://github.com/axetroy/lograil/compare/v0.1.3...v0.1.4
|
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="
|
|
2
|
+
<img src="https://raw.githubusercontent.com/axetroy/lograil/refs/heads/main/logo.svg" alt="lograil" width="128" height="128" />
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
# lograil
|
|
6
6
|
|
|
7
|
+
**Pronunciation**: /lɒɡ-reɪl/ (log-rail)
|
|
8
|
+
|
|
7
9
|
Structured, secure logging for **Web**, **Node.js**, and **Electron** — three first-class runtimes, one zero-config `logger`, pluggable transports, filters, processors, formatters, and plugins. Extend to any other platform through the plugin and runtime-adapter APIs.
|
|
8
10
|
|
|
9
11
|
The same `import { logger } from 'lograil'` works untouched in every runtime. On Electron, the main process writes logs to the console **and** daily rotating files, and renderer logs are forwarded over IPC automatically; on Node it persists to a rotating file by default; in the browser it speaks the console and any remote transport you add.
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Browser / non-Node stub. `AsyncLocalStorage` is unavailable here, so ambient
|
|
4
|
-
* context is a no-op — logs are unaffected and no context propagates. The real
|
|
5
|
-
* implementation (`async-context.ts`) is selected over this file in Node builds
|
|
6
|
-
* via the `browser` field in `package.json`.
|
|
7
|
-
*/
|
|
1
|
+
import type { AmbientContext } from './async-context.js';
|
|
8
2
|
export declare const asyncContext: {
|
|
9
3
|
run<T>(fn: () => T, _context: AmbientContext): T;
|
|
10
4
|
runAsync<T>(fn: () => Promise<T>, _context: AmbientContext): Promise<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-context.browser.d.ts","sourceRoot":"","sources":["../../../src/context/async-context.browser.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"async-context.browser.d.ts","sourceRoot":"","sources":["../../../src/context/async-context.browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAWzD,eAAO,MAAM,YAAY;QACnB,CAAC,MAAM,MAAM,CAAC,YAAY,cAAc,GAAG,CAAC;aAGvC,CAAC,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,YAAY,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;WAGhE,cAAc;iBAGR,OAAO;CAGrB,CAAC;AAEF,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,cAAc,GAAG,CAAC,CAE1E"}
|
|
@@ -8,6 +8,9 @@ exports.runWithContext = runWithContext;
|
|
|
8
8
|
* implementation (`async-context.ts`) is selected over this file in Node builds
|
|
9
9
|
* via the `browser` field in `package.json`.
|
|
10
10
|
*/
|
|
11
|
+
// Shared frozen empty object returned when no async store is active, so the
|
|
12
|
+
// common (no ambient context) path allocates nothing on every `get()`.
|
|
13
|
+
const EMPTY_AMBIENT = Object.freeze({});
|
|
11
14
|
exports.asyncContext = {
|
|
12
15
|
run(fn, _context) {
|
|
13
16
|
return fn();
|
|
@@ -16,7 +19,7 @@ exports.asyncContext = {
|
|
|
16
19
|
return fn();
|
|
17
20
|
},
|
|
18
21
|
get() {
|
|
19
|
-
return
|
|
22
|
+
return EMPTY_AMBIENT;
|
|
20
23
|
},
|
|
21
24
|
supported() {
|
|
22
25
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-context.browser.js","sourceRoot":"","sources":["../../../src/context/async-context.browser.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"async-context.browser.js","sourceRoot":"","sources":["../../../src/context/async-context.browser.ts"],"names":[],"mappings":";;;AA2BA,wCAEC;AA3BD;;;;;GAKG;AACH,4EAA4E;AAC5E,uEAAuE;AACvE,MAAM,aAAa,GAAmB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC3C,QAAA,YAAY,GAAG;IAC1B,GAAG,CAAI,EAAW,EAAE,QAAwB;QAC1C,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;IACD,QAAQ,CAAI,EAAoB,EAAE,QAAwB;QACxD,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;IACD,GAAG;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,SAAS;QACP,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAC;AAEF,0FAA0F;AAC1F,SAAgB,cAAc,CAAI,EAAW,EAAE,QAAwB;IACrE,OAAO,EAAE,EAAE,CAAC;AACd,CAAC"}
|
|
@@ -32,7 +32,7 @@ function createContextStore(initial) {
|
|
|
32
32
|
// Avoid cloning (and allocating) when the store is empty — the shared
|
|
33
33
|
// frozen object can never be mutated by callers.
|
|
34
34
|
for (const _k in data)
|
|
35
|
-
return {
|
|
35
|
+
return Object.assign({}, data);
|
|
36
36
|
return EMPTY_CONTEXT;
|
|
37
37
|
},
|
|
38
38
|
set(key, value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/context/context.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AA4BH,sCAGC;AAED,gDA6BC;AA7CD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAA4B,CAAC;AAEnE;;;;;GAKG;AACU,QAAA,YAAY,GAAG,aAAa,CAAC;AAE1C,uDAAuD;AACvD,SAAgB,aAAa,CAAC,CAA0B;IACtD,KAAK,MAAM,EAAE,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAiC;IAClE,IAAI,IAAI,GAA4B,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;IAE3D,MAAM,KAAK,GAAiB;QAC1B,GAAG;YACD,sEAAsE;YACtE,iDAAiD;YACjD,KAAK,MAAM,EAAE,IAAI,IAAI;gBAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/context/context.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AA4BH,sCAGC;AAED,gDA6BC;AA7CD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAA4B,CAAC;AAEnE;;;;;GAKG;AACU,QAAA,YAAY,GAAG,aAAa,CAAC;AAE1C,uDAAuD;AACvD,SAAgB,aAAa,CAAC,CAA0B;IACtD,KAAK,MAAM,EAAE,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAiC;IAClE,IAAI,IAAI,GAA4B,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;IAE3D,MAAM,KAAK,GAAiB;QAC1B,GAAG;YACD,sEAAsE;YACtE,iDAAiD;YACjD,KAAK,MAAM,EAAE,IAAI,IAAI;gBAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACtD,OAAO,aAAa,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,KAAK;YACZ,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACpB,CAAC;QACD,KAAK,CAAC,MAAM;YACV,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,CAAC,GAAG;YACR,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,KAAK;YACH,IAAI,GAAG,EAAE,CAAC;QACZ,CAAC;QACD,KAAK;YACH,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;KACF,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -42,9 +42,9 @@ export interface LoggerOptions {
|
|
|
42
42
|
/**
|
|
43
43
|
* Maximum time (ms) to spend flushing on process exit (`beforeExit`,
|
|
44
44
|
* `SIGINT`, `SIGTERM`) before giving up and letting the process exit, so a
|
|
45
|
-
* stalled transport flush can never hang shutdown. Default `2000
|
|
45
|
+
* stalled transport flush can never hang shutdown. Default `2000`.\
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
flushTimeoutMs?: number;
|
|
48
48
|
/** Optional scope / namespace for this logger. */
|
|
49
49
|
scope?: string;
|
|
50
50
|
/** Runtime adapter. Auto-detected when omitted. */
|
|
@@ -69,17 +69,17 @@ export interface LoggerOptions {
|
|
|
69
69
|
*/
|
|
70
70
|
levelEnvVar?: string | null;
|
|
71
71
|
/**
|
|
72
|
-
* Scope
|
|
72
|
+
* Scope filter. A comma- or space-separated list of glob patterns
|
|
73
73
|
* (with `*` wildcards); a leading `-` excludes. Only entries whose `scope`
|
|
74
|
-
* matches are emitted. Read automatically from `
|
|
74
|
+
* matches are emitted. Read automatically from `scopeFilterEnvVar` when omitted.
|
|
75
75
|
*/
|
|
76
|
-
|
|
76
|
+
scopeFilter?: string | string[];
|
|
77
77
|
/**
|
|
78
|
-
* Environment variable whose value supplies the
|
|
79
|
-
* `
|
|
78
|
+
* Environment variable whose value supplies the scope filter when
|
|
79
|
+
* `scopeFilter` is not set. Defaults to `"LOGRAIL_DEBUG"`. Set to `null`
|
|
80
80
|
* to disable.
|
|
81
81
|
*/
|
|
82
|
-
|
|
82
|
+
scopeFilterEnvVar?: string | null;
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* Internal options passed by `scope`/`child` to build a **lightweight** child
|
|
@@ -115,12 +115,14 @@ export declare class Logger implements LoggerMethods {
|
|
|
115
115
|
private parent?;
|
|
116
116
|
private levelOverride?;
|
|
117
117
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
118
|
+
* Bounded async queue for plugin interception. Tracks in-flight entries so
|
|
119
|
+
* `flush()` and `destroy()` know when all interceptions are done without
|
|
120
|
+
* letting the dispatch chain grow unboundedly (each push would append a
|
|
121
|
+
* `.then()` to an ever-longer Promise chain).
|
|
122
122
|
*/
|
|
123
|
-
private
|
|
123
|
+
private dispatchInflight;
|
|
124
|
+
private dispatchDrain;
|
|
125
|
+
private dispatchDrainResolve;
|
|
124
126
|
/** Independent async-write queue per transport. */
|
|
125
127
|
private transportQueues;
|
|
126
128
|
private destroyed;
|
|
@@ -130,9 +132,9 @@ export declare class Logger implements LoggerMethods {
|
|
|
130
132
|
private removeProcessHandlers?;
|
|
131
133
|
private onLoggerError?;
|
|
132
134
|
private writeTimeoutMs;
|
|
133
|
-
private
|
|
135
|
+
private flushTimeoutMs;
|
|
134
136
|
private _exiting;
|
|
135
|
-
private
|
|
137
|
+
private scopeFilter?;
|
|
136
138
|
/** True for loggers created via `scope`/`child` (share the parent's plumbing). */
|
|
137
139
|
private isChild;
|
|
138
140
|
/** Cached peer process level. When set, takes precedence over local `level` in `getLevel()`. */
|
|
@@ -209,6 +211,8 @@ export declare class Logger implements LoggerMethods {
|
|
|
209
211
|
trace: LogFn;
|
|
210
212
|
debug: LogFn;
|
|
211
213
|
info: LogFn;
|
|
214
|
+
/** Alias for {@link info}. */
|
|
215
|
+
log: LogFn;
|
|
212
216
|
warn: LogFn;
|
|
213
217
|
error: LogFn;
|
|
214
218
|
fatal: LogFn;
|
|
@@ -241,7 +245,7 @@ export declare class Logger implements LoggerMethods {
|
|
|
241
245
|
* exit the process) without risking a hang on a stalled transport.
|
|
242
246
|
*/
|
|
243
247
|
private flushWithTimeout;
|
|
244
|
-
/** Set the max time (ms) to flush
|
|
248
|
+
/** Set the max time (ms) to flush before process exit before giving up. */
|
|
245
249
|
setExitFlushTimeout(ms: number): this;
|
|
246
250
|
/** Get the current exit-flush timeout (ms). */
|
|
247
251
|
getExitFlushTimeout(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/core/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAC;AAE/F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAsCxD,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AAE3F,8FAA8F;AAC9F,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,gBAAgB,CAAC;IACxB,uEAAuE;IACvE,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/core/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAC;AAE/F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAsCxD,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AAE3F,8FAA8F;AAC9F,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,gBAAgB,CAAC;IACxB,uEAAuE;IACvE,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;AAkFjF,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,gEAAgE;IAChE,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,QAAQ,GAAG,eAAe,CAAC;IACtC,8DAA8D;IAC9D,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;;GAMG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAsBD;;;;;;;;GAQG;AACH,qBAAa,MAAO,YAAW,aAAa;IAC1C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,UAAU,CAAe;IACjC,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,oBAAoB,CAAuC;IACnE,mDAAmD;IACnD,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAC,CAAa;IACpC,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,qBAAqB,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAa;IAC3C,OAAO,CAAC,aAAa,CAAC,CAAqB;IAC3C,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,kFAAkF;IAClF,OAAO,CAAC,OAAO,CAAS;IACxB,gGAAgG;IAChG,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,qFAAqF;IACrF,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,wEAAwE;IACxE,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,OAAO,GAAE,aAAa,GAAG,YAAiB;IAuDtD;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAiBtB;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IASlC,QAAQ,IAAI,MAAM;IAUlB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAUpC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAMpD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAI7C,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMnD,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAKxC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkBnC,8CAA8C;IAC9C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpC,oEAAoE;IACpE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,4GAA4G;IAC5G,WAAW,IAAI,QAAQ;IAIvB,4FAA4F;IAC5F,OAAO,CAAC,kBAAkB;IAW1B,aAAa,IAAI,SAAS,SAAS,EAAE;IAMrC,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC;;;;;;;;;OASG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;IAc/D;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAO,GAAG,MAAM;IAgBzF,KAAK,EAAE,KAAK,CAA2D;IACvE,KAAK,EAAE,KAAK,CAA2D;IACvE,IAAI,EAAE,KAAK,CAA0D;IACrE,8BAA8B;IAC9B,GAAG,EAAE,KAAK,CAA0D;IACpE,IAAI,EAAE,KAAK,CAA0D;IACrE,KAAK,EAAE,KAAK,CAA2D;IACvE,KAAK,EAAE,KAAK,CAA2D;IAEvE,OAAO,CAAC,IAAI;IAaZ;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;IA6BhB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,UAAU;IA2ElB,OAAO,CAAC,iBAAiB;IAmCzB,2EAA2E;IAC3E,OAAO,CAAC,UAAU;IAclB,0EAA0E;IAC1E,OAAO,CAAC,UAAU;IAOlB,qFAAqF;IACrF,OAAO,CAAC,oBAAoB;IAWtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAexB,2EAA2E;IAC3E,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKrC,+CAA+C;IAC/C,mBAAmB,IAAI,MAAM;IAM7B;;;;OAIG;IACH,kBAAkB,IAAI,IAAI;IAiE1B;;;;OAIG;IACH,mBAAmB,IAAI,IAAI;IA2C3B;;;;;;OAMG;IACH,eAAe,IAAI,MAAM,IAAI;IAgCvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAgC/B"}
|
package/dist/cjs/core/logger.js
CHANGED
|
@@ -32,6 +32,15 @@ function isoFromMs(ms) {
|
|
|
32
32
|
TIME_DATE.setTime(ms);
|
|
33
33
|
return `${pad(TIME_DATE.getUTCFullYear(), 4)}-${pad(TIME_DATE.getUTCMonth() + 1, 2)}-${pad(TIME_DATE.getUTCDate(), 2)}T${pad(TIME_DATE.getUTCHours(), 2)}:${pad(TIME_DATE.getUTCMinutes(), 2)}:${pad(TIME_DATE.getUTCSeconds(), 2)}.${pad(TIME_DATE.getUTCMilliseconds(), 3)}Z`;
|
|
34
34
|
}
|
|
35
|
+
/** Cache compiled namespace filters by normalized input to avoid recompiling regexes on every call. */
|
|
36
|
+
const nsFilterCache = new Map();
|
|
37
|
+
function serializeNsInput(input) {
|
|
38
|
+
if (!input)
|
|
39
|
+
return '';
|
|
40
|
+
if (Array.isArray(input))
|
|
41
|
+
return input.join(',');
|
|
42
|
+
return input;
|
|
43
|
+
}
|
|
35
44
|
function escapeRegex(s) {
|
|
36
45
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
37
46
|
}
|
|
@@ -48,22 +57,34 @@ function toPattern(token) {
|
|
|
48
57
|
* `undefined` (no filtering).
|
|
49
58
|
*/
|
|
50
59
|
function compileNamespaceFilter(input) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
const key = serializeNsInput(input);
|
|
61
|
+
if (nsFilterCache.has(key))
|
|
62
|
+
return nsFilterCache.get(key);
|
|
63
|
+
let result;
|
|
64
|
+
if (!input || (Array.isArray(input) && input.length === 0)) {
|
|
65
|
+
result = undefined;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const tokens = (Array.isArray(input) ? input : input.split(/[ ,]+/))
|
|
69
|
+
.map((t) => t.trim())
|
|
70
|
+
.filter(Boolean);
|
|
71
|
+
if (tokens.length === 0) {
|
|
72
|
+
result = undefined;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const includes = [];
|
|
76
|
+
const excludes = [];
|
|
77
|
+
for (const token of tokens) {
|
|
78
|
+
if (token.startsWith('-'))
|
|
79
|
+
excludes.push(toPattern(token.slice(1)));
|
|
80
|
+
else
|
|
81
|
+
includes.push(toPattern(token));
|
|
82
|
+
}
|
|
83
|
+
result = { includes, excludes };
|
|
84
|
+
}
|
|
65
85
|
}
|
|
66
|
-
|
|
86
|
+
nsFilterCache.set(key, result);
|
|
87
|
+
return result;
|
|
67
88
|
}
|
|
68
89
|
function matchesNamespace(scope, filter) {
|
|
69
90
|
if (!filter)
|
|
@@ -106,12 +127,14 @@ function getNodeProcess() {
|
|
|
106
127
|
class Logger {
|
|
107
128
|
constructor(options = {}) {
|
|
108
129
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
130
|
+
* Bounded async queue for plugin interception. Tracks in-flight entries so
|
|
131
|
+
* `flush()` and `destroy()` know when all interceptions are done without
|
|
132
|
+
* letting the dispatch chain grow unboundedly (each push would append a
|
|
133
|
+
* `.then()` to an ever-longer Promise chain).
|
|
113
134
|
*/
|
|
114
|
-
this.
|
|
135
|
+
this.dispatchInflight = 0;
|
|
136
|
+
this.dispatchDrain = null;
|
|
137
|
+
this.dispatchDrainResolve = undefined;
|
|
115
138
|
/** Independent async-write queue per transport. */
|
|
116
139
|
this.transportQueues = new Map();
|
|
117
140
|
this.destroyed = false;
|
|
@@ -126,6 +149,8 @@ class Logger {
|
|
|
126
149
|
this.trace = (message, ...args) => this.emit('trace', message, args);
|
|
127
150
|
this.debug = (message, ...args) => this.emit('debug', message, args);
|
|
128
151
|
this.info = (message, ...args) => this.emit('info', message, args);
|
|
152
|
+
/** Alias for {@link info}. */
|
|
153
|
+
this.log = (message, ...args) => this.emit('info', message, args);
|
|
129
154
|
this.warn = (message, ...args) => this.emit('warn', message, args);
|
|
130
155
|
this.error = (message, ...args) => this.emit('error', message, args);
|
|
131
156
|
this.fatal = (message, ...args) => this.emit('fatal', message, args);
|
|
@@ -153,11 +178,11 @@ class Logger {
|
|
|
153
178
|
this.level = (0, types_js_1.normalizeLevel)(levelInput);
|
|
154
179
|
this.originalLevel = this.level;
|
|
155
180
|
this.scopeName = options.scope;
|
|
156
|
-
const nsInput = options.
|
|
157
|
-
(options.
|
|
181
|
+
const nsInput = options.scopeFilter ??
|
|
182
|
+
(options.scopeFilterEnvVar === null
|
|
158
183
|
? undefined
|
|
159
|
-
: readEnvVar(options.
|
|
160
|
-
this.
|
|
184
|
+
: readEnvVar(options.scopeFilterEnvVar ?? 'LOGRAIL_DEBUG'));
|
|
185
|
+
this.scopeFilter = compileNamespaceFilter(nsInput);
|
|
161
186
|
// On the Electron main process, receive renderer logs over IPC.
|
|
162
187
|
if (this.runtime.attachReceiver) {
|
|
163
188
|
this.detachReceiver = this.runtime.attachReceiver((entry) => this.ingestEntry(entry));
|
|
@@ -169,7 +194,7 @@ class Logger {
|
|
|
169
194
|
this.attachExitHandlers();
|
|
170
195
|
this.onLoggerError = options.onError;
|
|
171
196
|
this.writeTimeoutMs = options.writeTimeoutMs ?? 5000;
|
|
172
|
-
this.
|
|
197
|
+
this.flushTimeoutMs = options.flushTimeoutMs ?? 2000;
|
|
173
198
|
// Wire the pipeline/plugin error sinks into the unified handler.
|
|
174
199
|
this.pipeline.onError = (err, info) => this.reportError(info.phase, err, info.entry);
|
|
175
200
|
this.plugins.onError = (name, err, entry) => this.reportError('plugin', err, entry, name);
|
|
@@ -187,13 +212,13 @@ class Logger {
|
|
|
187
212
|
this.pipeline = parent.pipeline;
|
|
188
213
|
this.plugins = parent.plugins;
|
|
189
214
|
this.transports = parent.transports;
|
|
190
|
-
this.
|
|
215
|
+
this.scopeFilter = parent.scopeFilter;
|
|
191
216
|
this.context = opts.context ?? (0, index_js_3.createContextStore)();
|
|
192
217
|
this.scopeName = opts.scope;
|
|
193
218
|
// Only a root logger owns the shared plugin error sink; children inherit it.
|
|
194
219
|
this.onLoggerError = parent.onLoggerError;
|
|
195
220
|
this.writeTimeoutMs = parent.writeTimeoutMs;
|
|
196
|
-
this.
|
|
221
|
+
this.flushTimeoutMs = parent.flushTimeoutMs;
|
|
197
222
|
if (opts.levelOverride !== undefined)
|
|
198
223
|
this.levelOverride = opts.levelOverride;
|
|
199
224
|
}
|
|
@@ -207,7 +232,7 @@ class Logger {
|
|
|
207
232
|
return;
|
|
208
233
|
if (entry.level < this.getLevel())
|
|
209
234
|
return;
|
|
210
|
-
if (!matchesNamespace(entry.scope, this.
|
|
235
|
+
if (!matchesNamespace(entry.scope, this.scopeFilter))
|
|
211
236
|
return;
|
|
212
237
|
this.dispatch(entry);
|
|
213
238
|
}
|
|
@@ -258,9 +283,22 @@ class Logger {
|
|
|
258
283
|
}
|
|
259
284
|
removeTransport(name) {
|
|
260
285
|
const removed = this.transports.filter((t) => t.name === name);
|
|
261
|
-
for (const t of removed)
|
|
262
|
-
this.transportQueues.delete(t);
|
|
263
286
|
this.transports = this.transports.filter((t) => t.name !== name);
|
|
287
|
+
for (const transport of removed) {
|
|
288
|
+
const prev = this.transportQueues.get(transport) ?? Promise.resolve();
|
|
289
|
+
const teardown = prev
|
|
290
|
+
.then(async () => {
|
|
291
|
+
if (transport.flush)
|
|
292
|
+
await this.guardFlush(transport.flush.bind(transport));
|
|
293
|
+
if (transport.close)
|
|
294
|
+
await Promise.resolve(transport.close());
|
|
295
|
+
})
|
|
296
|
+
.catch((err) => this.reportError('transport', err, undefined, transport.name))
|
|
297
|
+
.finally(() => {
|
|
298
|
+
this.transportQueues.delete(transport);
|
|
299
|
+
});
|
|
300
|
+
this.transportQueues.set(transport, teardown);
|
|
301
|
+
}
|
|
264
302
|
}
|
|
265
303
|
/** Unregister a plugin by name at runtime. */
|
|
266
304
|
unregisterPlugin(name) {
|
|
@@ -348,7 +386,7 @@ class Logger {
|
|
|
348
386
|
const levelValue = types_js_1.LOG_LEVELS[levelName];
|
|
349
387
|
if (levelValue < this.getLevel())
|
|
350
388
|
return;
|
|
351
|
-
if (!matchesNamespace(this.scopeName, this.
|
|
389
|
+
if (!matchesNamespace(this.scopeName, this.scopeFilter))
|
|
352
390
|
return;
|
|
353
391
|
const entry = this.buildEntry(levelName, levelValue, message, args);
|
|
354
392
|
const processed = this.pipeline.process(entry);
|
|
@@ -364,13 +402,29 @@ class Logger {
|
|
|
364
402
|
*/
|
|
365
403
|
dispatch(entry) {
|
|
366
404
|
if (this.plugins.hasEntryInterceptors()) {
|
|
367
|
-
|
|
405
|
+
// Create or reset the drain promise eagerly so that `flush()` callers
|
|
406
|
+
// always have a non-null promise to await, even if they arrive before
|
|
407
|
+
// the current batch of in-flight interceptions completes.
|
|
408
|
+
this.dispatchDrain = new Promise((resolve) => {
|
|
409
|
+
this.dispatchDrainResolve = resolve;
|
|
410
|
+
});
|
|
411
|
+
this.dispatchInflight++;
|
|
412
|
+
this.plugins
|
|
413
|
+
.intercept(entry)
|
|
414
|
+
.then((intercepted) => {
|
|
368
415
|
if (intercepted)
|
|
369
416
|
this.writeToTransports(intercepted);
|
|
417
|
+
})
|
|
418
|
+
.catch((err) => this.reportError('plugin', err))
|
|
419
|
+
.finally(() => {
|
|
420
|
+
this.dispatchInflight--;
|
|
421
|
+
if (this.dispatchInflight === 0) {
|
|
422
|
+
const resolve = this.dispatchDrainResolve;
|
|
423
|
+
this.dispatchDrain = null;
|
|
424
|
+
this.dispatchDrainResolve = undefined;
|
|
425
|
+
resolve?.();
|
|
426
|
+
}
|
|
370
427
|
});
|
|
371
|
-
this.dispatchQueue = this.dispatchQueue
|
|
372
|
-
.then(() => p)
|
|
373
|
-
.catch((err) => this.reportError('plugin', err));
|
|
374
428
|
return;
|
|
375
429
|
}
|
|
376
430
|
this.writeToTransports(entry);
|
|
@@ -416,7 +470,9 @@ class Logger {
|
|
|
416
470
|
rest = [message, ...args];
|
|
417
471
|
}
|
|
418
472
|
if (!error) {
|
|
419
|
-
error =
|
|
473
|
+
error =
|
|
474
|
+
rest.find((a) => a instanceof Error) ??
|
|
475
|
+
rest.find((a) => typeof a === 'string' && a.length > 0);
|
|
420
476
|
}
|
|
421
477
|
const now = this.runtime.now();
|
|
422
478
|
const ts = typeof now === 'number' ? now : new Date(now).getTime();
|
|
@@ -503,7 +559,7 @@ class Logger {
|
|
|
503
559
|
}
|
|
504
560
|
/** Await a transport's async `flush`, but never let it stall teardown. */
|
|
505
561
|
guardFlush(p) {
|
|
506
|
-
if (!this.
|
|
562
|
+
if (!this.flushTimeoutMs)
|
|
507
563
|
return Promise.resolve();
|
|
508
564
|
const result = p();
|
|
509
565
|
if (!result || typeof result.then !== 'function')
|
|
@@ -521,7 +577,8 @@ class Logger {
|
|
|
521
577
|
async flush() {
|
|
522
578
|
// Let in-flight interception finish so every scheduled write has been
|
|
523
579
|
// enqueued onto its transport's own queue.
|
|
524
|
-
|
|
580
|
+
if (this.dispatchInflight > 0)
|
|
581
|
+
await this.dispatchDrain;
|
|
525
582
|
// Aggregate all per-transport async-write queues. `allSettled` means a
|
|
526
583
|
// rejected/errored transport queue never rejects flush; a stalled one is
|
|
527
584
|
// bounded by `writeTimeoutMs` via `guardWrite`.
|
|
@@ -552,15 +609,15 @@ class Logger {
|
|
|
552
609
|
this.flush().then(done, done);
|
|
553
610
|
});
|
|
554
611
|
}
|
|
555
|
-
/** Set the max time (ms) to flush
|
|
612
|
+
/** Set the max time (ms) to flush before process exit before giving up. */
|
|
556
613
|
setExitFlushTimeout(ms) {
|
|
557
614
|
if (Number.isFinite(ms) && ms >= 0)
|
|
558
|
-
this.
|
|
615
|
+
this.flushTimeoutMs = ms;
|
|
559
616
|
return this;
|
|
560
617
|
}
|
|
561
618
|
/** Get the current exit-flush timeout (ms). */
|
|
562
619
|
getExitFlushTimeout() {
|
|
563
|
-
return this.
|
|
620
|
+
return this.flushTimeoutMs;
|
|
564
621
|
}
|
|
565
622
|
// ---- Process integration ----
|
|
566
623
|
/**
|
|
@@ -577,7 +634,7 @@ class Logger {
|
|
|
577
634
|
// adapters that don't supply lifecycle hooks (e.g. custom test runtimes).
|
|
578
635
|
const lc = this.runtime.lifecycle;
|
|
579
636
|
if (lc) {
|
|
580
|
-
const ms = this.
|
|
637
|
+
const ms = this.flushTimeoutMs;
|
|
581
638
|
const detach = lc.onFlushBeforeExit(() => {
|
|
582
639
|
void this.flushWithTimeout(ms);
|
|
583
640
|
});
|
|
@@ -592,7 +649,7 @@ class Logger {
|
|
|
592
649
|
const proc = getNodeProcess();
|
|
593
650
|
if (!proc)
|
|
594
651
|
return;
|
|
595
|
-
const ms = this.
|
|
652
|
+
const ms = this.flushTimeoutMs;
|
|
596
653
|
// On normal exit the event loop is about to empty: flush pending writes.
|
|
597
654
|
// `beforeExit` re-fires as long as async writes keep the loop alive, so the
|
|
598
655
|
// queue keeps draining until empty (bounded by `ms` if a sink stalls).
|
|
@@ -619,6 +676,14 @@ class Logger {
|
|
|
619
676
|
proc.on('beforeExit', onBeforeExit);
|
|
620
677
|
proc.on('SIGINT', onSigInt);
|
|
621
678
|
proc.on('SIGTERM', onSigTerm);
|
|
679
|
+
// Windows does not emit `SIGTERM`. Register `SIGBREAK` (Ctrl+Break) as a
|
|
680
|
+
// best-effort fallback so `autoFlushOnExit` has a signal hook on that
|
|
681
|
+
// platform. In practice taskkill / OS shutdown kills without emitting any
|
|
682
|
+
// Node signal, so no handler can cover that path — the `beforeExit` hook
|
|
683
|
+
// is the only portable shutdown flush mechanism.
|
|
684
|
+
if (process.platform === 'win32') {
|
|
685
|
+
proc.on('SIGBREAK', onSigInt);
|
|
686
|
+
}
|
|
622
687
|
this.processHandlersAttached = true;
|
|
623
688
|
const prev = this.removeProcessHandlers;
|
|
624
689
|
this.removeProcessHandlers = () => {
|
|
@@ -643,7 +708,7 @@ class Logger {
|
|
|
643
708
|
// fall back to the direct `process` binding below, which is a no-op there.
|
|
644
709
|
const lc = this.runtime.lifecycle;
|
|
645
710
|
if (lc?.onUncaughtError) {
|
|
646
|
-
const ms = this.
|
|
711
|
+
const ms = this.flushTimeoutMs;
|
|
647
712
|
const detach = lc.onUncaughtError((err) => {
|
|
648
713
|
this.fatal(err);
|
|
649
714
|
return this.flushWithTimeout(ms);
|
|
@@ -661,11 +726,11 @@ class Logger {
|
|
|
661
726
|
return;
|
|
662
727
|
const onUncaught = (err) => {
|
|
663
728
|
this.fatal(err);
|
|
664
|
-
void this.flushWithTimeout(this.
|
|
729
|
+
void this.flushWithTimeout(this.flushTimeoutMs).finally(() => proc.exit(1));
|
|
665
730
|
};
|
|
666
731
|
const onRejection = (reason) => {
|
|
667
732
|
this.fatal(reason);
|
|
668
|
-
void this.flushWithTimeout(this.
|
|
733
|
+
void this.flushWithTimeout(this.flushTimeoutMs).finally(() => proc.exit(1));
|
|
669
734
|
};
|
|
670
735
|
proc.on('uncaughtException', onUncaught);
|
|
671
736
|
proc.on('unhandledRejection', onRejection);
|
|
@@ -730,7 +795,7 @@ class Logger {
|
|
|
730
795
|
// Flush pending writes before tearing down transports, so buffered logs
|
|
731
796
|
// are not lost. Bounded by the exit-flush timeout so a stalled sink can
|
|
732
797
|
// never hang teardown.
|
|
733
|
-
await this.flushWithTimeout(this.
|
|
798
|
+
await this.flushWithTimeout(this.flushTimeoutMs).catch(() => { });
|
|
734
799
|
await this.plugins.destroy().catch(() => { });
|
|
735
800
|
this.detachReceiver?.();
|
|
736
801
|
this.peerLevel = undefined;
|
|
@@ -744,7 +809,9 @@ class Logger {
|
|
|
744
809
|
}
|
|
745
810
|
}
|
|
746
811
|
this.transportQueues.clear();
|
|
747
|
-
this.
|
|
812
|
+
this.dispatchInflight = 0;
|
|
813
|
+
this.dispatchDrain = null;
|
|
814
|
+
this.dispatchDrainResolve = undefined;
|
|
748
815
|
}
|
|
749
816
|
}
|
|
750
817
|
exports.Logger = Logger;
|