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,666 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileTransport = void 0;
|
|
4
|
+
const index_js_1 = require("../shims/index.js");
|
|
5
|
+
const index_js_2 = require("../shims/index.js");
|
|
6
|
+
const index_js_3 = require("../shims/index.js");
|
|
7
|
+
const formatter_js_1 = require("../pipeline/formatter.js");
|
|
8
|
+
function timeStamp(d, unit) {
|
|
9
|
+
const y = d.getFullYear();
|
|
10
|
+
const m = String(d.getMonth() + 1).padStart(2, '0');
|
|
11
|
+
const day = String(d.getDate()).padStart(2, '0');
|
|
12
|
+
if (unit === 'day')
|
|
13
|
+
return `${y}-${m}-${day}`;
|
|
14
|
+
const h = String(d.getHours()).padStart(2, '0');
|
|
15
|
+
return `${y}-${m}-${day}-${h}`;
|
|
16
|
+
}
|
|
17
|
+
// ---- shared helpers -------------------------------------------------------
|
|
18
|
+
/** Best-effort cap: delete the oldest bucket/generation files beyond `maxFiles`.
|
|
19
|
+
* Only touches files the transport has explicitly created (tracked in `owned`).
|
|
20
|
+
* When `exclude` is provided, files matching its basename are also kept (used
|
|
21
|
+
* to protect the just-rotated-away file so it survives until the next bucket). */
|
|
22
|
+
async function trimRing(dir, appName, ext, maxFiles, owned, exclude) {
|
|
23
|
+
// maxFiles<=1 → no cap configured; skip trimming.
|
|
24
|
+
if (maxFiles <= 1)
|
|
25
|
+
return;
|
|
26
|
+
const keep = maxFiles - 1;
|
|
27
|
+
const excludeName = exclude ? (0, index_js_2.basename)(exclude) : undefined;
|
|
28
|
+
try {
|
|
29
|
+
const backups = (await (0, index_js_1.readdir)(dir))
|
|
30
|
+
.filter((f) => owned.has(f) &&
|
|
31
|
+
f !== `${appName}.${ext}` &&
|
|
32
|
+
(excludeName === undefined || f !== excludeName))
|
|
33
|
+
.sort();
|
|
34
|
+
const excess = backups.length - keep;
|
|
35
|
+
for (let i = 0; i < excess; i++) {
|
|
36
|
+
const toDelete = backups[i];
|
|
37
|
+
await (0, index_js_1.rm)((0, index_js_2.join)(dir, toDelete), { force: true }).catch(() => { });
|
|
38
|
+
owned.delete(toDelete);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
/* ignore */
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Best-effort cap that counts by **time buckets** (stamps) rather than files.
|
|
46
|
+
* Groups owned files by their timestamp stamp, then deletes the oldest
|
|
47
|
+
* complete bucket(s) when the number of distinct stamps exceeds `maxFiles`.
|
|
48
|
+
* This is the correct trimming strategy for `rotate-time` with `maxSize`,
|
|
49
|
+
* where a single bucket may produce multiple seq-numbered files. */
|
|
50
|
+
async function trimTimeRing(dir, appName, ext, maxFiles, owned) {
|
|
51
|
+
if (maxFiles <= 1)
|
|
52
|
+
return;
|
|
53
|
+
const prefix = `${appName}.`;
|
|
54
|
+
const suffix = `.${ext}`;
|
|
55
|
+
const stampRe = /^\d{4}-\d{2}-\d{2}(?:-\d{2})?/;
|
|
56
|
+
try {
|
|
57
|
+
// Group owned files by stamp.
|
|
58
|
+
const groups = new Map();
|
|
59
|
+
for (const f of owned) {
|
|
60
|
+
if (f === `${appName}.${ext}`)
|
|
61
|
+
continue;
|
|
62
|
+
if (!f.startsWith(prefix) || !f.endsWith(suffix))
|
|
63
|
+
continue;
|
|
64
|
+
const body = f.slice(prefix.length, -suffix.length);
|
|
65
|
+
const m = body.match(stampRe);
|
|
66
|
+
if (m) {
|
|
67
|
+
const stamp = m[0];
|
|
68
|
+
let arr = groups.get(stamp);
|
|
69
|
+
if (!arr) {
|
|
70
|
+
arr = [];
|
|
71
|
+
groups.set(stamp, arr);
|
|
72
|
+
}
|
|
73
|
+
arr.push(f);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const stamps = [...groups.keys()].sort();
|
|
77
|
+
const excess = stamps.length - maxFiles;
|
|
78
|
+
if (excess <= 0)
|
|
79
|
+
return;
|
|
80
|
+
for (let i = 0; i < excess; i++) {
|
|
81
|
+
const files = groups.get(stamps[i]);
|
|
82
|
+
for (const f of files) {
|
|
83
|
+
await (0, index_js_1.rm)((0, index_js_2.join)(dir, f), { force: true }).catch(() => { });
|
|
84
|
+
owned.delete(f);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
/* ignore */
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Best-effort cap on the number of seq files **within one time bucket**.
|
|
93
|
+
* Deletes the oldest seq files of `stamp` when the bucket holds more than
|
|
94
|
+
* `maxPerBucket` files, so a bucket forms an inner ring. The active file
|
|
95
|
+
* (highest seq) is never deleted. Iterates the `owned` set (not the
|
|
96
|
+
* directory) so the just-rotated-to active file — which may not exist on
|
|
97
|
+
* disk yet — is still counted. Best-effort: any fs error is swallowed. */
|
|
98
|
+
async function trimBucketSeq(dir, appName, ext, stamp, maxPerBucket, owned) {
|
|
99
|
+
if (maxPerBucket <= 0)
|
|
100
|
+
return;
|
|
101
|
+
const prefix = `${appName}.${stamp}.`;
|
|
102
|
+
const suffix = `.${ext}`;
|
|
103
|
+
try {
|
|
104
|
+
const files = [...owned].filter((f) => f.startsWith(prefix) && f.endsWith(suffix)).sort();
|
|
105
|
+
const excess = files.length - maxPerBucket;
|
|
106
|
+
for (let i = 0; i < excess; i++) {
|
|
107
|
+
await (0, index_js_1.rm)((0, index_js_2.join)(dir, files[i]), { force: true }).catch(() => { });
|
|
108
|
+
owned.delete(files[i]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
/* ignore */
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Global capacity guard: alongside (and independent of) per-mode `maxFiles`,
|
|
117
|
+
* delete the **oldest** owned files when either a total-size cap or an age cap
|
|
118
|
+
* is exceeded. "Oldest" is judged by modification time so it works uniformly
|
|
119
|
+
* across every mode. The active file is never deleted, even if it is the
|
|
120
|
+
* oldest. Best-effort: any fs error is swallowed.
|
|
121
|
+
*/
|
|
122
|
+
async function enforceGlobalCaps(params) {
|
|
123
|
+
const { dir, activePath, maxTotalSize, maxAge, now, owned } = params;
|
|
124
|
+
if (!Number.isFinite(maxTotalSize) && maxAge < 0)
|
|
125
|
+
return;
|
|
126
|
+
try {
|
|
127
|
+
const names = (await (0, index_js_1.readdir)(dir)).filter((f) => owned.has(f) && (0, index_js_2.join)(dir, f) !== activePath);
|
|
128
|
+
const files = await Promise.all(names.map(async (f) => {
|
|
129
|
+
try {
|
|
130
|
+
const s = await (0, index_js_1.stat)((0, index_js_2.join)(dir, f));
|
|
131
|
+
return { name: f, size: s.size, mtimeMs: s.mtimeMs };
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return null; // skip unstatable files — no infinite delete loop
|
|
135
|
+
}
|
|
136
|
+
}));
|
|
137
|
+
const valid = files.filter((f) => f !== null);
|
|
138
|
+
valid.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
139
|
+
let activeSize = 0;
|
|
140
|
+
try {
|
|
141
|
+
activeSize = (await (0, index_js_1.stat)(activePath)).size;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
/* active file not created yet */
|
|
145
|
+
}
|
|
146
|
+
const toDelete = [];
|
|
147
|
+
// Age cap: drop anything older than the threshold (0 = delete all).
|
|
148
|
+
if (maxAge >= 0) {
|
|
149
|
+
for (const f of valid) {
|
|
150
|
+
if (maxAge === 0 || now - f.mtimeMs > maxAge)
|
|
151
|
+
toDelete.push(f.name);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Size cap: drop oldest history files until active + history is under the limit.
|
|
155
|
+
if (Number.isFinite(maxTotalSize)) {
|
|
156
|
+
let total = activeSize;
|
|
157
|
+
for (const f of valid)
|
|
158
|
+
total += f.size;
|
|
159
|
+
for (const f of valid) {
|
|
160
|
+
if (total <= maxTotalSize)
|
|
161
|
+
break;
|
|
162
|
+
if (!toDelete.includes(f.name)) {
|
|
163
|
+
toDelete.push(f.name);
|
|
164
|
+
total -= f.size;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const f of toDelete) {
|
|
169
|
+
await (0, index_js_1.rm)((0, index_js_2.join)(dir, f), { force: true }).catch(() => { });
|
|
170
|
+
owned.delete(f);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
/* ignore */
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ---- 1.1 single -----------------------------------------------------------
|
|
178
|
+
class SingleRotator {
|
|
179
|
+
constructor(opts, dir, ext) {
|
|
180
|
+
this.path = (0, index_js_2.join)(dir, `${opts.appName}.${ext}`);
|
|
181
|
+
}
|
|
182
|
+
activePath() {
|
|
183
|
+
return this.path;
|
|
184
|
+
}
|
|
185
|
+
async prepare(_bytes, _entry, _now, io) {
|
|
186
|
+
io.owned.add((0, index_js_2.basename)(this.path));
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
reset() {
|
|
190
|
+
/* no transient state */
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// ---- 1.2 single-truncate --------------------------------------------------
|
|
194
|
+
class TruncateRotator {
|
|
195
|
+
constructor(opts, dir, ext) {
|
|
196
|
+
this.path = (0, index_js_2.join)(dir, `${opts.appName}.${ext}`);
|
|
197
|
+
this.backup = (0, index_js_2.join)(dir, opts.backupName ?? `${opts.appName}.bak`);
|
|
198
|
+
this.maxSize = opts.maxSize;
|
|
199
|
+
}
|
|
200
|
+
activePath() {
|
|
201
|
+
return this.path;
|
|
202
|
+
}
|
|
203
|
+
async prepare(bytes, _entry, _now, io) {
|
|
204
|
+
io.owned.add((0, index_js_2.basename)(this.path));
|
|
205
|
+
io.owned.add((0, index_js_2.basename)(this.backup));
|
|
206
|
+
let size = 0;
|
|
207
|
+
try {
|
|
208
|
+
size = (await (0, index_js_1.stat)(this.path)).size;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
/* file not written yet */
|
|
212
|
+
}
|
|
213
|
+
if (size + bytes > this.maxSize) {
|
|
214
|
+
await io.closeHandle();
|
|
215
|
+
// Remove any previous backup first: on Windows `rename` refuses to
|
|
216
|
+
// overwrite an existing target, which would otherwise block truncation.
|
|
217
|
+
await (0, index_js_1.rm)(this.backup, { force: true }).catch(() => { });
|
|
218
|
+
io.owned.delete((0, index_js_2.basename)(this.backup));
|
|
219
|
+
try {
|
|
220
|
+
await (0, index_js_1.rename)(this.path, this.backup);
|
|
221
|
+
io.owned.delete((0, index_js_2.basename)(this.path));
|
|
222
|
+
io.owned.add((0, index_js_2.basename)(this.backup));
|
|
223
|
+
return true; // truncated → a new active file was started
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
/* nothing to back up yet */
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
reset() {
|
|
232
|
+
/* no transient state */
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// ---- 2.1 rotate-size -----------------------------------------------------
|
|
236
|
+
class SizeRotator {
|
|
237
|
+
constructor(opts, dir, ext) {
|
|
238
|
+
this.active = (0, index_js_2.join)(dir, `${opts.appName}.${ext}`);
|
|
239
|
+
this.maxSize = opts.maxSize;
|
|
240
|
+
this.maxFiles = opts.maxFiles;
|
|
241
|
+
}
|
|
242
|
+
activePath() {
|
|
243
|
+
return this.active;
|
|
244
|
+
}
|
|
245
|
+
genPath(seq, io) {
|
|
246
|
+
return (0, index_js_2.join)(io.dir, `${io.appName}.${seq}.${io.ext}`);
|
|
247
|
+
}
|
|
248
|
+
async prepare(bytes, _entry, _now, io) {
|
|
249
|
+
io.owned.add((0, index_js_2.basename)(this.active));
|
|
250
|
+
let size = 0;
|
|
251
|
+
try {
|
|
252
|
+
size = (await (0, index_js_1.stat)(this.active)).size;
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
/* file not written yet */
|
|
256
|
+
}
|
|
257
|
+
if (size + bytes > this.maxSize) {
|
|
258
|
+
await io.closeHandle();
|
|
259
|
+
const gens = this.maxFiles - 1;
|
|
260
|
+
for (let k = gens; k >= 2; k--) {
|
|
261
|
+
try {
|
|
262
|
+
const from = this.genPath(k - 1, io);
|
|
263
|
+
const to = this.genPath(k, io);
|
|
264
|
+
await (0, index_js_1.rename)(from, to);
|
|
265
|
+
io.owned.delete((0, index_js_2.basename)(from));
|
|
266
|
+
io.owned.add((0, index_js_2.basename)(to));
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
/* missing generation — skip */
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
await (0, index_js_1.rename)(this.active, this.genPath(1, io));
|
|
274
|
+
io.owned.delete((0, index_js_2.basename)(this.active));
|
|
275
|
+
io.owned.add((0, index_js_2.basename)(this.genPath(1, io)));
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
/* nothing to rotate yet */
|
|
279
|
+
}
|
|
280
|
+
// Generations are capped by the rename chain above; no extra trim needed.
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
reset() {
|
|
286
|
+
/* no transient state */
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// ---- 2.2 rotate-time -----------------------------------------------------
|
|
290
|
+
class TimeRotator {
|
|
291
|
+
constructor(opts, dir, ext) {
|
|
292
|
+
this.seq = 0;
|
|
293
|
+
this.dir = dir;
|
|
294
|
+
this.ext = ext;
|
|
295
|
+
this.appName = opts.appName;
|
|
296
|
+
this.unit = opts.unit;
|
|
297
|
+
this.maxFiles = opts.maxFiles;
|
|
298
|
+
this.maxSize = opts.maxSize;
|
|
299
|
+
this.maxFilesPerBucket = opts.maxFilesPerBucket;
|
|
300
|
+
this.path = (0, index_js_2.join)(dir, `${opts.appName}.${ext}`);
|
|
301
|
+
}
|
|
302
|
+
activePath() {
|
|
303
|
+
return this.path;
|
|
304
|
+
}
|
|
305
|
+
stampPath(stamp, seq) {
|
|
306
|
+
return (0, index_js_2.join)(this.dir, `${this.appName}.${stamp}.${seq}.${this.ext}`);
|
|
307
|
+
}
|
|
308
|
+
/** Most recent existing bucket at or before `upTo`, so a restart continues
|
|
309
|
+
* the ring instead of orphaning yesterday's file. */
|
|
310
|
+
async latestExistingStamp(upTo) {
|
|
311
|
+
try {
|
|
312
|
+
const files = (await (0, index_js_1.readdir)(this.dir)).filter((f) => f.startsWith(`${this.appName}.`) && f.endsWith(`.${this.ext}`));
|
|
313
|
+
const stampRe = this.unit === 'hour' ? /^\d{4}-\d{2}-\d{2}-\d{2}/ : /^\d{4}-\d{2}-\d{2}/;
|
|
314
|
+
const prefix = `${this.appName}.`;
|
|
315
|
+
const suffix = `.${this.ext}`;
|
|
316
|
+
files.sort();
|
|
317
|
+
for (let i = files.length - 1; i >= 0; i--) {
|
|
318
|
+
const body = files[i].slice(prefix.length, -suffix.length);
|
|
319
|
+
// body is either `${stamp}` or `${stamp}.${seq}` — extract stamp
|
|
320
|
+
const dotIdx = body.lastIndexOf('.');
|
|
321
|
+
const stamp = dotIdx > 0 ? body.slice(0, dotIdx) : body;
|
|
322
|
+
if (stampRe.test(stamp) && stamp <= upTo)
|
|
323
|
+
return stamp;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
/* directory not readable yet — start fresh */
|
|
328
|
+
}
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
/** Find the highest seq number among files in the given time bucket. */
|
|
332
|
+
async latestExistingSeq(stamp) {
|
|
333
|
+
if (!this.maxSize)
|
|
334
|
+
return 0;
|
|
335
|
+
try {
|
|
336
|
+
const prefix = `${this.appName}.${stamp}.`;
|
|
337
|
+
const suffix = `.${this.ext}`;
|
|
338
|
+
const files = (await (0, index_js_1.readdir)(this.dir)).filter((f) => f.startsWith(prefix) && f.endsWith(suffix));
|
|
339
|
+
let maxSeq = 0;
|
|
340
|
+
for (const f of files) {
|
|
341
|
+
const body = f.slice(this.appName.length + 1, -this.ext.length - 1);
|
|
342
|
+
// body is `${stamp}.${seq}`
|
|
343
|
+
const parts = body.split('.');
|
|
344
|
+
const seq = Number(parts[parts.length - 1]);
|
|
345
|
+
if (Number.isFinite(seq) && seq > maxSeq)
|
|
346
|
+
maxSeq = seq;
|
|
347
|
+
}
|
|
348
|
+
return maxSeq;
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
return 0;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
async prepare(bytes, _entry, now, io) {
|
|
355
|
+
const stamp = timeStamp(now, this.unit);
|
|
356
|
+
if (this.currentStamp === undefined) {
|
|
357
|
+
const existing = await this.latestExistingStamp(stamp);
|
|
358
|
+
this.currentStamp = existing ?? stamp;
|
|
359
|
+
this.seq = await this.latestExistingSeq(this.currentStamp);
|
|
360
|
+
this.path = this.stampPath(this.currentStamp, this.seq);
|
|
361
|
+
io.owned.add((0, index_js_2.basename)(this.path));
|
|
362
|
+
if (existing && existing !== stamp) {
|
|
363
|
+
// Bucket already rolled over; open the new one and drop stale files.
|
|
364
|
+
this.currentStamp = stamp;
|
|
365
|
+
this.seq = 0;
|
|
366
|
+
await io.closeHandle();
|
|
367
|
+
this.path = this.stampPath(stamp, 0);
|
|
368
|
+
io.owned.add((0, index_js_2.basename)(this.path));
|
|
369
|
+
await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
if (stamp !== this.currentStamp) {
|
|
376
|
+
// Time bucket changed — archive the previous file and open a new one.
|
|
377
|
+
this.currentStamp = stamp;
|
|
378
|
+
this.seq = 0;
|
|
379
|
+
await io.closeHandle();
|
|
380
|
+
this.path = this.stampPath(stamp, 0);
|
|
381
|
+
io.owned.add((0, index_js_2.basename)(this.path));
|
|
382
|
+
await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
// Same time bucket — check size-based splitting within the bucket.
|
|
386
|
+
if (this.maxSize !== undefined) {
|
|
387
|
+
let size = 0;
|
|
388
|
+
try {
|
|
389
|
+
size = (await (0, index_js_1.stat)(this.path)).size;
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
/* file not written yet */
|
|
393
|
+
}
|
|
394
|
+
if (size + bytes > this.maxSize) {
|
|
395
|
+
this.seq += 1;
|
|
396
|
+
await io.closeHandle();
|
|
397
|
+
this.path = this.stampPath(this.currentStamp, this.seq);
|
|
398
|
+
io.owned.add((0, index_js_2.basename)(this.path));
|
|
399
|
+
await trimTimeRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
|
|
400
|
+
// Cap the seq count inside the current bucket (inner ring).
|
|
401
|
+
await trimBucketSeq(io.dir, io.appName, io.ext, this.currentStamp, this.maxFilesPerBucket ?? 0, io.owned);
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
reset() {
|
|
408
|
+
this.currentStamp = undefined;
|
|
409
|
+
this.seq = 0;
|
|
410
|
+
this.path = (0, index_js_2.join)(this.dir, `${this.appName}.${this.ext}`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// ---- 2.3 rotate-custom ---------------------------------------------------
|
|
414
|
+
class CustomRotator {
|
|
415
|
+
constructor(opts, dir, ext) {
|
|
416
|
+
this.seq = 0;
|
|
417
|
+
this.dir = dir;
|
|
418
|
+
this.ext = ext;
|
|
419
|
+
this.appName = opts.appName;
|
|
420
|
+
this.maxFiles = opts.maxFiles;
|
|
421
|
+
this.shouldRotate = opts.shouldRotate;
|
|
422
|
+
this.fileName = opts.fileName;
|
|
423
|
+
this.path = (0, index_js_2.join)(dir, this.fileName(opts.appName, 0, ext));
|
|
424
|
+
}
|
|
425
|
+
activePath() {
|
|
426
|
+
return this.path;
|
|
427
|
+
}
|
|
428
|
+
async prepare(_bytes, entry, now, io) {
|
|
429
|
+
const ctx = {
|
|
430
|
+
entry,
|
|
431
|
+
size: 0,
|
|
432
|
+
time: now.toISOString(),
|
|
433
|
+
};
|
|
434
|
+
if (this.shouldRotate(entry, ctx)) {
|
|
435
|
+
this.seq += 1;
|
|
436
|
+
await io.closeHandle();
|
|
437
|
+
this.path = (0, index_js_2.join)(io.dir, this.fileName(io.appName, this.seq, io.ext));
|
|
438
|
+
io.owned.add((0, index_js_2.basename)(this.path));
|
|
439
|
+
await trimRing(io.dir, io.appName, io.ext, this.maxFiles ?? 0, io.owned);
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
reset() {
|
|
445
|
+
this.seq = 0;
|
|
446
|
+
this.path = (0, index_js_2.join)(this.dir, this.fileName(this.appName, 0, this.ext));
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Single file transport covering every file-output strategy. Each strategy is
|
|
451
|
+
* an isolated `Rotator` (see above); this class only performs the shared
|
|
452
|
+
* filesystem plumbing on a serialized queue.
|
|
453
|
+
*
|
|
454
|
+
* Modes:
|
|
455
|
+
* - `single` (1.1): one fixed file, append forever.
|
|
456
|
+
* - `single-truncate` (1.2): back up + truncate when `maxSize` would be exceeded.
|
|
457
|
+
* - `rotate-size` (2.1): roll by size into N generations.
|
|
458
|
+
* - `rotate-time` (2.2): roll by hour/day into timestamped files.
|
|
459
|
+
* - `rotate-custom` (2.3): roll whenever a user predicate says so.
|
|
460
|
+
*
|
|
461
|
+
* `appName` is required and is embedded in every file name.
|
|
462
|
+
*/
|
|
463
|
+
class FileTransport {
|
|
464
|
+
/** Effective capacity limits, for diagnostics (e.g. "why was my log file
|
|
465
|
+
* deleted?"). `maxSize`/`maxFiles` reflect the active rotation mode;
|
|
466
|
+
* `maxTotalSize`/`maxAge` are the global caps (`Infinity`/`-1` = unset). */
|
|
467
|
+
get caps() {
|
|
468
|
+
const o = this.options;
|
|
469
|
+
return {
|
|
470
|
+
maxSize: 'maxSize' in o ? o.maxSize : undefined,
|
|
471
|
+
maxFiles: 'maxFiles' in o ? o.maxFiles : undefined,
|
|
472
|
+
maxFilesPerBucket: 'maxFilesPerBucket' in o ? o.maxFilesPerBucket : undefined,
|
|
473
|
+
maxTotalSize: this.maxTotalSize,
|
|
474
|
+
maxAge: this.maxAge,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
constructor(options) {
|
|
478
|
+
this.owned = new Set();
|
|
479
|
+
this.closed = false;
|
|
480
|
+
this.reportedFirstError = false;
|
|
481
|
+
this.handle = null;
|
|
482
|
+
this.queue = Promise.resolve();
|
|
483
|
+
this.ownedScanned = false;
|
|
484
|
+
this.writeCount = 0;
|
|
485
|
+
this.lastCheckMs = 0;
|
|
486
|
+
if (!options.appName) {
|
|
487
|
+
throw new Error('FileTransport requires an "appName"');
|
|
488
|
+
}
|
|
489
|
+
this.options = options;
|
|
490
|
+
this.dir = options.dir ?? (0, index_js_3.tmpdir)();
|
|
491
|
+
this.ext = options.ext ?? 'log';
|
|
492
|
+
this.name = options.name ?? `file:${options.appName}`;
|
|
493
|
+
this.formatter = options.formatter ?? (0, formatter_js_1.createJsonFormatter)();
|
|
494
|
+
this.filter = options.filter;
|
|
495
|
+
this.maxTotalSize = options.maxTotalSize ?? Infinity;
|
|
496
|
+
this.maxAge = options.maxAge ?? -1;
|
|
497
|
+
this.createdAt = Date.now();
|
|
498
|
+
switch (options.mode) {
|
|
499
|
+
case 'single':
|
|
500
|
+
this.rotator = new SingleRotator(options, this.dir, this.ext);
|
|
501
|
+
break;
|
|
502
|
+
case 'single-truncate':
|
|
503
|
+
this.rotator = new TruncateRotator(options, this.dir, this.ext);
|
|
504
|
+
break;
|
|
505
|
+
case 'rotate-size':
|
|
506
|
+
this.rotator = new SizeRotator(options, this.dir, this.ext);
|
|
507
|
+
break;
|
|
508
|
+
case 'rotate-time':
|
|
509
|
+
this.rotator = new TimeRotator(options, this.dir, this.ext);
|
|
510
|
+
break;
|
|
511
|
+
case 'rotate-custom':
|
|
512
|
+
this.rotator = new CustomRotator(options, this.dir, this.ext);
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
// Capture the clock synchronously at write time so a rotate-time transport
|
|
516
|
+
// uses the timestamp of the call, not a later microtask.
|
|
517
|
+
this.clock = options.mode === 'rotate-time' && options.now ? options.now : () => new Date();
|
|
518
|
+
this.io = {
|
|
519
|
+
dir: this.dir,
|
|
520
|
+
ext: this.ext,
|
|
521
|
+
appName: options.appName,
|
|
522
|
+
closeHandle: () => this.closeHandle(),
|
|
523
|
+
owned: this.owned,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
/** Absolute path of the log directory. */
|
|
527
|
+
getDir() {
|
|
528
|
+
return this.dir;
|
|
529
|
+
}
|
|
530
|
+
/** Absolute path of the file currently being written to. */
|
|
531
|
+
getActiveFile() {
|
|
532
|
+
return this.rotator.activePath();
|
|
533
|
+
}
|
|
534
|
+
/** List all log files managed by this transport.
|
|
535
|
+
*
|
|
536
|
+
* By default returns every file the transport knows about, including
|
|
537
|
+
* files left over from previous runs (discovered via `scanOwned`). Pass
|
|
538
|
+
* `{ currentSessionOnly: true }` to restrict the result to files created
|
|
539
|
+
* by the current transport instance. */
|
|
540
|
+
async getFiles(options) {
|
|
541
|
+
await this.scanOwned();
|
|
542
|
+
const activePath = this.rotator.activePath();
|
|
543
|
+
const results = [];
|
|
544
|
+
for (const name of this.owned) {
|
|
545
|
+
const filePath = (0, index_js_2.join)(this.dir, name);
|
|
546
|
+
try {
|
|
547
|
+
const s = await (0, index_js_1.stat)(filePath);
|
|
548
|
+
if (options?.currentSessionOnly && s.mtimeMs < this.createdAt)
|
|
549
|
+
continue;
|
|
550
|
+
results.push({
|
|
551
|
+
name,
|
|
552
|
+
path: filePath,
|
|
553
|
+
size: s.size,
|
|
554
|
+
mtime: s.mtimeMs,
|
|
555
|
+
active: filePath === activePath,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
// file disappeared between readdir and stat — skip
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return results;
|
|
563
|
+
}
|
|
564
|
+
async ensureHandle() {
|
|
565
|
+
if (!this.handle) {
|
|
566
|
+
await this.scanOwned();
|
|
567
|
+
await (0, index_js_1.mkdir)((0, index_js_2.dirname)(this.rotator.activePath()), { recursive: true });
|
|
568
|
+
this.handle = await (0, index_js_1.open)(this.rotator.activePath(), 'a');
|
|
569
|
+
this.io.owned.add((0, index_js_2.basename)(this.rotator.activePath()));
|
|
570
|
+
}
|
|
571
|
+
return this.handle;
|
|
572
|
+
}
|
|
573
|
+
async scanOwned() {
|
|
574
|
+
if (this.ownedScanned)
|
|
575
|
+
return;
|
|
576
|
+
this.ownedScanned = true;
|
|
577
|
+
try {
|
|
578
|
+
const files = await (0, index_js_1.readdir)(this.dir);
|
|
579
|
+
const prefix = `${this.io.appName}.`;
|
|
580
|
+
const suffix = `.${this.io.ext}`;
|
|
581
|
+
for (const f of files) {
|
|
582
|
+
if (f.startsWith(prefix) && f.endsWith(suffix)) {
|
|
583
|
+
this.io.owned.add(f);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
catch {
|
|
588
|
+
/* ignore scan failures */
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
async closeHandle() {
|
|
592
|
+
if (this.handle) {
|
|
593
|
+
await this.handle.close();
|
|
594
|
+
this.handle = null;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
write(entry, formatted) {
|
|
598
|
+
if (this.closed || (this.filter && !this.filter(entry)))
|
|
599
|
+
return;
|
|
600
|
+
const line = formatted + '\n';
|
|
601
|
+
const bytes = Buffer.byteLength(line, 'utf8');
|
|
602
|
+
const now = this.clock();
|
|
603
|
+
const nowMs = now.getTime();
|
|
604
|
+
const task = this.queue
|
|
605
|
+
.then(async () => {
|
|
606
|
+
const rotated = await this.rotator.prepare(bytes, entry, now, this.io);
|
|
607
|
+
// Run the global cap check only when a rotation just happened (a new
|
|
608
|
+
// file landed) — that is when stale files can exceed the caps. Non-
|
|
609
|
+
// rotating modes (e.g. `single`) rely on the throttled periodic check
|
|
610
|
+
// below, so we never scan the directory on every hot-path write.
|
|
611
|
+
if (rotated) {
|
|
612
|
+
await enforceGlobalCaps({
|
|
613
|
+
dir: this.dir,
|
|
614
|
+
activePath: this.rotator.activePath(),
|
|
615
|
+
maxTotalSize: this.maxTotalSize,
|
|
616
|
+
maxAge: this.maxAge,
|
|
617
|
+
now: nowMs,
|
|
618
|
+
owned: this.io.owned,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
// Throttled periodic check so caps are still honored between rotations
|
|
622
|
+
// (or when a mode never rotates). At most once per PERIODIC_EVERY writes
|
|
623
|
+
// and once per PERIODIC_INTERVAL_MS.
|
|
624
|
+
this.writeCount++;
|
|
625
|
+
const due = this.writeCount % FileTransport.PERIODIC_EVERY === 0 &&
|
|
626
|
+
nowMs - this.lastCheckMs >= FileTransport.PERIODIC_INTERVAL_MS;
|
|
627
|
+
if (due) {
|
|
628
|
+
this.lastCheckMs = nowMs;
|
|
629
|
+
await enforceGlobalCaps({
|
|
630
|
+
dir: this.dir,
|
|
631
|
+
activePath: this.rotator.activePath(),
|
|
632
|
+
maxTotalSize: this.maxTotalSize,
|
|
633
|
+
maxAge: this.maxAge,
|
|
634
|
+
now: nowMs,
|
|
635
|
+
owned: this.io.owned,
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
const handle = await this.ensureHandle();
|
|
639
|
+
await handle.write(line);
|
|
640
|
+
})
|
|
641
|
+
.catch((err) => {
|
|
642
|
+
if (!this.reportedFirstError) {
|
|
643
|
+
this.reportedFirstError = true;
|
|
644
|
+
console.error('[lograil] FileTransport write error (subsequent errors suppressed):', err);
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
this.queue = task;
|
|
648
|
+
return task;
|
|
649
|
+
}
|
|
650
|
+
async flush() {
|
|
651
|
+
await this.queue;
|
|
652
|
+
}
|
|
653
|
+
async close() {
|
|
654
|
+
await this.queue;
|
|
655
|
+
await this.closeHandle();
|
|
656
|
+
this.rotator.reset();
|
|
657
|
+
this.closed = true;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
exports.FileTransport = FileTransport;
|
|
661
|
+
// Throttled periodic capacity check (in addition to the mandatory check that
|
|
662
|
+
// runs after every rotation): inspect at most once per `PERIODIC_EVERY`
|
|
663
|
+
// writes and at most once per `PERIODIC_INTERVAL_MS`.
|
|
664
|
+
FileTransport.PERIODIC_EVERY = 256;
|
|
665
|
+
FileTransport.PERIODIC_INTERVAL_MS = 60000;
|
|
666
|
+
//# sourceMappingURL=file.js.map
|