lograil 0.1.0 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -1
- package/README.md +3 -1
- package/dist/cjs/context/async-context.browser.d.ts +1 -7
- package/dist/cjs/context/async-context.browser.d.ts.map +1 -1
- package/dist/cjs/context/async-context.browser.js +4 -1
- package/dist/cjs/context/async-context.browser.js.map +1 -1
- package/dist/cjs/context/context.js +1 -1
- package/dist/cjs/context/context.js.map +1 -1
- package/dist/cjs/core/logger.d.ts +20 -16
- package/dist/cjs/core/logger.d.ts.map +1 -1
- package/dist/cjs/core/logger.js +115 -48
- package/dist/cjs/core/logger.js.map +1 -1
- package/dist/cjs/pipeline/formatter.d.ts.map +1 -1
- package/dist/cjs/pipeline/formatter.js +64 -31
- package/dist/cjs/pipeline/formatter.js.map +1 -1
- package/dist/cjs/pipeline/pipeline.d.ts.map +1 -1
- package/dist/cjs/pipeline/pipeline.js +2 -1
- package/dist/cjs/pipeline/pipeline.js.map +1 -1
- package/dist/cjs/pipeline/processor.d.ts.map +1 -1
- package/dist/cjs/pipeline/processor.js +18 -6
- package/dist/cjs/pipeline/processor.js.map +1 -1
- package/dist/cjs/pipeline/sampler.d.ts.map +1 -1
- package/dist/cjs/pipeline/sampler.js +5 -0
- package/dist/cjs/pipeline/sampler.js.map +1 -1
- package/dist/cjs/plugin/manager.d.ts.map +1 -1
- package/dist/cjs/plugin/manager.js +9 -1
- package/dist/cjs/plugin/manager.js.map +1 -1
- package/dist/cjs/plugin/otel-trace.d.ts.map +1 -1
- package/dist/cjs/plugin/otel-trace.js +4 -7
- package/dist/cjs/plugin/otel-trace.js.map +1 -1
- package/dist/cjs/runtime/electron-binding.d.ts +4 -0
- package/dist/cjs/runtime/electron-binding.d.ts.map +1 -1
- package/dist/cjs/runtime/electron-binding.js +24 -2
- package/dist/cjs/runtime/electron-binding.js.map +1 -1
- package/dist/cjs/runtime/electron.d.ts.map +1 -1
- package/dist/cjs/runtime/electron.js +7 -1
- package/dist/cjs/runtime/electron.js.map +1 -1
- package/dist/cjs/runtime/process-lifecycle.d.ts.map +1 -1
- package/dist/cjs/runtime/process-lifecycle.js +11 -0
- package/dist/cjs/runtime/process-lifecycle.js.map +1 -1
- package/dist/cjs/transport/cluster-ipc.d.ts +2 -0
- package/dist/cjs/transport/cluster-ipc.d.ts.map +1 -1
- package/dist/cjs/transport/cluster-ipc.js +53 -5
- package/dist/cjs/transport/cluster-ipc.js.map +1 -1
- package/dist/cjs/transport/console.d.ts.map +1 -1
- package/dist/cjs/transport/console.js +10 -9
- package/dist/cjs/transport/console.js.map +1 -1
- package/dist/cjs/transport/electron-ipc.d.ts +4 -17
- package/dist/cjs/transport/electron-ipc.d.ts.map +1 -1
- package/dist/cjs/transport/electron-ipc.js +42 -73
- package/dist/cjs/transport/electron-ipc.js.map +1 -1
- package/dist/cjs/transport/file.d.ts +10 -4
- package/dist/cjs/transport/file.d.ts.map +1 -1
- package/dist/cjs/transport/file.js +28 -8
- package/dist/cjs/transport/file.js.map +1 -1
- package/dist/cjs/transport/live.d.ts +2 -1
- package/dist/cjs/transport/live.d.ts.map +1 -1
- package/dist/cjs/transport/live.js +4 -1
- package/dist/cjs/transport/live.js.map +1 -1
- package/dist/cjs/transport/otlp.d.ts +1 -1
- package/dist/cjs/transport/otlp.d.ts.map +1 -1
- package/dist/cjs/transport/otlp.js +24 -21
- package/dist/cjs/transport/otlp.js.map +1 -1
- package/dist/cjs/transport/worker-ipc.d.ts +3 -0
- package/dist/cjs/transport/worker-ipc.d.ts.map +1 -1
- package/dist/cjs/transport/worker-ipc.js +76 -8
- package/dist/cjs/transport/worker-ipc.js.map +1 -1
- package/dist/cjs/types.d.ts +16 -5
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js +5 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/context/async-context.browser.d.ts +1 -7
- package/dist/esm/context/async-context.browser.d.ts.map +1 -1
- package/dist/esm/context/async-context.browser.js +4 -1
- package/dist/esm/context/async-context.browser.js.map +1 -1
- package/dist/esm/context/context.js +1 -1
- package/dist/esm/context/context.js.map +1 -1
- package/dist/esm/core/logger.d.ts +20 -16
- package/dist/esm/core/logger.d.ts.map +1 -1
- package/dist/esm/core/logger.js +115 -48
- package/dist/esm/core/logger.js.map +1 -1
- package/dist/esm/pipeline/formatter.d.ts.map +1 -1
- package/dist/esm/pipeline/formatter.js +64 -31
- package/dist/esm/pipeline/formatter.js.map +1 -1
- package/dist/esm/pipeline/pipeline.d.ts.map +1 -1
- package/dist/esm/pipeline/pipeline.js +2 -1
- package/dist/esm/pipeline/pipeline.js.map +1 -1
- package/dist/esm/pipeline/processor.d.ts.map +1 -1
- package/dist/esm/pipeline/processor.js +18 -6
- package/dist/esm/pipeline/processor.js.map +1 -1
- package/dist/esm/pipeline/sampler.d.ts.map +1 -1
- package/dist/esm/pipeline/sampler.js +5 -0
- package/dist/esm/pipeline/sampler.js.map +1 -1
- package/dist/esm/plugin/manager.d.ts.map +1 -1
- package/dist/esm/plugin/manager.js +9 -1
- package/dist/esm/plugin/manager.js.map +1 -1
- package/dist/esm/plugin/otel-trace.d.ts.map +1 -1
- package/dist/esm/plugin/otel-trace.js +4 -7
- package/dist/esm/plugin/otel-trace.js.map +1 -1
- package/dist/esm/runtime/electron-binding.d.ts +4 -0
- package/dist/esm/runtime/electron-binding.d.ts.map +1 -1
- package/dist/esm/runtime/electron-binding.js +24 -2
- package/dist/esm/runtime/electron-binding.js.map +1 -1
- package/dist/esm/runtime/electron.d.ts.map +1 -1
- package/dist/esm/runtime/electron.js +7 -1
- package/dist/esm/runtime/electron.js.map +1 -1
- package/dist/esm/runtime/process-lifecycle.d.ts.map +1 -1
- package/dist/esm/runtime/process-lifecycle.js +11 -0
- package/dist/esm/runtime/process-lifecycle.js.map +1 -1
- package/dist/esm/transport/cluster-ipc.d.ts +2 -0
- package/dist/esm/transport/cluster-ipc.d.ts.map +1 -1
- package/dist/esm/transport/cluster-ipc.js +52 -5
- package/dist/esm/transport/cluster-ipc.js.map +1 -1
- package/dist/esm/transport/console.d.ts.map +1 -1
- package/dist/esm/transport/console.js +10 -9
- package/dist/esm/transport/console.js.map +1 -1
- package/dist/esm/transport/electron-ipc.d.ts +4 -17
- package/dist/esm/transport/electron-ipc.d.ts.map +1 -1
- package/dist/esm/transport/electron-ipc.js +42 -71
- package/dist/esm/transport/electron-ipc.js.map +1 -1
- package/dist/esm/transport/file.d.ts +10 -4
- package/dist/esm/transport/file.d.ts.map +1 -1
- package/dist/esm/transport/file.js +28 -8
- package/dist/esm/transport/file.js.map +1 -1
- package/dist/esm/transport/live.d.ts +2 -1
- package/dist/esm/transport/live.d.ts.map +1 -1
- package/dist/esm/transport/live.js +4 -1
- package/dist/esm/transport/live.js.map +1 -1
- package/dist/esm/transport/otlp.d.ts +1 -1
- package/dist/esm/transport/otlp.d.ts.map +1 -1
- package/dist/esm/transport/otlp.js +24 -21
- package/dist/esm/transport/otlp.js.map +1 -1
- package/dist/esm/transport/worker-ipc.d.ts +3 -0
- package/dist/esm/transport/worker-ipc.d.ts.map +1 -1
- package/dist/esm/transport/worker-ipc.js +75 -8
- package/dist/esm/transport/worker-ipc.js.map +1 -1
- package/dist/esm/types.d.ts +16 -5
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +5 -1
- package/dist/esm/types.js.map +1 -1
- package/package.json +12 -3
- package/dist/cjs/transport/rotating-file.d.ts +0 -67
- package/dist/cjs/transport/rotating-file.d.ts.map +0 -1
- package/dist/cjs/transport/rotating-file.js +0 -179
- package/dist/cjs/transport/rotating-file.js.map +0 -1
- package/dist/esm/transport/rotating-file.d.ts +0 -67
- package/dist/esm/transport/rotating-file.d.ts.map +0 -1
- package/dist/esm/transport/rotating-file.js +0 -175
- package/dist/esm/transport/rotating-file.js.map +0 -1
package/dist/esm/types.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
8
|
* Ordered by severity. Higher value means more severe.
|
|
9
|
+
* @internal
|
|
9
10
|
*/
|
|
10
11
|
export const LOG_LEVELS = {
|
|
11
12
|
trace: 10,
|
|
@@ -15,10 +16,13 @@ export const LOG_LEVELS = {
|
|
|
15
16
|
error: 50,
|
|
16
17
|
fatal: 60,
|
|
17
18
|
};
|
|
19
|
+
/** @internal */
|
|
18
20
|
export const LOG_LEVEL_NAMES = Object.keys(LOG_LEVELS);
|
|
21
|
+
/** @internal */
|
|
19
22
|
export function isLogLevelName(value) {
|
|
20
23
|
return typeof value === 'string' && value in LOG_LEVELS;
|
|
21
24
|
}
|
|
25
|
+
/** @internal */
|
|
22
26
|
export function normalizeLevel(input) {
|
|
23
27
|
if (typeof input === 'number') {
|
|
24
28
|
return input;
|
|
@@ -29,7 +33,7 @@ export function normalizeLevel(input) {
|
|
|
29
33
|
}
|
|
30
34
|
return value;
|
|
31
35
|
}
|
|
32
|
-
/** Returns true when the value is a {@link LogLevelCommand}. */
|
|
36
|
+
/** @internal Returns true when the value is a {@link LogLevelCommand}. */
|
|
33
37
|
export function isLogLevelCommand(value) {
|
|
34
38
|
return (typeof value === 'object' &&
|
|
35
39
|
value !== null &&
|
package/dist/esm/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAwC;IAC7D,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,EAAE;CACV,CAAC;AAEF,gBAAgB;AAChB,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAmB,CAAC;AAEzE,gBAAgB;AAChB,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,UAAU,CAAC;AAC1D,CAAC;AA6DD,gBAAgB;AAChB,MAAM,UAAU,cAAc,CAAC,KAAoB;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AASD,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACb,KAAiC,CAAC,YAAY,KAAK,IAAI;QACvD,KAAiC,CAAC,gBAAgB,KAAK,UAAU,CACnE,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lograil",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"packageManager": "yarn@1.22.22",
|
|
5
5
|
"description": "High-performance, secure universal logging library for Web, Node.js and Electron — first-class runtime support, extensible to other platforms via plugins.",
|
|
6
6
|
"author": "Axetroy <axetroy.dev@gmail.com>",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/axetroy/lograil.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/axetroy/lograil#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/axetroy/lograil/issues"
|
|
14
|
+
},
|
|
7
15
|
"type": "module",
|
|
8
16
|
"main": "./dist/cjs/index.js",
|
|
9
17
|
"module": "./dist/esm/index.js",
|
|
@@ -98,7 +106,7 @@
|
|
|
98
106
|
],
|
|
99
107
|
"license": "MIT",
|
|
100
108
|
"peerDependencies": {
|
|
101
|
-
"@opentelemetry/api": "^1.
|
|
109
|
+
"@opentelemetry/api": "^1.9.1"
|
|
102
110
|
},
|
|
103
111
|
"peerDependenciesMeta": {
|
|
104
112
|
"@opentelemetry/api": {
|
|
@@ -107,7 +115,8 @@
|
|
|
107
115
|
},
|
|
108
116
|
"devDependencies": {
|
|
109
117
|
"@eslint/js": "^9.39.5",
|
|
110
|
-
"@
|
|
118
|
+
"@opentelemetry/api": "^1.9.1",
|
|
119
|
+
"@types/node": "^26.4.1",
|
|
111
120
|
"@vitest/coverage-v8": "2.1.9",
|
|
112
121
|
"electron": "^28.0.0",
|
|
113
122
|
"eslint": "^9.39.5",
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { LogEntry } from '../types.js';
|
|
2
|
-
import type { Formatter } from '../pipeline/formatter.js';
|
|
3
|
-
import type { Transport } from './transport.js';
|
|
4
|
-
export interface RotatingFileTransportOptions {
|
|
5
|
-
/** Active (or current-day) log file path, e.g. `/var/log/app.log`. */
|
|
6
|
-
path: string;
|
|
7
|
-
/** Size mode: rotate once the active file exceeds this size in bytes. */
|
|
8
|
-
maxSize?: number;
|
|
9
|
-
/**
|
|
10
|
-
* Maximum number of files in the rotation set.
|
|
11
|
-
* - Size mode: `app.log` + `app.1.log` … (generations). Minimum 2.
|
|
12
|
-
* - Daily mode: `{name}.{YYYY-MM-DD}.01..{maxFiles}.log` per day; when the
|
|
13
|
-
* index would pass `maxFiles` it wraps back to `01` and clears that file.
|
|
14
|
-
* Defaults to 5 (size) or 99 (daily).
|
|
15
|
-
*/
|
|
16
|
-
maxFiles?: number;
|
|
17
|
-
/**
|
|
18
|
-
* Daily mode (default `true`): one dated file per day, split into
|
|
19
|
-
* `01`..`{maxFiles}` indexes. Set `false` for plain size-based generation
|
|
20
|
-
* rotation (`app.log` → `app.1.log` → …) without dates.
|
|
21
|
-
*/
|
|
22
|
-
daily?: boolean;
|
|
23
|
-
/** Override the clock (mainly for testing). Defaults to `new Date()`. */
|
|
24
|
-
now?: () => Date;
|
|
25
|
-
formatter?: Formatter;
|
|
26
|
-
name?: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* File transport with rotation, for the Electron main process (Node.js).
|
|
30
|
-
*
|
|
31
|
-
* Two modes:
|
|
32
|
-
* - **Daily** (default): the active file is
|
|
33
|
-
* `{name}.{YYYY-MM-DD}.{index}.log`, where `index` runs `01`..`maxFiles`
|
|
34
|
-
* (default 99). When it would pass `maxFiles` it wraps back to `01` and
|
|
35
|
-
* that file is cleared — a `maxFiles`-file ring buffer per day. When the
|
|
36
|
-
* local day changes, the index resets to `01` for the new day.
|
|
37
|
-
*/
|
|
38
|
-
export declare class RotatingFileTransport implements Transport {
|
|
39
|
-
readonly name: string;
|
|
40
|
-
readonly formatter: Formatter;
|
|
41
|
-
private readonly path;
|
|
42
|
-
private readonly maxSize;
|
|
43
|
-
private readonly maxFiles;
|
|
44
|
-
private readonly daily;
|
|
45
|
-
private readonly now;
|
|
46
|
-
private handle;
|
|
47
|
-
private queue;
|
|
48
|
-
private size;
|
|
49
|
-
private sizeInitialized;
|
|
50
|
-
private currentDate;
|
|
51
|
-
private index;
|
|
52
|
-
constructor(options: RotatingFileTransportOptions);
|
|
53
|
-
private activePath;
|
|
54
|
-
private ensureHandle;
|
|
55
|
-
private ensureSize;
|
|
56
|
-
private rotateSize;
|
|
57
|
-
/**
|
|
58
|
-
* Move to a new index file. When `clear` is true the target file is
|
|
59
|
-
* truncated first (used both for normal index advancement and for the
|
|
60
|
-
* wrap-to-01, which must clear the stale `01` slot).
|
|
61
|
-
*/
|
|
62
|
-
private rotateToIndex;
|
|
63
|
-
write(_entry: LogEntry, formatted: string): void | Promise<void>;
|
|
64
|
-
flush(): Promise<void>;
|
|
65
|
-
close(): Promise<void>;
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=rotating-file.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rotating-file.d.ts","sourceRoot":"","sources":["../../../src/transport/rotating-file.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,4BAA4B;IAC3C,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAaD;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,YAAW,SAAS;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,MAAM,CAAiD;IAC/D,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,KAAK,CAAK;gBAEN,OAAO,EAAE,4BAA4B;IAkBjD,OAAO,CAAC,UAAU;YAUJ,YAAY;YAOZ,UAAU;YAWV,UAAU;IAuBxB;;;;OAIG;YACW,aAAa;IAqB3B,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RotatingFileTransport = void 0;
|
|
4
|
-
const promises_1 = require("node:fs/promises");
|
|
5
|
-
const node_path_1 = require("node:path");
|
|
6
|
-
const formatter_js_1 = require("../pipeline/formatter.js");
|
|
7
|
-
const DEFAULT_MAX_SIZE = 10 * 1024 * 1024;
|
|
8
|
-
const DEFAULT_MAX_FILES = 5;
|
|
9
|
-
const DEFAULT_MAX_FILES_DAILY = 99;
|
|
10
|
-
function dateStamp(d) {
|
|
11
|
-
const y = d.getFullYear();
|
|
12
|
-
const m = String(d.getMonth() + 1).padStart(2, '0');
|
|
13
|
-
const day = String(d.getDate()).padStart(2, '0');
|
|
14
|
-
return `${y}-${m}-${day}`;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* File transport with rotation, for the Electron main process (Node.js).
|
|
18
|
-
*
|
|
19
|
-
* Two modes:
|
|
20
|
-
* - **Daily** (default): the active file is
|
|
21
|
-
* `{name}.{YYYY-MM-DD}.{index}.log`, where `index` runs `01`..`maxFiles`
|
|
22
|
-
* (default 99). When it would pass `maxFiles` it wraps back to `01` and
|
|
23
|
-
* that file is cleared — a `maxFiles`-file ring buffer per day. When the
|
|
24
|
-
* local day changes, the index resets to `01` for the new day.
|
|
25
|
-
*/
|
|
26
|
-
class RotatingFileTransport {
|
|
27
|
-
constructor(options) {
|
|
28
|
-
this.handle = null;
|
|
29
|
-
this.queue = Promise.resolve();
|
|
30
|
-
this.size = 0;
|
|
31
|
-
this.sizeInitialized = false;
|
|
32
|
-
this.index = 1;
|
|
33
|
-
if (!options.path) {
|
|
34
|
-
throw new Error('RotatingFileTransport requires a "path"');
|
|
35
|
-
}
|
|
36
|
-
this.path = options.path;
|
|
37
|
-
this.daily = options.daily ?? true;
|
|
38
|
-
this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;
|
|
39
|
-
this.maxFiles = options.maxFiles ?? (this.daily ? DEFAULT_MAX_FILES_DAILY : DEFAULT_MAX_FILES);
|
|
40
|
-
if (!this.daily) {
|
|
41
|
-
this.maxFiles = Math.max(2, this.maxFiles);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
this.maxFiles = Math.max(1, this.maxFiles);
|
|
45
|
-
}
|
|
46
|
-
this.now = options.now ?? (() => new Date());
|
|
47
|
-
this.name = options.name ?? `rotating-file:${options.path}`;
|
|
48
|
-
this.formatter = options.formatter ?? (0, formatter_js_1.createJsonFormatter)();
|
|
49
|
-
}
|
|
50
|
-
activePath() {
|
|
51
|
-
if (!this.daily) {
|
|
52
|
-
return this.path;
|
|
53
|
-
}
|
|
54
|
-
const ext = (0, node_path_1.extname)(this.path);
|
|
55
|
-
const base = ext ? this.path.slice(0, -ext.length) : this.path;
|
|
56
|
-
const idx = String(this.index).padStart(2, '0');
|
|
57
|
-
return `${base}.${this.currentDate}.${idx}${ext}`;
|
|
58
|
-
}
|
|
59
|
-
async ensureHandle() {
|
|
60
|
-
if (!this.handle) {
|
|
61
|
-
await (0, promises_1.mkdir)((0, node_path_1.dirname)(this.activePath()), { recursive: true });
|
|
62
|
-
this.handle = await (0, promises_1.open)(this.activePath(), 'a');
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
async ensureSize() {
|
|
66
|
-
if (this.sizeInitialized)
|
|
67
|
-
return;
|
|
68
|
-
try {
|
|
69
|
-
const st = await (0, promises_1.stat)(this.activePath());
|
|
70
|
-
this.size = st.size;
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
this.size = 0;
|
|
74
|
-
}
|
|
75
|
-
this.sizeInitialized = true;
|
|
76
|
-
}
|
|
77
|
-
async rotateSize() {
|
|
78
|
-
if (this.handle) {
|
|
79
|
-
await this.handle.close();
|
|
80
|
-
this.handle = null;
|
|
81
|
-
}
|
|
82
|
-
const gens = this.maxFiles - 1;
|
|
83
|
-
for (let k = gens; k >= 2; k--) {
|
|
84
|
-
try {
|
|
85
|
-
await (0, promises_1.rename)(`${this.path}.${k - 1}`, `${this.path}.${k}`);
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
/* generation missing — skip */
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
try {
|
|
92
|
-
await (0, promises_1.rename)(this.path, `${this.path}.1`);
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
/* nothing to rotate yet */
|
|
96
|
-
}
|
|
97
|
-
this.size = 0;
|
|
98
|
-
this.sizeInitialized = true;
|
|
99
|
-
await this.ensureHandle();
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Move to a new index file. When `clear` is true the target file is
|
|
103
|
-
* truncated first (used both for normal index advancement and for the
|
|
104
|
-
* wrap-to-01, which must clear the stale `01` slot).
|
|
105
|
-
*/
|
|
106
|
-
async rotateToIndex(idx, clear) {
|
|
107
|
-
if (this.handle) {
|
|
108
|
-
await this.handle.close();
|
|
109
|
-
this.handle = null;
|
|
110
|
-
}
|
|
111
|
-
this.index = idx;
|
|
112
|
-
if (clear) {
|
|
113
|
-
try {
|
|
114
|
-
await (0, promises_1.truncate)(this.activePath(), 0);
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
/* file did not exist yet — fine */
|
|
118
|
-
}
|
|
119
|
-
this.size = 0;
|
|
120
|
-
this.sizeInitialized = true;
|
|
121
|
-
}
|
|
122
|
-
await this.ensureHandle();
|
|
123
|
-
if (!clear) {
|
|
124
|
-
await this.ensureSize();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
write(_entry, formatted) {
|
|
128
|
-
const line = formatted + '\n';
|
|
129
|
-
const bytes = Buffer.byteLength(line, 'utf8');
|
|
130
|
-
const task = this.queue
|
|
131
|
-
.then(async () => {
|
|
132
|
-
if (!this.daily) {
|
|
133
|
-
await this.ensureSize();
|
|
134
|
-
if (this.size + bytes > this.maxSize) {
|
|
135
|
-
await this.rotateSize();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
const today = dateStamp(this.now());
|
|
140
|
-
if (this.currentDate === undefined || today !== this.currentDate) {
|
|
141
|
-
// First open, or a new day: reset to index 01 (resume/append).
|
|
142
|
-
this.currentDate = today;
|
|
143
|
-
this.index = 1;
|
|
144
|
-
await this.rotateToIndex(1, false);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
await this.ensureSize();
|
|
148
|
-
if (this.size + bytes > this.maxSize) {
|
|
149
|
-
let next = this.index + 1;
|
|
150
|
-
if (next > this.maxFiles) {
|
|
151
|
-
next = 1; // wrap and clear the 01 slot
|
|
152
|
-
}
|
|
153
|
-
await this.rotateToIndex(next, true);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
await this.ensureHandle();
|
|
158
|
-
await this.handle.write(line);
|
|
159
|
-
this.size += bytes;
|
|
160
|
-
})
|
|
161
|
-
.catch(() => {
|
|
162
|
-
/* swallow write errors to avoid crashing the app */
|
|
163
|
-
});
|
|
164
|
-
this.queue = task;
|
|
165
|
-
return task;
|
|
166
|
-
}
|
|
167
|
-
async flush() {
|
|
168
|
-
await this.queue;
|
|
169
|
-
}
|
|
170
|
-
async close() {
|
|
171
|
-
await this.queue;
|
|
172
|
-
if (this.handle) {
|
|
173
|
-
await this.handle.close();
|
|
174
|
-
this.handle = null;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
exports.RotatingFileTransport = RotatingFileTransport;
|
|
179
|
-
//# sourceMappingURL=rotating-file.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rotating-file.js","sourceRoot":"","sources":["../../../src/transport/rotating-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { LogEntry } from '../types.js';
|
|
2
|
-
import type { Formatter } from '../pipeline/formatter.js';
|
|
3
|
-
import type { Transport } from './transport.js';
|
|
4
|
-
export interface RotatingFileTransportOptions {
|
|
5
|
-
/** Active (or current-day) log file path, e.g. `/var/log/app.log`. */
|
|
6
|
-
path: string;
|
|
7
|
-
/** Size mode: rotate once the active file exceeds this size in bytes. */
|
|
8
|
-
maxSize?: number;
|
|
9
|
-
/**
|
|
10
|
-
* Maximum number of files in the rotation set.
|
|
11
|
-
* - Size mode: `app.log` + `app.1.log` … (generations). Minimum 2.
|
|
12
|
-
* - Daily mode: `{name}.{YYYY-MM-DD}.01..{maxFiles}.log` per day; when the
|
|
13
|
-
* index would pass `maxFiles` it wraps back to `01` and clears that file.
|
|
14
|
-
* Defaults to 5 (size) or 99 (daily).
|
|
15
|
-
*/
|
|
16
|
-
maxFiles?: number;
|
|
17
|
-
/**
|
|
18
|
-
* Daily mode (default `true`): one dated file per day, split into
|
|
19
|
-
* `01`..`{maxFiles}` indexes. Set `false` for plain size-based generation
|
|
20
|
-
* rotation (`app.log` → `app.1.log` → …) without dates.
|
|
21
|
-
*/
|
|
22
|
-
daily?: boolean;
|
|
23
|
-
/** Override the clock (mainly for testing). Defaults to `new Date()`. */
|
|
24
|
-
now?: () => Date;
|
|
25
|
-
formatter?: Formatter;
|
|
26
|
-
name?: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* File transport with rotation, for the Electron main process (Node.js).
|
|
30
|
-
*
|
|
31
|
-
* Two modes:
|
|
32
|
-
* - **Daily** (default): the active file is
|
|
33
|
-
* `{name}.{YYYY-MM-DD}.{index}.log`, where `index` runs `01`..`maxFiles`
|
|
34
|
-
* (default 99). When it would pass `maxFiles` it wraps back to `01` and
|
|
35
|
-
* that file is cleared — a `maxFiles`-file ring buffer per day. When the
|
|
36
|
-
* local day changes, the index resets to `01` for the new day.
|
|
37
|
-
*/
|
|
38
|
-
export declare class RotatingFileTransport implements Transport {
|
|
39
|
-
readonly name: string;
|
|
40
|
-
readonly formatter: Formatter;
|
|
41
|
-
private readonly path;
|
|
42
|
-
private readonly maxSize;
|
|
43
|
-
private readonly maxFiles;
|
|
44
|
-
private readonly daily;
|
|
45
|
-
private readonly now;
|
|
46
|
-
private handle;
|
|
47
|
-
private queue;
|
|
48
|
-
private size;
|
|
49
|
-
private sizeInitialized;
|
|
50
|
-
private currentDate;
|
|
51
|
-
private index;
|
|
52
|
-
constructor(options: RotatingFileTransportOptions);
|
|
53
|
-
private activePath;
|
|
54
|
-
private ensureHandle;
|
|
55
|
-
private ensureSize;
|
|
56
|
-
private rotateSize;
|
|
57
|
-
/**
|
|
58
|
-
* Move to a new index file. When `clear` is true the target file is
|
|
59
|
-
* truncated first (used both for normal index advancement and for the
|
|
60
|
-
* wrap-to-01, which must clear the stale `01` slot).
|
|
61
|
-
*/
|
|
62
|
-
private rotateToIndex;
|
|
63
|
-
write(_entry: LogEntry, formatted: string): void | Promise<void>;
|
|
64
|
-
flush(): Promise<void>;
|
|
65
|
-
close(): Promise<void>;
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=rotating-file.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rotating-file.d.ts","sourceRoot":"","sources":["../../../src/transport/rotating-file.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,4BAA4B;IAC3C,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAaD;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,YAAW,SAAS;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,MAAM,CAAiD;IAC/D,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,KAAK,CAAK;gBAEN,OAAO,EAAE,4BAA4B;IAkBjD,OAAO,CAAC,UAAU;YAUJ,YAAY;YAOZ,UAAU;YAWV,UAAU;IAuBxB;;;;OAIG;YACW,aAAa;IAqB3B,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { mkdir, open, rename, stat, truncate } from 'node:fs/promises';
|
|
2
|
-
import { dirname, extname } from 'node:path';
|
|
3
|
-
import { createJsonFormatter } from '../pipeline/formatter.js';
|
|
4
|
-
const DEFAULT_MAX_SIZE = 10 * 1024 * 1024;
|
|
5
|
-
const DEFAULT_MAX_FILES = 5;
|
|
6
|
-
const DEFAULT_MAX_FILES_DAILY = 99;
|
|
7
|
-
function dateStamp(d) {
|
|
8
|
-
const y = d.getFullYear();
|
|
9
|
-
const m = String(d.getMonth() + 1).padStart(2, '0');
|
|
10
|
-
const day = String(d.getDate()).padStart(2, '0');
|
|
11
|
-
return `${y}-${m}-${day}`;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* File transport with rotation, for the Electron main process (Node.js).
|
|
15
|
-
*
|
|
16
|
-
* Two modes:
|
|
17
|
-
* - **Daily** (default): the active file is
|
|
18
|
-
* `{name}.{YYYY-MM-DD}.{index}.log`, where `index` runs `01`..`maxFiles`
|
|
19
|
-
* (default 99). When it would pass `maxFiles` it wraps back to `01` and
|
|
20
|
-
* that file is cleared — a `maxFiles`-file ring buffer per day. When the
|
|
21
|
-
* local day changes, the index resets to `01` for the new day.
|
|
22
|
-
*/
|
|
23
|
-
export class RotatingFileTransport {
|
|
24
|
-
constructor(options) {
|
|
25
|
-
this.handle = null;
|
|
26
|
-
this.queue = Promise.resolve();
|
|
27
|
-
this.size = 0;
|
|
28
|
-
this.sizeInitialized = false;
|
|
29
|
-
this.index = 1;
|
|
30
|
-
if (!options.path) {
|
|
31
|
-
throw new Error('RotatingFileTransport requires a "path"');
|
|
32
|
-
}
|
|
33
|
-
this.path = options.path;
|
|
34
|
-
this.daily = options.daily ?? true;
|
|
35
|
-
this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;
|
|
36
|
-
this.maxFiles = options.maxFiles ?? (this.daily ? DEFAULT_MAX_FILES_DAILY : DEFAULT_MAX_FILES);
|
|
37
|
-
if (!this.daily) {
|
|
38
|
-
this.maxFiles = Math.max(2, this.maxFiles);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
this.maxFiles = Math.max(1, this.maxFiles);
|
|
42
|
-
}
|
|
43
|
-
this.now = options.now ?? (() => new Date());
|
|
44
|
-
this.name = options.name ?? `rotating-file:${options.path}`;
|
|
45
|
-
this.formatter = options.formatter ?? createJsonFormatter();
|
|
46
|
-
}
|
|
47
|
-
activePath() {
|
|
48
|
-
if (!this.daily) {
|
|
49
|
-
return this.path;
|
|
50
|
-
}
|
|
51
|
-
const ext = extname(this.path);
|
|
52
|
-
const base = ext ? this.path.slice(0, -ext.length) : this.path;
|
|
53
|
-
const idx = String(this.index).padStart(2, '0');
|
|
54
|
-
return `${base}.${this.currentDate}.${idx}${ext}`;
|
|
55
|
-
}
|
|
56
|
-
async ensureHandle() {
|
|
57
|
-
if (!this.handle) {
|
|
58
|
-
await mkdir(dirname(this.activePath()), { recursive: true });
|
|
59
|
-
this.handle = await open(this.activePath(), 'a');
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
async ensureSize() {
|
|
63
|
-
if (this.sizeInitialized)
|
|
64
|
-
return;
|
|
65
|
-
try {
|
|
66
|
-
const st = await stat(this.activePath());
|
|
67
|
-
this.size = st.size;
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
this.size = 0;
|
|
71
|
-
}
|
|
72
|
-
this.sizeInitialized = true;
|
|
73
|
-
}
|
|
74
|
-
async rotateSize() {
|
|
75
|
-
if (this.handle) {
|
|
76
|
-
await this.handle.close();
|
|
77
|
-
this.handle = null;
|
|
78
|
-
}
|
|
79
|
-
const gens = this.maxFiles - 1;
|
|
80
|
-
for (let k = gens; k >= 2; k--) {
|
|
81
|
-
try {
|
|
82
|
-
await rename(`${this.path}.${k - 1}`, `${this.path}.${k}`);
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
/* generation missing — skip */
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
try {
|
|
89
|
-
await rename(this.path, `${this.path}.1`);
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
/* nothing to rotate yet */
|
|
93
|
-
}
|
|
94
|
-
this.size = 0;
|
|
95
|
-
this.sizeInitialized = true;
|
|
96
|
-
await this.ensureHandle();
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Move to a new index file. When `clear` is true the target file is
|
|
100
|
-
* truncated first (used both for normal index advancement and for the
|
|
101
|
-
* wrap-to-01, which must clear the stale `01` slot).
|
|
102
|
-
*/
|
|
103
|
-
async rotateToIndex(idx, clear) {
|
|
104
|
-
if (this.handle) {
|
|
105
|
-
await this.handle.close();
|
|
106
|
-
this.handle = null;
|
|
107
|
-
}
|
|
108
|
-
this.index = idx;
|
|
109
|
-
if (clear) {
|
|
110
|
-
try {
|
|
111
|
-
await truncate(this.activePath(), 0);
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
/* file did not exist yet — fine */
|
|
115
|
-
}
|
|
116
|
-
this.size = 0;
|
|
117
|
-
this.sizeInitialized = true;
|
|
118
|
-
}
|
|
119
|
-
await this.ensureHandle();
|
|
120
|
-
if (!clear) {
|
|
121
|
-
await this.ensureSize();
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
write(_entry, formatted) {
|
|
125
|
-
const line = formatted + '\n';
|
|
126
|
-
const bytes = Buffer.byteLength(line, 'utf8');
|
|
127
|
-
const task = this.queue
|
|
128
|
-
.then(async () => {
|
|
129
|
-
if (!this.daily) {
|
|
130
|
-
await this.ensureSize();
|
|
131
|
-
if (this.size + bytes > this.maxSize) {
|
|
132
|
-
await this.rotateSize();
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
const today = dateStamp(this.now());
|
|
137
|
-
if (this.currentDate === undefined || today !== this.currentDate) {
|
|
138
|
-
// First open, or a new day: reset to index 01 (resume/append).
|
|
139
|
-
this.currentDate = today;
|
|
140
|
-
this.index = 1;
|
|
141
|
-
await this.rotateToIndex(1, false);
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
await this.ensureSize();
|
|
145
|
-
if (this.size + bytes > this.maxSize) {
|
|
146
|
-
let next = this.index + 1;
|
|
147
|
-
if (next > this.maxFiles) {
|
|
148
|
-
next = 1; // wrap and clear the 01 slot
|
|
149
|
-
}
|
|
150
|
-
await this.rotateToIndex(next, true);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
await this.ensureHandle();
|
|
155
|
-
await this.handle.write(line);
|
|
156
|
-
this.size += bytes;
|
|
157
|
-
})
|
|
158
|
-
.catch(() => {
|
|
159
|
-
/* swallow write errors to avoid crashing the app */
|
|
160
|
-
});
|
|
161
|
-
this.queue = task;
|
|
162
|
-
return task;
|
|
163
|
-
}
|
|
164
|
-
async flush() {
|
|
165
|
-
await this.queue;
|
|
166
|
-
}
|
|
167
|
-
async close() {
|
|
168
|
-
await this.queue;
|
|
169
|
-
if (this.handle) {
|
|
170
|
-
await this.handle.close();
|
|
171
|
-
this.handle = null;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
//# sourceMappingURL=rotating-file.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rotating-file.js","sourceRoot":"","sources":["../../../src/transport/rotating-file.ts"],"names":[],"mappings":"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"}
|