lograil 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +40 -0
- package/dist/cjs/context/async-context.browser.d.ts +16 -0
- package/dist/cjs/context/async-context.browser.d.ts.map +1 -0
- package/dist/cjs/context/async-context.browser.js +29 -0
- package/dist/cjs/context/async-context.browser.js.map +1 -0
- package/dist/cjs/context/async-context.d.ts +10 -0
- package/dist/cjs/context/async-context.d.ts.map +1 -0
- package/dist/cjs/context/async-context.js +37 -0
- package/dist/cjs/context/async-context.js.map +1 -0
- package/dist/cjs/context/context.d.ts +33 -0
- package/dist/cjs/context/context.d.ts.map +1 -0
- package/dist/cjs/context/context.js +57 -0
- package/dist/cjs/context/context.js.map +1 -0
- package/dist/cjs/context/index.d.ts +3 -0
- package/dist/cjs/context/index.d.ts.map +1 -0
- package/dist/cjs/context/index.js +19 -0
- package/dist/cjs/context/index.js.map +1 -0
- package/dist/cjs/core/entry.d.ts +30 -0
- package/dist/cjs/core/entry.d.ts.map +1 -0
- package/dist/cjs/core/entry.js +37 -0
- package/dist/cjs/core/entry.js.map +1 -0
- package/dist/cjs/core/index.d.ts +7 -0
- package/dist/cjs/core/index.d.ts.map +1 -0
- package/dist/cjs/core/index.js +24 -0
- package/dist/cjs/core/index.js.map +1 -0
- package/dist/cjs/core/level.d.ts +12 -0
- package/dist/cjs/core/level.d.ts.map +1 -0
- package/dist/cjs/core/level.js +31 -0
- package/dist/cjs/core/level.js.map +1 -0
- package/dist/cjs/core/logger.d.ts +271 -0
- package/dist/cjs/core/logger.d.ts.map +1 -0
- package/dist/cjs/core/logger.js +751 -0
- package/dist/cjs/core/logger.js.map +1 -0
- package/dist/cjs/core/printf.d.ts +34 -0
- package/dist/cjs/core/printf.d.ts.map +1 -0
- package/dist/cjs/core/printf.js +133 -0
- package/dist/cjs/core/printf.js.map +1 -0
- package/dist/cjs/index.d.ts +40 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +56 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/pipeline/filter.d.ts +10 -0
- package/dist/cjs/pipeline/filter.d.ts.map +1 -0
- package/dist/cjs/pipeline/filter.js +16 -0
- package/dist/cjs/pipeline/filter.js.map +1 -0
- package/dist/cjs/pipeline/formatter.d.ts +19 -0
- package/dist/cjs/pipeline/formatter.d.ts.map +1 -0
- package/dist/cjs/pipeline/formatter.js +183 -0
- package/dist/cjs/pipeline/formatter.js.map +1 -0
- package/dist/cjs/pipeline/index.d.ts +6 -0
- package/dist/cjs/pipeline/index.d.ts.map +1 -0
- package/dist/cjs/pipeline/index.js +22 -0
- package/dist/cjs/pipeline/index.js.map +1 -0
- package/dist/cjs/pipeline/pipeline.d.ts +45 -0
- package/dist/cjs/pipeline/pipeline.d.ts.map +1 -0
- package/dist/cjs/pipeline/pipeline.js +80 -0
- package/dist/cjs/pipeline/pipeline.js.map +1 -0
- package/dist/cjs/pipeline/processor.d.ts +67 -0
- package/dist/cjs/pipeline/processor.d.ts.map +1 -0
- package/dist/cjs/pipeline/processor.js +284 -0
- package/dist/cjs/pipeline/processor.js.map +1 -0
- package/dist/cjs/pipeline/sampler.d.ts +45 -0
- package/dist/cjs/pipeline/sampler.d.ts.map +1 -0
- package/dist/cjs/pipeline/sampler.js +62 -0
- package/dist/cjs/pipeline/sampler.js.map +1 -0
- package/dist/cjs/plugin/index.d.ts +4 -0
- package/dist/cjs/plugin/index.d.ts.map +1 -0
- package/dist/cjs/plugin/index.js +20 -0
- package/dist/cjs/plugin/index.js.map +1 -0
- package/dist/cjs/plugin/manager.d.ts +38 -0
- package/dist/cjs/plugin/manager.d.ts.map +1 -0
- package/dist/cjs/plugin/manager.js +79 -0
- package/dist/cjs/plugin/manager.js.map +1 -0
- package/dist/cjs/plugin/otel-trace.d.ts +19 -0
- package/dist/cjs/plugin/otel-trace.d.ts.map +1 -0
- package/dist/cjs/plugin/otel-trace.js +91 -0
- package/dist/cjs/plugin/otel-trace.js.map +1 -0
- package/dist/cjs/plugin/plugin.d.ts +41 -0
- package/dist/cjs/plugin/plugin.d.ts.map +1 -0
- package/dist/cjs/plugin/plugin.js +3 -0
- package/dist/cjs/plugin/plugin.js.map +1 -0
- package/dist/cjs/runtime/adapter.d.ts +81 -0
- package/dist/cjs/runtime/adapter.d.ts.map +1 -0
- package/dist/cjs/runtime/adapter.js +3 -0
- package/dist/cjs/runtime/adapter.js.map +1 -0
- package/dist/cjs/runtime/defaults.d.ts +27 -0
- package/dist/cjs/runtime/defaults.d.ts.map +1 -0
- package/dist/cjs/runtime/defaults.js +30 -0
- package/dist/cjs/runtime/defaults.js.map +1 -0
- package/dist/cjs/runtime/electron-binding.browser.d.ts +10 -0
- package/dist/cjs/runtime/electron-binding.browser.d.ts.map +1 -0
- package/dist/cjs/runtime/electron-binding.browser.js +18 -0
- package/dist/cjs/runtime/electron-binding.browser.js.map +1 -0
- package/dist/cjs/runtime/electron-binding.d.ts +24 -0
- package/dist/cjs/runtime/electron-binding.d.ts.map +1 -0
- package/dist/cjs/runtime/electron-binding.js +49 -0
- package/dist/cjs/runtime/electron-binding.js.map +1 -0
- package/dist/cjs/runtime/electron-lifecycle.d.ts +17 -0
- package/dist/cjs/runtime/electron-lifecycle.d.ts.map +1 -0
- package/dist/cjs/runtime/electron-lifecycle.js +47 -0
- package/dist/cjs/runtime/electron-lifecycle.js.map +1 -0
- package/dist/cjs/runtime/electron-main.d.ts +24 -0
- package/dist/cjs/runtime/electron-main.d.ts.map +1 -0
- package/dist/cjs/runtime/electron-main.js +102 -0
- package/dist/cjs/runtime/electron-main.js.map +1 -0
- package/dist/cjs/runtime/electron-renderer.d.ts +26 -0
- package/dist/cjs/runtime/electron-renderer.d.ts.map +1 -0
- package/dist/cjs/runtime/electron-renderer.js +33 -0
- package/dist/cjs/runtime/electron-renderer.js.map +1 -0
- package/dist/cjs/runtime/electron.d.ts +20 -0
- package/dist/cjs/runtime/electron.d.ts.map +1 -0
- package/dist/cjs/runtime/electron.js +27 -0
- package/dist/cjs/runtime/electron.js.map +1 -0
- package/dist/cjs/runtime/index.d.ts +21 -0
- package/dist/cjs/runtime/index.d.ts.map +1 -0
- package/dist/cjs/runtime/index.js +41 -0
- package/dist/cjs/runtime/index.js.map +1 -0
- package/dist/cjs/runtime/node.d.ts +27 -0
- package/dist/cjs/runtime/node.d.ts.map +1 -0
- package/dist/cjs/runtime/node.js +126 -0
- package/dist/cjs/runtime/node.js.map +1 -0
- package/dist/cjs/runtime/process-lifecycle.d.ts +13 -0
- package/dist/cjs/runtime/process-lifecycle.d.ts.map +1 -0
- package/dist/cjs/runtime/process-lifecycle.js +80 -0
- package/dist/cjs/runtime/process-lifecycle.js.map +1 -0
- package/dist/cjs/runtime/web-lifecycle.d.ts +13 -0
- package/dist/cjs/runtime/web-lifecycle.d.ts.map +1 -0
- package/dist/cjs/runtime/web-lifecycle.js +39 -0
- package/dist/cjs/runtime/web-lifecycle.js.map +1 -0
- package/dist/cjs/runtime/web.d.ts +14 -0
- package/dist/cjs/runtime/web.d.ts.map +1 -0
- package/dist/cjs/runtime/web.js +61 -0
- package/dist/cjs/runtime/web.js.map +1 -0
- package/dist/cjs/shims/index.browser.d.ts +26 -0
- package/dist/cjs/shims/index.browser.d.ts.map +1 -0
- package/dist/cjs/shims/index.browser.js +67 -0
- package/dist/cjs/shims/index.browser.js.map +1 -0
- package/dist/cjs/shims/index.d.ts +15 -0
- package/dist/cjs/shims/index.d.ts.map +1 -0
- package/dist/cjs/shims/index.js +39 -0
- package/dist/cjs/shims/index.js.map +1 -0
- package/dist/cjs/transport/cluster-ipc.d.ts +36 -0
- package/dist/cjs/transport/cluster-ipc.d.ts.map +1 -0
- package/dist/cjs/transport/cluster-ipc.js +76 -0
- package/dist/cjs/transport/cluster-ipc.js.map +1 -0
- package/dist/cjs/transport/console.d.ts +28 -0
- package/dist/cjs/transport/console.d.ts.map +1 -0
- package/dist/cjs/transport/console.js +48 -0
- package/dist/cjs/transport/console.js.map +1 -0
- package/dist/cjs/transport/electron-ipc.d.ts +69 -0
- package/dist/cjs/transport/electron-ipc.d.ts.map +1 -0
- package/dist/cjs/transport/electron-ipc.js +153 -0
- package/dist/cjs/transport/electron-ipc.js.map +1 -0
- package/dist/cjs/transport/file.d.ts +190 -0
- package/dist/cjs/transport/file.d.ts.map +1 -0
- package/dist/cjs/transport/file.js +666 -0
- package/dist/cjs/transport/file.js.map +1 -0
- package/dist/cjs/transport/index.d.ts +9 -0
- package/dist/cjs/transport/index.d.ts.map +1 -0
- package/dist/cjs/transport/index.js +25 -0
- package/dist/cjs/transport/index.js.map +1 -0
- package/dist/cjs/transport/live.d.ts +72 -0
- package/dist/cjs/transport/live.d.ts.map +1 -0
- package/dist/cjs/transport/live.js +104 -0
- package/dist/cjs/transport/live.js.map +1 -0
- package/dist/cjs/transport/otlp.d.ts +97 -0
- package/dist/cjs/transport/otlp.d.ts.map +1 -0
- package/dist/cjs/transport/otlp.js +194 -0
- package/dist/cjs/transport/otlp.js.map +1 -0
- package/dist/cjs/transport/rotating-file.d.ts +67 -0
- package/dist/cjs/transport/rotating-file.d.ts.map +1 -0
- package/dist/cjs/transport/rotating-file.js +179 -0
- package/dist/cjs/transport/rotating-file.js.map +1 -0
- package/dist/cjs/transport/transport.d.ts +35 -0
- package/dist/cjs/transport/transport.d.ts.map +1 -0
- package/dist/cjs/transport/transport.js +3 -0
- package/dist/cjs/transport/transport.js.map +1 -0
- package/dist/cjs/transport/worker-ipc.d.ts +43 -0
- package/dist/cjs/transport/worker-ipc.d.ts.map +1 -0
- package/dist/cjs/transport/worker-ipc.js +106 -0
- package/dist/cjs/transport/worker-ipc.js.map +1 -0
- package/dist/cjs/types.d.ts +72 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +45 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/context/async-context.browser.d.ts +16 -0
- package/dist/esm/context/async-context.browser.d.ts.map +1 -0
- package/dist/esm/context/async-context.browser.js +25 -0
- package/dist/esm/context/async-context.browser.js.map +1 -0
- package/dist/esm/context/async-context.d.ts +10 -0
- package/dist/esm/context/async-context.d.ts.map +1 -0
- package/dist/esm/context/async-context.js +33 -0
- package/dist/esm/context/async-context.js.map +1 -0
- package/dist/esm/context/context.d.ts +33 -0
- package/dist/esm/context/context.d.ts.map +1 -0
- package/dist/esm/context/context.js +52 -0
- package/dist/esm/context/context.js.map +1 -0
- package/dist/esm/context/index.d.ts +3 -0
- package/dist/esm/context/index.d.ts.map +1 -0
- package/dist/esm/context/index.js +3 -0
- package/dist/esm/context/index.js.map +1 -0
- package/dist/esm/core/entry.d.ts +30 -0
- package/dist/esm/core/entry.d.ts.map +1 -0
- package/dist/esm/core/entry.js +34 -0
- package/dist/esm/core/entry.js.map +1 -0
- package/dist/esm/core/index.d.ts +7 -0
- package/dist/esm/core/index.d.ts.map +1 -0
- package/dist/esm/core/index.js +6 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/core/level.d.ts +12 -0
- package/dist/esm/core/level.d.ts.map +1 -0
- package/dist/esm/core/level.js +25 -0
- package/dist/esm/core/level.js.map +1 -0
- package/dist/esm/core/logger.d.ts +271 -0
- package/dist/esm/core/logger.d.ts.map +1 -0
- package/dist/esm/core/logger.js +747 -0
- package/dist/esm/core/logger.js.map +1 -0
- package/dist/esm/core/printf.d.ts +34 -0
- package/dist/esm/core/printf.d.ts.map +1 -0
- package/dist/esm/core/printf.js +129 -0
- package/dist/esm/core/printf.js.map +1 -0
- package/dist/esm/index.d.ts +40 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +38 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/pipeline/filter.d.ts +10 -0
- package/dist/esm/pipeline/filter.d.ts.map +1 -0
- package/dist/esm/pipeline/filter.js +11 -0
- package/dist/esm/pipeline/filter.js.map +1 -0
- package/dist/esm/pipeline/formatter.d.ts +19 -0
- package/dist/esm/pipeline/formatter.d.ts.map +1 -0
- package/dist/esm/pipeline/formatter.js +179 -0
- package/dist/esm/pipeline/formatter.js.map +1 -0
- package/dist/esm/pipeline/index.d.ts +6 -0
- package/dist/esm/pipeline/index.d.ts.map +1 -0
- package/dist/esm/pipeline/index.js +6 -0
- package/dist/esm/pipeline/index.js.map +1 -0
- package/dist/esm/pipeline/pipeline.d.ts +45 -0
- package/dist/esm/pipeline/pipeline.d.ts.map +1 -0
- package/dist/esm/pipeline/pipeline.js +76 -0
- package/dist/esm/pipeline/pipeline.js.map +1 -0
- package/dist/esm/pipeline/processor.d.ts +67 -0
- package/dist/esm/pipeline/processor.d.ts.map +1 -0
- package/dist/esm/pipeline/processor.js +277 -0
- package/dist/esm/pipeline/processor.js.map +1 -0
- package/dist/esm/pipeline/sampler.d.ts +45 -0
- package/dist/esm/pipeline/sampler.d.ts.map +1 -0
- package/dist/esm/pipeline/sampler.js +59 -0
- package/dist/esm/pipeline/sampler.js.map +1 -0
- package/dist/esm/plugin/index.d.ts +4 -0
- package/dist/esm/plugin/index.d.ts.map +1 -0
- package/dist/esm/plugin/index.js +4 -0
- package/dist/esm/plugin/index.js.map +1 -0
- package/dist/esm/plugin/manager.d.ts +38 -0
- package/dist/esm/plugin/manager.d.ts.map +1 -0
- package/dist/esm/plugin/manager.js +75 -0
- package/dist/esm/plugin/manager.js.map +1 -0
- package/dist/esm/plugin/otel-trace.d.ts +19 -0
- package/dist/esm/plugin/otel-trace.d.ts.map +1 -0
- package/dist/esm/plugin/otel-trace.js +55 -0
- package/dist/esm/plugin/otel-trace.js.map +1 -0
- package/dist/esm/plugin/plugin.d.ts +41 -0
- package/dist/esm/plugin/plugin.d.ts.map +1 -0
- package/dist/esm/plugin/plugin.js +2 -0
- package/dist/esm/plugin/plugin.js.map +1 -0
- package/dist/esm/runtime/adapter.d.ts +81 -0
- package/dist/esm/runtime/adapter.d.ts.map +1 -0
- package/dist/esm/runtime/adapter.js +2 -0
- package/dist/esm/runtime/adapter.js.map +1 -0
- package/dist/esm/runtime/defaults.d.ts +27 -0
- package/dist/esm/runtime/defaults.d.ts.map +1 -0
- package/dist/esm/runtime/defaults.js +27 -0
- package/dist/esm/runtime/defaults.js.map +1 -0
- package/dist/esm/runtime/electron-binding.browser.d.ts +10 -0
- package/dist/esm/runtime/electron-binding.browser.d.ts.map +1 -0
- package/dist/esm/runtime/electron-binding.browser.js +13 -0
- package/dist/esm/runtime/electron-binding.browser.js.map +1 -0
- package/dist/esm/runtime/electron-binding.d.ts +24 -0
- package/dist/esm/runtime/electron-binding.d.ts.map +1 -0
- package/dist/esm/runtime/electron-binding.js +44 -0
- package/dist/esm/runtime/electron-binding.js.map +1 -0
- package/dist/esm/runtime/electron-lifecycle.d.ts +17 -0
- package/dist/esm/runtime/electron-lifecycle.d.ts.map +1 -0
- package/dist/esm/runtime/electron-lifecycle.js +44 -0
- package/dist/esm/runtime/electron-lifecycle.js.map +1 -0
- package/dist/esm/runtime/electron-main.d.ts +24 -0
- package/dist/esm/runtime/electron-main.d.ts.map +1 -0
- package/dist/esm/runtime/electron-main.js +99 -0
- package/dist/esm/runtime/electron-main.js.map +1 -0
- package/dist/esm/runtime/electron-renderer.d.ts +26 -0
- package/dist/esm/runtime/electron-renderer.d.ts.map +1 -0
- package/dist/esm/runtime/electron-renderer.js +30 -0
- package/dist/esm/runtime/electron-renderer.js.map +1 -0
- package/dist/esm/runtime/electron.d.ts +20 -0
- package/dist/esm/runtime/electron.d.ts.map +1 -0
- package/dist/esm/runtime/electron.js +21 -0
- package/dist/esm/runtime/electron.js.map +1 -0
- package/dist/esm/runtime/index.d.ts +21 -0
- package/dist/esm/runtime/index.d.ts.map +1 -0
- package/dist/esm/runtime/index.js +29 -0
- package/dist/esm/runtime/index.js.map +1 -0
- package/dist/esm/runtime/node.d.ts +27 -0
- package/dist/esm/runtime/node.d.ts.map +1 -0
- package/dist/esm/runtime/node.js +123 -0
- package/dist/esm/runtime/node.js.map +1 -0
- package/dist/esm/runtime/process-lifecycle.d.ts +13 -0
- package/dist/esm/runtime/process-lifecycle.d.ts.map +1 -0
- package/dist/esm/runtime/process-lifecycle.js +77 -0
- package/dist/esm/runtime/process-lifecycle.js.map +1 -0
- package/dist/esm/runtime/web-lifecycle.d.ts +13 -0
- package/dist/esm/runtime/web-lifecycle.d.ts.map +1 -0
- package/dist/esm/runtime/web-lifecycle.js +36 -0
- package/dist/esm/runtime/web-lifecycle.js.map +1 -0
- package/dist/esm/runtime/web.d.ts +14 -0
- package/dist/esm/runtime/web.d.ts.map +1 -0
- package/dist/esm/runtime/web.js +58 -0
- package/dist/esm/runtime/web.js.map +1 -0
- package/dist/esm/shims/index.browser.d.ts +26 -0
- package/dist/esm/shims/index.browser.d.ts.map +1 -0
- package/dist/esm/shims/index.browser.js +54 -0
- package/dist/esm/shims/index.browser.js.map +1 -0
- package/dist/esm/shims/index.d.ts +15 -0
- package/dist/esm/shims/index.d.ts.map +1 -0
- package/dist/esm/shims/index.js +22 -0
- package/dist/esm/shims/index.js.map +1 -0
- package/dist/esm/transport/cluster-ipc.d.ts +36 -0
- package/dist/esm/transport/cluster-ipc.d.ts.map +1 -0
- package/dist/esm/transport/cluster-ipc.js +71 -0
- package/dist/esm/transport/cluster-ipc.js.map +1 -0
- package/dist/esm/transport/console.d.ts +28 -0
- package/dist/esm/transport/console.d.ts.map +1 -0
- package/dist/esm/transport/console.js +44 -0
- package/dist/esm/transport/console.js.map +1 -0
- package/dist/esm/transport/electron-ipc.d.ts +69 -0
- package/dist/esm/transport/electron-ipc.d.ts.map +1 -0
- package/dist/esm/transport/electron-ipc.js +146 -0
- package/dist/esm/transport/electron-ipc.js.map +1 -0
- package/dist/esm/transport/file.d.ts +190 -0
- package/dist/esm/transport/file.d.ts.map +1 -0
- package/dist/esm/transport/file.js +662 -0
- package/dist/esm/transport/file.js.map +1 -0
- package/dist/esm/transport/index.d.ts +9 -0
- package/dist/esm/transport/index.d.ts.map +1 -0
- package/dist/esm/transport/index.js +9 -0
- package/dist/esm/transport/index.js.map +1 -0
- package/dist/esm/transport/live.d.ts +72 -0
- package/dist/esm/transport/live.d.ts.map +1 -0
- package/dist/esm/transport/live.js +100 -0
- package/dist/esm/transport/live.js.map +1 -0
- package/dist/esm/transport/otlp.d.ts +97 -0
- package/dist/esm/transport/otlp.d.ts.map +1 -0
- package/dist/esm/transport/otlp.js +190 -0
- package/dist/esm/transport/otlp.js.map +1 -0
- package/dist/esm/transport/rotating-file.d.ts +67 -0
- package/dist/esm/transport/rotating-file.d.ts.map +1 -0
- package/dist/esm/transport/rotating-file.js +175 -0
- package/dist/esm/transport/rotating-file.js.map +1 -0
- package/dist/esm/transport/transport.d.ts +35 -0
- package/dist/esm/transport/transport.d.ts.map +1 -0
- package/dist/esm/transport/transport.js +2 -0
- package/dist/esm/transport/transport.js.map +1 -0
- package/dist/esm/transport/worker-ipc.d.ts +43 -0
- package/dist/esm/transport/worker-ipc.d.ts.map +1 -0
- package/dist/esm/transport/worker-ipc.js +101 -0
- package/dist/esm/transport/worker-ipc.js.map +1 -0
- package/dist/esm/types.d.ts +72 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +39 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +128 -0
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
const types_js_1 = require("../types.js");
|
|
5
|
+
const index_js_1 = require("../runtime/index.js");
|
|
6
|
+
const pipeline_js_1 = require("../pipeline/pipeline.js");
|
|
7
|
+
const formatter_js_1 = require("../pipeline/formatter.js");
|
|
8
|
+
const index_js_2 = require("../plugin/index.js");
|
|
9
|
+
const index_js_3 = require("../context/index.js");
|
|
10
|
+
const entry_js_1 = require("./entry.js");
|
|
11
|
+
const printf_js_1 = require("./printf.js");
|
|
12
|
+
// Captured at module load — before `redirectConsole` can replace `console.*` —
|
|
13
|
+
// so the logger's own error reporting never recurses into itself.
|
|
14
|
+
const RAW_CONSOLE_ERROR = typeof console !== 'undefined' && typeof console.error === 'function'
|
|
15
|
+
? console.error.bind(console)
|
|
16
|
+
: () => { };
|
|
17
|
+
function pad(n, len) {
|
|
18
|
+
let s = String(n);
|
|
19
|
+
while (s.length < len)
|
|
20
|
+
s = `0${s}`;
|
|
21
|
+
return s;
|
|
22
|
+
}
|
|
23
|
+
// Reused across entries so the timestamp formatter never allocates a `Date`
|
|
24
|
+
// per log line (single-threaded: `setTime` + UTC reads run synchronously).
|
|
25
|
+
const TIME_DATE = new Date();
|
|
26
|
+
/**
|
|
27
|
+
* Format a millisecond epoch timestamp as an ISO-8601 UTC string
|
|
28
|
+
* (`YYYY-MM-DDTHH:mm:ss.sssZ`). A single `Date` is reused for the calendar
|
|
29
|
+
* decomposition, avoiding a per-entry allocation; only the string is built.
|
|
30
|
+
*/
|
|
31
|
+
function isoFromMs(ms) {
|
|
32
|
+
TIME_DATE.setTime(ms);
|
|
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
|
+
}
|
|
35
|
+
function escapeRegex(s) {
|
|
36
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
37
|
+
}
|
|
38
|
+
function toPattern(token) {
|
|
39
|
+
const body = token
|
|
40
|
+
.split('*')
|
|
41
|
+
.map((part) => escapeRegex(part))
|
|
42
|
+
.join('.*');
|
|
43
|
+
return { re: new RegExp(`^${body}$`) };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compile a namespace filter. `input` is a comma/space-separated list of glob
|
|
47
|
+
* patterns (with `*` wildcards); a leading `-` excludes. An empty input yields
|
|
48
|
+
* `undefined` (no filtering).
|
|
49
|
+
*/
|
|
50
|
+
function compileNamespaceFilter(input) {
|
|
51
|
+
if (!input || (Array.isArray(input) && input.length === 0))
|
|
52
|
+
return undefined;
|
|
53
|
+
const tokens = (Array.isArray(input) ? input : input.split(/[ ,]+/))
|
|
54
|
+
.map((t) => t.trim())
|
|
55
|
+
.filter(Boolean);
|
|
56
|
+
if (tokens.length === 0)
|
|
57
|
+
return undefined;
|
|
58
|
+
const includes = [];
|
|
59
|
+
const excludes = [];
|
|
60
|
+
for (const token of tokens) {
|
|
61
|
+
if (token.startsWith('-'))
|
|
62
|
+
excludes.push(toPattern(token.slice(1)));
|
|
63
|
+
else
|
|
64
|
+
includes.push(toPattern(token));
|
|
65
|
+
}
|
|
66
|
+
return { includes, excludes };
|
|
67
|
+
}
|
|
68
|
+
function matchesNamespace(scope, filter) {
|
|
69
|
+
if (!filter)
|
|
70
|
+
return true;
|
|
71
|
+
const s = scope ?? '';
|
|
72
|
+
for (const ex of filter.excludes) {
|
|
73
|
+
if (ex.re.test(s))
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
if (filter.includes.length === 0)
|
|
77
|
+
return true;
|
|
78
|
+
return filter.includes.some((inc) => inc.re.test(s));
|
|
79
|
+
}
|
|
80
|
+
/** Read an environment variable, returning `undefined` when unavailable/empty. */
|
|
81
|
+
function readEnvVar(name) {
|
|
82
|
+
if (typeof process === 'undefined' || !process.env)
|
|
83
|
+
return undefined;
|
|
84
|
+
const v = process.env[name];
|
|
85
|
+
return typeof v === 'string' && v.length > 0 ? v : undefined;
|
|
86
|
+
}
|
|
87
|
+
/** Narrowing guard for {@link ChildOptions}. */
|
|
88
|
+
function isChildOptions(o) {
|
|
89
|
+
return o.__child === true;
|
|
90
|
+
}
|
|
91
|
+
function getNodeProcess() {
|
|
92
|
+
if (typeof process === 'undefined' || typeof process.on !== 'function') {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
return process;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Unified logging facade. Produces {@link LogEntry} records, runs them through
|
|
99
|
+
* the {@link Pipeline} (filter + processors), lets {@link Plugin}s intercept,
|
|
100
|
+
* formats and writes them to {@link Transport}s.
|
|
101
|
+
*
|
|
102
|
+
* Instances are cheap to derive via {@link scope} or {@link child}; all
|
|
103
|
+
* children share the same transports, pipeline and plugins, but carry their own
|
|
104
|
+
* scope and context (captured from the parent at creation).
|
|
105
|
+
*/
|
|
106
|
+
class Logger {
|
|
107
|
+
constructor(options = {}) {
|
|
108
|
+
/**
|
|
109
|
+
* Sequences the async plugin-interception step so entries are processed in
|
|
110
|
+
* emit order. Transport writes fan out to their own per-transport queues
|
|
111
|
+
* (see `transportQueues`), so a slow/blocked transport can never stall the
|
|
112
|
+
* others or this front queue.
|
|
113
|
+
*/
|
|
114
|
+
this.dispatchQueue = Promise.resolve();
|
|
115
|
+
/** Independent async-write queue per transport. */
|
|
116
|
+
this.transportQueues = new Map();
|
|
117
|
+
this.destroyed = false;
|
|
118
|
+
this.processHandlersAttached = false;
|
|
119
|
+
this.errorHandlersAttached = false;
|
|
120
|
+
this._exiting = false;
|
|
121
|
+
/** True for loggers created via `scope`/`child` (share the parent's plumbing). */
|
|
122
|
+
this.isChild = false;
|
|
123
|
+
/** Tracks whether the local level was explicitly set via setLevel(). */
|
|
124
|
+
this.hasExplicitLocalLevel = false;
|
|
125
|
+
// ---- Emitting ----
|
|
126
|
+
this.trace = (message, ...args) => this.emit('trace', message, args);
|
|
127
|
+
this.debug = (message, ...args) => this.emit('debug', message, args);
|
|
128
|
+
this.info = (message, ...args) => this.emit('info', message, args);
|
|
129
|
+
this.warn = (message, ...args) => this.emit('warn', message, args);
|
|
130
|
+
this.error = (message, ...args) => this.emit('error', message, args);
|
|
131
|
+
this.fatal = (message, ...args) => this.emit('fatal', message, args);
|
|
132
|
+
// Lightweight child path: reuse the parent's runtime, pipeline, plugins,
|
|
133
|
+
// transports and namespace filter, skipping env reads, regex compilation
|
|
134
|
+
// and runtime detection entirely. This keeps `scope`/`child` (used per
|
|
135
|
+
// request, e.g. `logger.child({ requestId })`) near-zero allocation.
|
|
136
|
+
if (isChildOptions(options)) {
|
|
137
|
+
this.isChild = true;
|
|
138
|
+
this.initFromParent(options);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
this.runtime = options.runtime ?? (0, index_js_1.detectRuntime)();
|
|
142
|
+
const pipelineOpts = options.pipeline instanceof pipeline_js_1.Pipeline ? undefined : options.pipeline;
|
|
143
|
+
this.pipeline =
|
|
144
|
+
options.pipeline instanceof pipeline_js_1.Pipeline ? options.pipeline : new pipeline_js_1.Pipeline(pipelineOpts ?? {});
|
|
145
|
+
if (!(options.pipeline instanceof pipeline_js_1.Pipeline) && !pipelineOpts?.formatter) {
|
|
146
|
+
this.pipeline.setFormatter((0, formatter_js_1.createLineFormatter)());
|
|
147
|
+
}
|
|
148
|
+
this.plugins = options.plugins ?? new index_js_2.PluginManager(this.buildPluginContext());
|
|
149
|
+
this.transports = options.transports ?? this.runtime.defaultTransports();
|
|
150
|
+
this.context = options.context ?? (0, index_js_3.createContextStore)();
|
|
151
|
+
const envLevelName = options.levelEnvVar === null ? undefined : readEnvVar(options.levelEnvVar ?? 'LOG_LEVEL');
|
|
152
|
+
const levelInput = envLevelName && (0, types_js_1.isLogLevelName)(envLevelName) ? envLevelName : (options.level ?? 'info');
|
|
153
|
+
this.level = (0, types_js_1.normalizeLevel)(levelInput);
|
|
154
|
+
this.originalLevel = this.level;
|
|
155
|
+
this.scopeName = options.scope;
|
|
156
|
+
const nsInput = options.namespaceFilter ??
|
|
157
|
+
(options.namespaceEnvVar === null
|
|
158
|
+
? undefined
|
|
159
|
+
: readEnvVar(options.namespaceEnvVar ?? 'LOGRAIL_DEBUG'));
|
|
160
|
+
this.namespaceFilter = compileNamespaceFilter(nsInput);
|
|
161
|
+
// On the Electron main process, receive renderer logs over IPC.
|
|
162
|
+
if (this.runtime.attachReceiver) {
|
|
163
|
+
this.detachReceiver = this.runtime.attachReceiver((entry) => this.ingestEntry(entry));
|
|
164
|
+
this.runtime.onLevelCommand = (level) => {
|
|
165
|
+
this.peerLevel = level;
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (options.autoFlushOnExit)
|
|
169
|
+
this.attachExitHandlers();
|
|
170
|
+
this.onLoggerError = options.onError;
|
|
171
|
+
this.writeTimeoutMs = options.writeTimeoutMs ?? 5000;
|
|
172
|
+
this.exitFlushTimeoutMs = options.exitFlushTimeoutMs ?? 2000;
|
|
173
|
+
// Wire the pipeline/plugin error sinks into the unified handler.
|
|
174
|
+
this.pipeline.onError = (err, info) => this.reportError(info.phase, err, info.entry);
|
|
175
|
+
this.plugins.onError = (name, err, entry) => this.reportError('plugin', err, entry, name);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Initialise a lightweight child from its parent. Reuses the parent's
|
|
179
|
+
* runtime, pipeline, plugins, transports and namespace filter, and shares the
|
|
180
|
+
* parent's error handler config so no duplicate `onError` wiring (or duplicate
|
|
181
|
+
* IPC receiver registration) happens.
|
|
182
|
+
*/
|
|
183
|
+
initFromParent(opts) {
|
|
184
|
+
const parent = opts.parent;
|
|
185
|
+
this.parent = parent;
|
|
186
|
+
this.runtime = parent.runtime;
|
|
187
|
+
this.pipeline = parent.pipeline;
|
|
188
|
+
this.plugins = parent.plugins;
|
|
189
|
+
this.transports = parent.transports;
|
|
190
|
+
this.namespaceFilter = parent.namespaceFilter;
|
|
191
|
+
this.context = opts.context ?? (0, index_js_3.createContextStore)();
|
|
192
|
+
this.scopeName = opts.scope;
|
|
193
|
+
// Only a root logger owns the shared plugin error sink; children inherit it.
|
|
194
|
+
this.onLoggerError = parent.onLoggerError;
|
|
195
|
+
this.writeTimeoutMs = parent.writeTimeoutMs;
|
|
196
|
+
this.exitFlushTimeoutMs = parent.exitFlushTimeoutMs;
|
|
197
|
+
if (opts.levelOverride !== undefined)
|
|
198
|
+
this.levelOverride = opts.levelOverride;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Feed an externally produced {@link LogEntry} (e.g. received from a renderer
|
|
202
|
+
* process over IPC) into the pipeline/transports. Subject to the configured
|
|
203
|
+
* level and plugins, then written via the active transports.
|
|
204
|
+
*/
|
|
205
|
+
ingestEntry(entry) {
|
|
206
|
+
if (this.destroyed)
|
|
207
|
+
return;
|
|
208
|
+
if (entry.level < this.getLevel())
|
|
209
|
+
return;
|
|
210
|
+
if (!matchesNamespace(entry.scope, this.namespaceFilter))
|
|
211
|
+
return;
|
|
212
|
+
this.dispatch(entry);
|
|
213
|
+
}
|
|
214
|
+
// ---- Level ----
|
|
215
|
+
getLevel() {
|
|
216
|
+
if (this.levelOverride !== undefined)
|
|
217
|
+
return this.levelOverride;
|
|
218
|
+
if (this.parent)
|
|
219
|
+
return this.parent.getLevel();
|
|
220
|
+
// If local level was explicitly set (via constructor or setLevel), use it.
|
|
221
|
+
// Otherwise fall back to the cached peer level.
|
|
222
|
+
if (this.hasExplicitLocalLevel)
|
|
223
|
+
return this.level;
|
|
224
|
+
if (this.peerLevel !== undefined)
|
|
225
|
+
return this.peerLevel;
|
|
226
|
+
return this.level;
|
|
227
|
+
}
|
|
228
|
+
setLevel(level) {
|
|
229
|
+
const v = (0, types_js_1.normalizeLevel)(level);
|
|
230
|
+
if (this.parent) {
|
|
231
|
+
this.levelOverride = v;
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
this.level = v;
|
|
235
|
+
this.hasExplicitLocalLevel = true;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Register a callback invoked when a cross-process level command is received
|
|
240
|
+
* (e.g. from a renderer, worker, or cluster peer). Called automatically by
|
|
241
|
+
* the runtime when {@link RuntimeAdapter.onLevelCommand} is wired up; most
|
|
242
|
+
* users should not call this directly.
|
|
243
|
+
*/
|
|
244
|
+
setOnLevelCommand(cb) {
|
|
245
|
+
this.runtime.onLevelCommand = cb;
|
|
246
|
+
}
|
|
247
|
+
// ---- Context ----
|
|
248
|
+
setContext(key, value) {
|
|
249
|
+
this.context.set(key, value);
|
|
250
|
+
}
|
|
251
|
+
mergeContext(values) {
|
|
252
|
+
this.context.merge(values);
|
|
253
|
+
}
|
|
254
|
+
// ---- Transports ----
|
|
255
|
+
addTransport(transport) {
|
|
256
|
+
this.transports.push(transport);
|
|
257
|
+
this.plugins.notifyTransport(transport);
|
|
258
|
+
}
|
|
259
|
+
removeTransport(name) {
|
|
260
|
+
const removed = this.transports.filter((t) => t.name === name);
|
|
261
|
+
for (const t of removed)
|
|
262
|
+
this.transportQueues.delete(t);
|
|
263
|
+
this.transports = this.transports.filter((t) => t.name !== name);
|
|
264
|
+
}
|
|
265
|
+
/** Unregister a plugin by name at runtime. */
|
|
266
|
+
unregisterPlugin(name) {
|
|
267
|
+
this.plugins.unregister(name);
|
|
268
|
+
}
|
|
269
|
+
/** Whether a plugin with the given name is currently registered. */
|
|
270
|
+
hasPlugin(name) {
|
|
271
|
+
return this.plugins.has(name);
|
|
272
|
+
}
|
|
273
|
+
/** Access the processing pipeline to add/remove filters & processors or change the formatter at runtime. */
|
|
274
|
+
getPipeline() {
|
|
275
|
+
return this.pipeline;
|
|
276
|
+
}
|
|
277
|
+
/** Build the {@link PluginContext} handed to plugins so they can reconfigure the logger. */
|
|
278
|
+
buildPluginContext() {
|
|
279
|
+
return {
|
|
280
|
+
addTransport: (t) => this.addTransport(t),
|
|
281
|
+
removeTransport: (n) => this.removeTransport(n),
|
|
282
|
+
pipeline: this.pipeline,
|
|
283
|
+
use: (p) => this.use(p),
|
|
284
|
+
unregisterPlugin: (n) => this.unregisterPlugin(n),
|
|
285
|
+
logger: this,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
getTransports() {
|
|
289
|
+
return this.transports;
|
|
290
|
+
}
|
|
291
|
+
// ---- Plugins ----
|
|
292
|
+
use(plugin) {
|
|
293
|
+
return this.plugins.register(plugin);
|
|
294
|
+
}
|
|
295
|
+
// ---- Scoped loggers ----
|
|
296
|
+
/**
|
|
297
|
+
* Derive a scoped child logger. The child shares this logger's transports,
|
|
298
|
+
* pipeline, plugins and runtime, inherits its scope (joined with `:`) and
|
|
299
|
+
* context (captured from the parent at creation), and may carry extra
|
|
300
|
+
* context. The level is inherited live from the parent (see {@link child})
|
|
301
|
+
* unless overridden via `setLevel`.
|
|
302
|
+
*
|
|
303
|
+
* Construction is lightweight: no environment reads, regex compilation or
|
|
304
|
+
* runtime detection is performed — the child reuses this logger's plumbing.
|
|
305
|
+
*/
|
|
306
|
+
scope(scope, context) {
|
|
307
|
+
const childScope = this.scopeName ? `${this.scopeName}:${scope}` : scope;
|
|
308
|
+
const childContext = this.context.child();
|
|
309
|
+
if (context) {
|
|
310
|
+
childContext.merge(context);
|
|
311
|
+
}
|
|
312
|
+
return new Logger({
|
|
313
|
+
__child: true,
|
|
314
|
+
parent: this,
|
|
315
|
+
scope: childScope,
|
|
316
|
+
context: childContext,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Derive a child logger that shares this logger's transports, pipeline,
|
|
321
|
+
* plugins and runtime. The child:
|
|
322
|
+
* - merges `options.context` on top of the parent's context (captured at
|
|
323
|
+
* creation),
|
|
324
|
+
* - inherits the parent's scope,
|
|
325
|
+
* - inherits the parent's level live, unless `options.level` overrides it
|
|
326
|
+
* (the override also applies to any further descendants).
|
|
327
|
+
*
|
|
328
|
+
* This is the canonical "child logger" (à la `pino.child`), ideal for
|
|
329
|
+
* per-request context such as `logger.child({ requestId: id })`. Construction
|
|
330
|
+
* is lightweight — see {@link scope}.
|
|
331
|
+
*/
|
|
332
|
+
child(options = {}) {
|
|
333
|
+
const childContext = this.context.child();
|
|
334
|
+
if (options.context) {
|
|
335
|
+
childContext.merge(options.context);
|
|
336
|
+
}
|
|
337
|
+
return new Logger({
|
|
338
|
+
__child: true,
|
|
339
|
+
parent: this,
|
|
340
|
+
scope: this.scopeName,
|
|
341
|
+
context: childContext,
|
|
342
|
+
levelOverride: options.level !== undefined ? (0, types_js_1.normalizeLevel)(options.level) : undefined,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
emit(levelName, message, args) {
|
|
346
|
+
if (this.destroyed)
|
|
347
|
+
return;
|
|
348
|
+
const levelValue = types_js_1.LOG_LEVELS[levelName];
|
|
349
|
+
if (levelValue < this.getLevel())
|
|
350
|
+
return;
|
|
351
|
+
if (!matchesNamespace(this.scopeName, this.namespaceFilter))
|
|
352
|
+
return;
|
|
353
|
+
const entry = this.buildEntry(levelName, levelValue, message, args);
|
|
354
|
+
const processed = this.pipeline.process(entry);
|
|
355
|
+
if (!processed)
|
|
356
|
+
return;
|
|
357
|
+
this.dispatch(processed);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Route a processed entry to the transports. When no plugin intercepts
|
|
361
|
+
* entries we can write synchronously and skip the per-call Promise + write
|
|
362
|
+
* queue entirely (the common case); the async path is only used when a plugin
|
|
363
|
+
* hook or an async transport needs it.
|
|
364
|
+
*/
|
|
365
|
+
dispatch(entry) {
|
|
366
|
+
if (this.plugins.hasEntryInterceptors()) {
|
|
367
|
+
const p = this.plugins.intercept(entry).then((intercepted) => {
|
|
368
|
+
if (intercepted)
|
|
369
|
+
this.writeToTransports(intercepted);
|
|
370
|
+
});
|
|
371
|
+
this.dispatchQueue = this.dispatchQueue
|
|
372
|
+
.then(() => p)
|
|
373
|
+
.catch((err) => this.reportError('plugin', err));
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
this.writeToTransports(entry);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Report an internal error without throwing. Routes to the user-supplied
|
|
380
|
+
* `onError` handler, falling back to the native `console.error` (deliberately
|
|
381
|
+
* not the redirected one, to avoid recursion).
|
|
382
|
+
*/
|
|
383
|
+
reportError(phase, err, entry, source) {
|
|
384
|
+
if (this.onLoggerError) {
|
|
385
|
+
this.onLoggerError(err, { phase, entry, source });
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
RAW_CONSOLE_ERROR(`[lograil]${source ? ` (${source})` : ''} ${phase} error:`, err);
|
|
389
|
+
}
|
|
390
|
+
buildEntry(levelName, levelValue, message, args) {
|
|
391
|
+
let msg;
|
|
392
|
+
let error;
|
|
393
|
+
let rest = args;
|
|
394
|
+
if (message instanceof Error) {
|
|
395
|
+
error = message;
|
|
396
|
+
msg = message.message;
|
|
397
|
+
}
|
|
398
|
+
else if (typeof message === 'string') {
|
|
399
|
+
// `printf`-style: `logger.info('user %s', name)`. Only enter the format
|
|
400
|
+
// path when at least one argument is present and a legal specifier
|
|
401
|
+
// exists, so the dominant `info('msg', {obj})` pattern stays on the
|
|
402
|
+
// zero-format fast path and literal `%` in messages is preserved.
|
|
403
|
+
if (args.length > 0 && (0, printf_js_1.hasPrintfSpecifier)(message)) {
|
|
404
|
+
const [formatted, ...restArgs] = (0, printf_js_1.formatMessage)(message, args);
|
|
405
|
+
msg = formatted;
|
|
406
|
+
rest = restArgs;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
msg = message;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
// Non-string / non-Error first argument (e.g. an object): preserve it as
|
|
414
|
+
// structured data instead of coercing to "[object Object]".
|
|
415
|
+
msg = '';
|
|
416
|
+
rest = [message, ...args];
|
|
417
|
+
}
|
|
418
|
+
if (!error) {
|
|
419
|
+
error = rest.find((a) => a instanceof Error);
|
|
420
|
+
}
|
|
421
|
+
const now = this.runtime.now();
|
|
422
|
+
const ts = typeof now === 'number' ? now : new Date(now).getTime();
|
|
423
|
+
// Merge the ambient (request-scoped) context on top of this logger's own
|
|
424
|
+
// context. Reading it is O(1); we only clone when one side is non-empty.
|
|
425
|
+
const base = this.context.get();
|
|
426
|
+
const ambient = index_js_3.asyncContext.get();
|
|
427
|
+
// NB: never hand the live AsyncLocalStorage store directly to the entry —
|
|
428
|
+
// the ambient object is shared across the async scope, so a later mutation
|
|
429
|
+
// (or `freezeEntry` below) would corrupt every entry in that scope. When
|
|
430
|
+
// ambient is the only source we clone it into a per-entry object; otherwise
|
|
431
|
+
// we reuse the frozen EMPTY_RECORD sentinel so the hot path allocates
|
|
432
|
+
// nothing.
|
|
433
|
+
const context = ambient === index_js_3.EMPTY_RECORD
|
|
434
|
+
? base
|
|
435
|
+
: (0, index_js_3.isEmptyRecord)(base)
|
|
436
|
+
? { ...ambient }
|
|
437
|
+
: { ...base, ...ambient };
|
|
438
|
+
return {
|
|
439
|
+
level: levelValue,
|
|
440
|
+
levelName,
|
|
441
|
+
message: msg,
|
|
442
|
+
args: rest,
|
|
443
|
+
timestamp: ts,
|
|
444
|
+
time: isoFromMs(ts),
|
|
445
|
+
scope: this.scopeName,
|
|
446
|
+
pid: this.runtime.pid(),
|
|
447
|
+
context,
|
|
448
|
+
// Shared frozen empty record (no per-call allocation); `freezeEntry`
|
|
449
|
+
// recognises it as a sentinel and skips cloning/freezing.
|
|
450
|
+
metadata: index_js_3.EMPTY_RECORD,
|
|
451
|
+
error,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
writeToTransports(entry) {
|
|
455
|
+
// Freeze at the single fan-out choke point so every transport, formatter and
|
|
456
|
+
// plugin reads an immutable entry and can safely share it by reference
|
|
457
|
+
// (zero-copy within the process). Idempotent.
|
|
458
|
+
const frozen = (0, entry_js_1.freezeEntry)(entry);
|
|
459
|
+
for (const transport of this.transports) {
|
|
460
|
+
const tl = transport.level;
|
|
461
|
+
if (tl !== undefined && frozen.level < (0, types_js_1.normalizeLevel)(tl))
|
|
462
|
+
continue;
|
|
463
|
+
const formatter = transport.formatter ?? this.pipeline.getFormatter();
|
|
464
|
+
let formatted;
|
|
465
|
+
try {
|
|
466
|
+
formatted = formatter(frozen);
|
|
467
|
+
}
|
|
468
|
+
catch (err) {
|
|
469
|
+
this.reportError('formatter', err, frozen);
|
|
470
|
+
formatted = `[formatting failed] ${frozen.message}`;
|
|
471
|
+
}
|
|
472
|
+
const onErr = transport.onError;
|
|
473
|
+
try {
|
|
474
|
+
const result = transport.write(frozen, String(formatted));
|
|
475
|
+
if (result && typeof result.then === 'function') {
|
|
476
|
+
const guarded = this.guardWrite(result);
|
|
477
|
+
// Chain onto THIS transport's own queue, not a shared one, so a stalled
|
|
478
|
+
// write here cannot block other transports (or the front dispatch queue).
|
|
479
|
+
const prev = this.transportQueues.get(transport) ?? Promise.resolve();
|
|
480
|
+
const next = prev
|
|
481
|
+
.then(() => guarded)
|
|
482
|
+
.catch((err) => this.reportTransportError(err, frozen, onErr));
|
|
483
|
+
this.transportQueues.set(transport, next);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
catch (err) {
|
|
487
|
+
this.reportTransportError(err, frozen, onErr);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
/** Await a transport's async `write`, but never let it stall the queue. */
|
|
492
|
+
guardWrite(p) {
|
|
493
|
+
if (!this.writeTimeoutMs)
|
|
494
|
+
return p;
|
|
495
|
+
let timer;
|
|
496
|
+
const timeout = new Promise((_, reject) => {
|
|
497
|
+
timer = setTimeout(() => reject(new Error(`transport write timed out after ${this.writeTimeoutMs}ms`)), this.writeTimeoutMs);
|
|
498
|
+
});
|
|
499
|
+
return Promise.race([p, timeout]).finally(() => {
|
|
500
|
+
if (timer)
|
|
501
|
+
clearTimeout(timer);
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
/** Await a transport's async `flush`, but never let it stall teardown. */
|
|
505
|
+
guardFlush(p) {
|
|
506
|
+
if (!this.writeTimeoutMs)
|
|
507
|
+
return Promise.resolve();
|
|
508
|
+
const result = p();
|
|
509
|
+
if (!result || typeof result.then !== 'function')
|
|
510
|
+
return Promise.resolve();
|
|
511
|
+
return this.guardWrite(result);
|
|
512
|
+
}
|
|
513
|
+
/** Surface a transport failure via the transport's hook, else the global handler. */
|
|
514
|
+
reportTransportError(err, entry, onErr) {
|
|
515
|
+
if (onErr)
|
|
516
|
+
onErr(err, entry);
|
|
517
|
+
else
|
|
518
|
+
this.reportError('transport', err, entry);
|
|
519
|
+
}
|
|
520
|
+
// ---- Lifecycle ----
|
|
521
|
+
async flush() {
|
|
522
|
+
// Let in-flight interception finish so every scheduled write has been
|
|
523
|
+
// enqueued onto its transport's own queue.
|
|
524
|
+
await this.dispatchQueue;
|
|
525
|
+
// Aggregate all per-transport async-write queues. `allSettled` means a
|
|
526
|
+
// rejected/errored transport queue never rejects flush; a stalled one is
|
|
527
|
+
// bounded by `writeTimeoutMs` via `guardWrite`.
|
|
528
|
+
await Promise.allSettled(Array.from(this.transportQueues.values()));
|
|
529
|
+
// Flush each transport's internal buffers with the same timeout guard so
|
|
530
|
+
// a stalled flush can never hang shutdown or caller code.
|
|
531
|
+
await Promise.allSettled(this.transports.map((t) => (t.flush ? this.guardFlush(t.flush.bind(t)) : Promise.resolve())));
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Flush, but never wait longer than `ms`. Resolves (does not reject) once the
|
|
535
|
+
* flush settles or the timeout elapses, so callers can always proceed (e.g.
|
|
536
|
+
* exit the process) without risking a hang on a stalled transport.
|
|
537
|
+
*/
|
|
538
|
+
flushWithTimeout(ms) {
|
|
539
|
+
if (!ms)
|
|
540
|
+
return this.flush();
|
|
541
|
+
return new Promise((resolve) => {
|
|
542
|
+
let settled = false;
|
|
543
|
+
const done = () => {
|
|
544
|
+
if (settled)
|
|
545
|
+
return;
|
|
546
|
+
settled = true;
|
|
547
|
+
resolve();
|
|
548
|
+
};
|
|
549
|
+
const timer = setTimeout(done, ms);
|
|
550
|
+
if (typeof timer.unref === 'function')
|
|
551
|
+
timer.unref();
|
|
552
|
+
this.flush().then(done, done);
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
/** Set the max time (ms) to flush on process exit before giving up. */
|
|
556
|
+
setExitFlushTimeout(ms) {
|
|
557
|
+
if (Number.isFinite(ms) && ms >= 0)
|
|
558
|
+
this.exitFlushTimeoutMs = ms;
|
|
559
|
+
return this;
|
|
560
|
+
}
|
|
561
|
+
/** Get the current exit-flush timeout (ms). */
|
|
562
|
+
getExitFlushTimeout() {
|
|
563
|
+
return this.exitFlushTimeoutMs;
|
|
564
|
+
}
|
|
565
|
+
// ---- Process integration ----
|
|
566
|
+
/**
|
|
567
|
+
* Register `beforeExit` / `SIGINT` / `SIGTERM` handlers that flush the logger
|
|
568
|
+
* before the process leaves. On `SIGINT` / `SIGTERM` the process exits (130 /
|
|
569
|
+
* 143) after the flush completes. No-op outside Node. Idempotent.
|
|
570
|
+
*/
|
|
571
|
+
attachExitHandlers() {
|
|
572
|
+
if (this.processHandlersAttached)
|
|
573
|
+
return;
|
|
574
|
+
// Prefer runtime-provided lifecycle hooks so the logger stays
|
|
575
|
+
// runtime-agnostic and the runtime owns process/window event wiring and
|
|
576
|
+
// exit semantics. Falls back to a direct `process` binding below for
|
|
577
|
+
// adapters that don't supply lifecycle hooks (e.g. custom test runtimes).
|
|
578
|
+
const lc = this.runtime.lifecycle;
|
|
579
|
+
if (lc) {
|
|
580
|
+
const ms = this.exitFlushTimeoutMs;
|
|
581
|
+
const detach = lc.onFlushBeforeExit(() => {
|
|
582
|
+
void this.flushWithTimeout(ms);
|
|
583
|
+
});
|
|
584
|
+
const prev = this.removeProcessHandlers;
|
|
585
|
+
this.removeProcessHandlers = () => {
|
|
586
|
+
prev?.();
|
|
587
|
+
detach();
|
|
588
|
+
};
|
|
589
|
+
this.processHandlersAttached = true;
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
const proc = getNodeProcess();
|
|
593
|
+
if (!proc)
|
|
594
|
+
return;
|
|
595
|
+
const ms = this.exitFlushTimeoutMs;
|
|
596
|
+
// On normal exit the event loop is about to empty: flush pending writes.
|
|
597
|
+
// `beforeExit` re-fires as long as async writes keep the loop alive, so the
|
|
598
|
+
// queue keeps draining until empty (bounded by `ms` if a sink stalls).
|
|
599
|
+
const onBeforeExit = () => {
|
|
600
|
+
void this.flushWithTimeout(ms);
|
|
601
|
+
};
|
|
602
|
+
// On a signal, flush what we can, then terminate — but never hang shutdown
|
|
603
|
+
// on a stalled transport (the timeout guarantees we still exit).
|
|
604
|
+
const onSignal = (code) => {
|
|
605
|
+
if (this._exiting)
|
|
606
|
+
return;
|
|
607
|
+
this._exiting = true;
|
|
608
|
+
void this.flushWithTimeout(ms).finally(() => {
|
|
609
|
+
try {
|
|
610
|
+
proc.exit(code);
|
|
611
|
+
}
|
|
612
|
+
catch {
|
|
613
|
+
/* ignore */
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
};
|
|
617
|
+
const onSigInt = () => onSignal(130);
|
|
618
|
+
const onSigTerm = () => onSignal(143);
|
|
619
|
+
proc.on('beforeExit', onBeforeExit);
|
|
620
|
+
proc.on('SIGINT', onSigInt);
|
|
621
|
+
proc.on('SIGTERM', onSigTerm);
|
|
622
|
+
this.processHandlersAttached = true;
|
|
623
|
+
const prev = this.removeProcessHandlers;
|
|
624
|
+
this.removeProcessHandlers = () => {
|
|
625
|
+
prev?.();
|
|
626
|
+
proc.removeListener('beforeExit', onBeforeExit);
|
|
627
|
+
proc.removeListener('SIGINT', onSigInt);
|
|
628
|
+
proc.removeListener('SIGTERM', onSigTerm);
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Forward `uncaughtException` and `unhandledRejection` to the logger (at
|
|
633
|
+
* `fatal` level) and exit afterwards, so crashes are recorded before the
|
|
634
|
+
* process dies. No-op outside Node. Idempotent.
|
|
635
|
+
*/
|
|
636
|
+
watchUncaughtErrors() {
|
|
637
|
+
if (this.errorHandlersAttached)
|
|
638
|
+
return;
|
|
639
|
+
// Delegate to the runtime's lifecycle hooks when present (see
|
|
640
|
+
// `attachExitHandlers` for the rationale). The hooks own the `process`
|
|
641
|
+
// events and the post-flush `exit(1)`; we only provide the fatal log +
|
|
642
|
+
// bounded flush. Runtimes without an `onUncaughtError` hook (e.g. web)
|
|
643
|
+
// fall back to the direct `process` binding below, which is a no-op there.
|
|
644
|
+
const lc = this.runtime.lifecycle;
|
|
645
|
+
if (lc?.onUncaughtError) {
|
|
646
|
+
const ms = this.exitFlushTimeoutMs;
|
|
647
|
+
const detach = lc.onUncaughtError((err) => {
|
|
648
|
+
this.fatal(err);
|
|
649
|
+
return this.flushWithTimeout(ms);
|
|
650
|
+
});
|
|
651
|
+
const prev = this.removeProcessHandlers;
|
|
652
|
+
this.removeProcessHandlers = () => {
|
|
653
|
+
prev?.();
|
|
654
|
+
detach();
|
|
655
|
+
};
|
|
656
|
+
this.errorHandlersAttached = true;
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
const proc = getNodeProcess();
|
|
660
|
+
if (!proc)
|
|
661
|
+
return;
|
|
662
|
+
const onUncaught = (err) => {
|
|
663
|
+
this.fatal(err);
|
|
664
|
+
void this.flushWithTimeout(this.exitFlushTimeoutMs).finally(() => proc.exit(1));
|
|
665
|
+
};
|
|
666
|
+
const onRejection = (reason) => {
|
|
667
|
+
this.fatal(reason);
|
|
668
|
+
void this.flushWithTimeout(this.exitFlushTimeoutMs).finally(() => proc.exit(1));
|
|
669
|
+
};
|
|
670
|
+
proc.on('uncaughtException', onUncaught);
|
|
671
|
+
proc.on('unhandledRejection', onRejection);
|
|
672
|
+
this.errorHandlersAttached = true;
|
|
673
|
+
const prev = this.removeProcessHandlers;
|
|
674
|
+
this.removeProcessHandlers = () => {
|
|
675
|
+
prev?.();
|
|
676
|
+
proc.removeListener('uncaughtException', onUncaught);
|
|
677
|
+
proc.removeListener('unhandledRejection', onRejection);
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Route `console.*` calls through this logger, so third-party `console.log`
|
|
682
|
+
* output is captured into the structured pipeline. The native console output
|
|
683
|
+
* is suppressed for those calls (the logger's own transports produce the
|
|
684
|
+
* visible output); if logging throws, the native console is used as a
|
|
685
|
+
* fallback. Returns a function that restores the original `console`.
|
|
686
|
+
*/
|
|
687
|
+
redirectConsole() {
|
|
688
|
+
if (typeof console === 'undefined')
|
|
689
|
+
return () => { };
|
|
690
|
+
const routes = [
|
|
691
|
+
['log', 'info'],
|
|
692
|
+
['info', 'info'],
|
|
693
|
+
['debug', 'debug'],
|
|
694
|
+
['warn', 'warn'],
|
|
695
|
+
['error', 'error'],
|
|
696
|
+
['trace', 'trace'],
|
|
697
|
+
];
|
|
698
|
+
const originals = {};
|
|
699
|
+
for (const [method, level] of routes) {
|
|
700
|
+
const original = console[method]?.bind(console);
|
|
701
|
+
if (!original)
|
|
702
|
+
continue;
|
|
703
|
+
originals[method] = original;
|
|
704
|
+
console[method] = (...args) => {
|
|
705
|
+
try {
|
|
706
|
+
this[level](...args);
|
|
707
|
+
}
|
|
708
|
+
catch {
|
|
709
|
+
original(...args);
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
return () => {
|
|
714
|
+
for (const key of Object.keys(originals)) {
|
|
715
|
+
console[key] = originals[key];
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
async destroy() {
|
|
720
|
+
this.destroyed = true;
|
|
721
|
+
// Only a root logger owns the shared resources (process handlers, plugins,
|
|
722
|
+
// transports, the IPC receiver). A child shares them with its parent and
|
|
723
|
+
// must not tear them down — destroying a child used to silently break the
|
|
724
|
+
// parent's transports and plugins.
|
|
725
|
+
if (this.isChild) {
|
|
726
|
+
this.transportQueues.clear();
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
this.removeProcessHandlers?.();
|
|
730
|
+
// Flush pending writes before tearing down transports, so buffered logs
|
|
731
|
+
// are not lost. Bounded by the exit-flush timeout so a stalled sink can
|
|
732
|
+
// never hang teardown.
|
|
733
|
+
await this.flushWithTimeout(this.exitFlushTimeoutMs).catch(() => { });
|
|
734
|
+
await this.plugins.destroy().catch(() => { });
|
|
735
|
+
this.detachReceiver?.();
|
|
736
|
+
this.peerLevel = undefined;
|
|
737
|
+
if (this.originalLevel !== undefined) {
|
|
738
|
+
this.level = this.originalLevel;
|
|
739
|
+
this.hasExplicitLocalLevel = false;
|
|
740
|
+
}
|
|
741
|
+
for (const transport of this.transports) {
|
|
742
|
+
if (transport.close) {
|
|
743
|
+
await Promise.resolve(transport.close()).catch(() => { });
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
this.transportQueues.clear();
|
|
747
|
+
this.dispatchQueue = Promise.resolve();
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
exports.Logger = Logger;
|
|
751
|
+
//# sourceMappingURL=logger.js.map
|