@eggjs/logger 0.0.0 → 4.0.1-beta.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/LICENSE +21 -0
- package/dist/egg/console_logger.d.ts +16 -0
- package/dist/egg/console_logger.js +34 -0
- package/dist/egg/custom_logger.d.ts +10 -0
- package/dist/egg/custom_logger.js +10 -0
- package/dist/egg/error_logger.d.ts +13 -0
- package/dist/egg/error_logger.js +23 -0
- package/dist/egg/logger.d.ts +20 -0
- package/dist/egg/logger.js +92 -0
- package/dist/egg/loggers.d.ts +18 -0
- package/dist/egg/loggers.js +98 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +14 -0
- package/dist/level.d.ts +15 -0
- package/dist/level.js +22 -0
- package/dist/logger.d.ts +41 -0
- package/dist/logger.js +95 -0
- package/dist/transports/console.d.ts +17 -0
- package/dist/transports/console.js +31 -0
- package/dist/transports/file.d.ts +26 -0
- package/dist/transports/file.js +71 -0
- package/dist/transports/file_buffer.d.ts +23 -0
- package/dist/transports/file_buffer.js +57 -0
- package/dist/transports/transport.d.ts +28 -0
- package/dist/transports/transport.js +67 -0
- package/dist/utils.d.ts +75 -0
- package/dist/utils.js +146 -0
- package/dist/vendor.d.ts +8 -0
- package/package.json +47 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017-present Alibaba Group Holding Limited and other contributors.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EggConsoleLoggerOptions } from "../utils.js";
|
|
2
|
+
import { Logger } from "../logger.js";
|
|
3
|
+
|
|
4
|
+
//#region src/egg/console_logger.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Terminal Logger: sends all log output to console.
|
|
8
|
+
* Uses egg's server environment (EGG_SERVER_ENV or options.env) to determine default level.
|
|
9
|
+
* Production (prod) defaults to INFO; other environments default to WARN.
|
|
10
|
+
*/
|
|
11
|
+
declare class EggConsoleLogger extends Logger {
|
|
12
|
+
constructor(options?: Partial<EggConsoleLoggerOptions>);
|
|
13
|
+
get defaults(): Partial<EggConsoleLoggerOptions>;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { EggConsoleLogger };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Logger } from "../logger.js";
|
|
2
|
+
import { assign, consoleFormatter } from "../utils.js";
|
|
3
|
+
import { ConsoleTransport } from "../transports/console.js";
|
|
4
|
+
|
|
5
|
+
//#region src/egg/console_logger.ts
|
|
6
|
+
/**
|
|
7
|
+
* Terminal Logger: sends all log output to console.
|
|
8
|
+
* Uses egg's server environment (EGG_SERVER_ENV or options.env) to determine default level.
|
|
9
|
+
* Production (prod) defaults to INFO; other environments default to WARN.
|
|
10
|
+
*/
|
|
11
|
+
var EggConsoleLogger = class extends Logger {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super();
|
|
14
|
+
const opts = assign({}, this.defaults, options);
|
|
15
|
+
const env = opts.env ?? process.env.EGG_SERVER_ENV ?? "";
|
|
16
|
+
const envLevel = process.env.NODE_CONSOLE_LOGGER_LEVEL;
|
|
17
|
+
const defaultLevel = env === "prod" ? "INFO" : "WARN";
|
|
18
|
+
const level = opts.level ?? envLevel ?? defaultLevel;
|
|
19
|
+
this.set("console", new ConsoleTransport({
|
|
20
|
+
level,
|
|
21
|
+
formatter: consoleFormatter,
|
|
22
|
+
maxCauseChainLength: opts.maxCauseChainLength
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
get defaults() {
|
|
26
|
+
return {
|
|
27
|
+
encoding: "utf8",
|
|
28
|
+
maxCauseChainLength: 10
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { EggConsoleLogger };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EggLoggerOptions } from "../utils.js";
|
|
2
|
+
import { EggLogger } from "./logger.js";
|
|
3
|
+
|
|
4
|
+
//#region src/egg/error_logger.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Error Logger: only prints ERROR level and above.
|
|
8
|
+
*/
|
|
9
|
+
declare class EggErrorLogger extends EggLogger {
|
|
10
|
+
constructor(options?: Partial<EggLoggerOptions>);
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { EggErrorLogger };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { levels } from "../level.js";
|
|
2
|
+
import "../utils.js";
|
|
3
|
+
import { EggLogger } from "./logger.js";
|
|
4
|
+
|
|
5
|
+
//#region src/egg/error_logger.ts
|
|
6
|
+
/**
|
|
7
|
+
* Error Logger: only prints ERROR level and above.
|
|
8
|
+
*/
|
|
9
|
+
var EggErrorLogger = class extends EggLogger {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
const opts = options ?? {};
|
|
12
|
+
opts.level = getMinLevel(opts.level);
|
|
13
|
+
opts.consoleLevel = getMinLevel(opts.consoleLevel);
|
|
14
|
+
super(opts);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
function getMinLevel(level) {
|
|
18
|
+
if (!level) return "ERROR";
|
|
19
|
+
return levels[level] >= levels.ERROR ? level : "ERROR";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { EggErrorLogger };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LoggerLevel } from "../level.js";
|
|
2
|
+
import { EggLoggerOptions } from "../utils.js";
|
|
3
|
+
import { Logger } from "../logger.js";
|
|
4
|
+
|
|
5
|
+
//#region src/egg/logger.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Egg Logger: supports File, BufferedFile and Console transports.
|
|
9
|
+
*/
|
|
10
|
+
declare class EggLogger extends Logger {
|
|
11
|
+
readonly opts: EggLoggerOptions;
|
|
12
|
+
constructor(options?: Partial<EggLoggerOptions>);
|
|
13
|
+
get level(): LoggerLevel;
|
|
14
|
+
set level(level: LoggerLevel);
|
|
15
|
+
get consoleLevel(): LoggerLevel;
|
|
16
|
+
set consoleLevel(level: LoggerLevel);
|
|
17
|
+
get defaults(): Partial<EggLoggerOptions>;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { EggLogger };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Logger } from "../logger.js";
|
|
2
|
+
import { assign, consoleFormatter, defaultFormatter } from "../utils.js";
|
|
3
|
+
import { ConsoleTransport } from "../transports/console.js";
|
|
4
|
+
import { FileTransport } from "../transports/file.js";
|
|
5
|
+
import { FileBufferTransport } from "../transports/file_buffer.js";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
8
|
+
//#region src/egg/logger.ts
|
|
9
|
+
/**
|
|
10
|
+
* Egg Logger: supports File, BufferedFile and Console transports.
|
|
11
|
+
*/
|
|
12
|
+
var EggLogger = class extends Logger {
|
|
13
|
+
opts;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
super();
|
|
16
|
+
this.opts = assign({}, this.defaults, options);
|
|
17
|
+
this.options = this.opts;
|
|
18
|
+
const { opts } = this;
|
|
19
|
+
if (opts.file && opts.dir && !path.isAbsolute(opts.file)) opts.file = path.join(opts.dir, opts.file);
|
|
20
|
+
if (opts.outputJSON === true && opts.file) opts.jsonFile = opts.file.replace(/\.log$/, ".json.log");
|
|
21
|
+
const EggFileTransport = opts.buffer === true ? FileBufferTransport : FileTransport;
|
|
22
|
+
if (!opts.outputJSONOnly && opts.file) this.set("file", new EggFileTransport({
|
|
23
|
+
file: opts.file,
|
|
24
|
+
level: opts.level ?? "INFO",
|
|
25
|
+
encoding: opts.encoding,
|
|
26
|
+
formatter: opts.formatter,
|
|
27
|
+
contextFormatter: opts.contextFormatter,
|
|
28
|
+
paddingMessageFormatter: opts.paddingMessageFormatter,
|
|
29
|
+
flushInterval: opts.flushInterval,
|
|
30
|
+
eol: opts.eol,
|
|
31
|
+
localStorage: opts.localStorage,
|
|
32
|
+
dateISOFormat: opts.dateISOFormat,
|
|
33
|
+
maxCauseChainLength: opts.maxCauseChainLength
|
|
34
|
+
}));
|
|
35
|
+
if (opts.jsonFile) this.set("jsonFile", new EggFileTransport({
|
|
36
|
+
file: opts.jsonFile,
|
|
37
|
+
level: opts.level ?? "INFO",
|
|
38
|
+
encoding: opts.encoding,
|
|
39
|
+
flushInterval: opts.flushInterval,
|
|
40
|
+
json: true,
|
|
41
|
+
eol: opts.eol,
|
|
42
|
+
localStorage: opts.localStorage,
|
|
43
|
+
dateISOFormat: opts.dateISOFormat,
|
|
44
|
+
maxCauseChainLength: opts.maxCauseChainLength
|
|
45
|
+
}));
|
|
46
|
+
this.set("console", new ConsoleTransport({
|
|
47
|
+
level: opts.consoleLevel ?? "NONE",
|
|
48
|
+
formatter: consoleFormatter,
|
|
49
|
+
contextFormatter: opts.contextFormatter,
|
|
50
|
+
paddingMessageFormatter: opts.paddingMessageFormatter,
|
|
51
|
+
eol: opts.eol,
|
|
52
|
+
localStorage: opts.localStorage,
|
|
53
|
+
dateISOFormat: opts.dateISOFormat,
|
|
54
|
+
maxCauseChainLength: opts.maxCauseChainLength
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
get level() {
|
|
58
|
+
return this.opts.level;
|
|
59
|
+
}
|
|
60
|
+
set level(level) {
|
|
61
|
+
this.opts.level = level;
|
|
62
|
+
for (const transport of this.values()) {
|
|
63
|
+
if (transport instanceof ConsoleTransport) continue;
|
|
64
|
+
transport.level = level;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
get consoleLevel() {
|
|
68
|
+
return this.opts.consoleLevel;
|
|
69
|
+
}
|
|
70
|
+
set consoleLevel(level) {
|
|
71
|
+
this.opts.consoleLevel = level;
|
|
72
|
+
for (const transport of this.values()) if (transport instanceof ConsoleTransport) transport.level = level;
|
|
73
|
+
}
|
|
74
|
+
get defaults() {
|
|
75
|
+
return {
|
|
76
|
+
file: null,
|
|
77
|
+
encoding: "utf8",
|
|
78
|
+
level: "INFO",
|
|
79
|
+
consoleLevel: "NONE",
|
|
80
|
+
formatter: defaultFormatter,
|
|
81
|
+
buffer: true,
|
|
82
|
+
outputJSON: false,
|
|
83
|
+
outputJSONOnly: false,
|
|
84
|
+
dateISOFormat: false,
|
|
85
|
+
jsonFile: "",
|
|
86
|
+
maxCauseChainLength: 10
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
//#endregion
|
|
92
|
+
export { EggLogger };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EggLoggersConfig } from "../utils.js";
|
|
2
|
+
import { Logger } from "../logger.js";
|
|
3
|
+
|
|
4
|
+
//#region src/egg/loggers.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Logger Manager - creates and manages multiple loggers based on configuration.
|
|
8
|
+
*/
|
|
9
|
+
declare class EggLoggers extends Map<string, Logger> {
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
constructor(config: EggLoggersConfig);
|
|
12
|
+
set(name: string, logger: Logger): this;
|
|
13
|
+
disableConsole(): void;
|
|
14
|
+
reload(): void;
|
|
15
|
+
setConcentrateError(name: string, logger: Logger): void;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { EggLoggers };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { assign } from "../utils.js";
|
|
2
|
+
import { EggLogger } from "./logger.js";
|
|
3
|
+
import { EggErrorLogger } from "./error_logger.js";
|
|
4
|
+
import { EggCustomLogger } from "./custom_logger.js";
|
|
5
|
+
import { debuglog } from "node:util";
|
|
6
|
+
import assert from "node:assert";
|
|
7
|
+
|
|
8
|
+
//#region src/egg/loggers.ts
|
|
9
|
+
const debug = debuglog("egg:logger");
|
|
10
|
+
const defaults = {
|
|
11
|
+
env: "default",
|
|
12
|
+
type: "",
|
|
13
|
+
dir: "",
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
level: "INFO",
|
|
16
|
+
outputJSON: false,
|
|
17
|
+
outputJSONOnly: false,
|
|
18
|
+
buffer: true,
|
|
19
|
+
appLogName: "",
|
|
20
|
+
coreLogName: "",
|
|
21
|
+
agentLogName: "",
|
|
22
|
+
errorLogName: "",
|
|
23
|
+
concentrateError: "duplicate",
|
|
24
|
+
concentrateErrorLoggerName: "errorLogger"
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Logger Manager - creates and manages multiple loggers based on configuration.
|
|
28
|
+
*/
|
|
29
|
+
var EggLoggers = class extends Map {
|
|
30
|
+
constructor(config) {
|
|
31
|
+
super();
|
|
32
|
+
const loggerConfig = assign({}, defaults, config.logger);
|
|
33
|
+
if (loggerConfig.consoleLevel === void 0) {
|
|
34
|
+
const env = loggerConfig.env ?? "default";
|
|
35
|
+
loggerConfig.consoleLevel = env === "local" || env === "unittest" ? "INFO" : "NONE";
|
|
36
|
+
}
|
|
37
|
+
const customLoggerConfig = config.customLogger ?? {};
|
|
38
|
+
debug("Init loggers with options %j", loggerConfig);
|
|
39
|
+
assert(loggerConfig.type, "should pass config.logger.type");
|
|
40
|
+
assert(loggerConfig.dir, "should pass config.logger.dir");
|
|
41
|
+
assert(loggerConfig.appLogName, "should pass config.logger.appLogName");
|
|
42
|
+
assert(loggerConfig.coreLogName, "should pass config.logger.coreLogName");
|
|
43
|
+
assert(loggerConfig.agentLogName, "should pass config.logger.agentLogName");
|
|
44
|
+
assert(loggerConfig.errorLogName, "should pass config.logger.errorLogName");
|
|
45
|
+
const errorLogger = new EggErrorLogger(assign({}, loggerConfig, { file: loggerConfig.errorLogName }));
|
|
46
|
+
this.set("errorLogger", errorLogger);
|
|
47
|
+
let coreLogger;
|
|
48
|
+
let logger;
|
|
49
|
+
if (loggerConfig.type === "agent") {
|
|
50
|
+
logger = new EggLogger(assign({}, loggerConfig, { file: loggerConfig.agentLogName }));
|
|
51
|
+
coreLogger = new EggLogger(assign({}, loggerConfig, loggerConfig.coreLogger, { file: loggerConfig.agentLogName }));
|
|
52
|
+
} else {
|
|
53
|
+
logger = new EggLogger(assign({}, loggerConfig, { file: loggerConfig.appLogName }));
|
|
54
|
+
coreLogger = new EggLogger(assign({}, loggerConfig, loggerConfig.coreLogger, { file: loggerConfig.coreLogName }));
|
|
55
|
+
}
|
|
56
|
+
this.set("logger", logger);
|
|
57
|
+
this.set("coreLogger", coreLogger);
|
|
58
|
+
for (const name in customLoggerConfig) {
|
|
59
|
+
const customLogger = new EggCustomLogger(assign({}, loggerConfig, customLoggerConfig[name]));
|
|
60
|
+
this.set(name, customLogger);
|
|
61
|
+
}
|
|
62
|
+
this.setConcentrateError("logger", logger);
|
|
63
|
+
this.setConcentrateError("coreLogger", coreLogger);
|
|
64
|
+
for (const name in customLoggerConfig) this.setConcentrateError(name, this.get(name));
|
|
65
|
+
}
|
|
66
|
+
set(name, logger) {
|
|
67
|
+
if (this.has(name)) return this;
|
|
68
|
+
this[name] = logger;
|
|
69
|
+
super.set(name, logger);
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
disableConsole() {
|
|
73
|
+
for (const logger of this.values()) logger.disable("console");
|
|
74
|
+
}
|
|
75
|
+
reload() {
|
|
76
|
+
for (const logger of this.values()) logger.reload();
|
|
77
|
+
}
|
|
78
|
+
setConcentrateError(name, logger) {
|
|
79
|
+
if (name === "errorLogger") return;
|
|
80
|
+
const opts = logger.opts;
|
|
81
|
+
const concentrateLoggerName = opts.concentrateErrorLoggerName ?? "errorLogger";
|
|
82
|
+
const concentrateLogger = this.get(concentrateLoggerName);
|
|
83
|
+
if (!concentrateLogger) return;
|
|
84
|
+
switch (opts.concentrateError) {
|
|
85
|
+
case "duplicate":
|
|
86
|
+
logger.duplicate("ERROR", concentrateLogger, { excludes: ["console"] });
|
|
87
|
+
break;
|
|
88
|
+
case "redirect":
|
|
89
|
+
logger.redirect("ERROR", concentrateLogger);
|
|
90
|
+
break;
|
|
91
|
+
case "ignore": break;
|
|
92
|
+
default: break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
98
|
+
export { EggLoggers };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ALL, DEBUG, ERROR, INFO, LoggerLevel, NONE, WARN, levels } from "./level.js";
|
|
2
|
+
import { ConsoleTransportOptions, EggConsoleLoggerOptions, EggLoggerOptions, EggLoggersConfig, EggLoggersOptions, FileTransportOptions, LoggerMeta, TransportOptions, consoleFormatter, defaultContextPaddingMessage, defaultFormatter, formatError } from "./utils.js";
|
|
3
|
+
import { Transport } from "./transports/transport.js";
|
|
4
|
+
import { Logger } from "./logger.js";
|
|
5
|
+
import { EggConsoleLogger } from "./egg/console_logger.js";
|
|
6
|
+
import { EggLogger } from "./egg/logger.js";
|
|
7
|
+
import { EggCustomLogger } from "./egg/custom_logger.js";
|
|
8
|
+
import { EggErrorLogger } from "./egg/error_logger.js";
|
|
9
|
+
import { EggLoggers } from "./egg/loggers.js";
|
|
10
|
+
import { ConsoleTransport } from "./transports/console.js";
|
|
11
|
+
import { FileTransport } from "./transports/file.js";
|
|
12
|
+
import { FileBufferTransport } from "./transports/file_buffer.js";
|
|
13
|
+
export { ALL, ConsoleTransport, type ConsoleTransportOptions, DEBUG, ERROR, EggConsoleLogger, type EggConsoleLoggerOptions, EggCustomLogger, EggErrorLogger, EggLogger, type EggLoggerOptions, EggLoggers, type EggLoggersConfig, type EggLoggersOptions, FileBufferTransport, FileTransport, type FileTransportOptions, INFO, Logger, type LoggerLevel, type LoggerMeta, NONE, Transport, type TransportOptions, WARN, consoleFormatter, defaultContextPaddingMessage, defaultFormatter, formatError, levels };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ALL, DEBUG, ERROR, INFO, NONE, WARN, levels } from "./level.js";
|
|
2
|
+
import { Logger } from "./logger.js";
|
|
3
|
+
import { consoleFormatter, defaultContextPaddingMessage, defaultFormatter, formatError } from "./utils.js";
|
|
4
|
+
import { Transport } from "./transports/transport.js";
|
|
5
|
+
import { ConsoleTransport } from "./transports/console.js";
|
|
6
|
+
import { FileTransport } from "./transports/file.js";
|
|
7
|
+
import { FileBufferTransport } from "./transports/file_buffer.js";
|
|
8
|
+
import { EggLogger } from "./egg/logger.js";
|
|
9
|
+
import { EggErrorLogger } from "./egg/error_logger.js";
|
|
10
|
+
import { EggConsoleLogger } from "./egg/console_logger.js";
|
|
11
|
+
import { EggCustomLogger } from "./egg/custom_logger.js";
|
|
12
|
+
import { EggLoggers } from "./egg/loggers.js";
|
|
13
|
+
|
|
14
|
+
export { ALL, ConsoleTransport, DEBUG, ERROR, EggConsoleLogger, EggCustomLogger, EggErrorLogger, EggLogger, EggLoggers, FileBufferTransport, FileTransport, INFO, Logger, NONE, Transport, WARN, consoleFormatter, defaultContextPaddingMessage, defaultFormatter, formatError, levels };
|
package/dist/level.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/level.d.ts
|
|
2
|
+
declare const ALL: number;
|
|
3
|
+
/** Debug log for execute tracing */
|
|
4
|
+
declare const DEBUG: number;
|
|
5
|
+
/** Normal information logging */
|
|
6
|
+
declare const INFO: number;
|
|
7
|
+
/** Warning information logging */
|
|
8
|
+
declare const WARN: number;
|
|
9
|
+
/** Error or exception logging */
|
|
10
|
+
declare const ERROR: number;
|
|
11
|
+
declare const NONE: number;
|
|
12
|
+
type LoggerLevel = "ALL" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "NONE";
|
|
13
|
+
declare const levels: Record<string, number>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ALL, DEBUG, ERROR, INFO, LoggerLevel, NONE, WARN, levels };
|
package/dist/level.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/level.ts
|
|
2
|
+
const ALL = -Infinity;
|
|
3
|
+
/** Debug log for execute tracing */
|
|
4
|
+
const DEBUG = 0;
|
|
5
|
+
/** Normal information logging */
|
|
6
|
+
const INFO = 1;
|
|
7
|
+
/** Warning information logging */
|
|
8
|
+
const WARN = 2;
|
|
9
|
+
/** Error or exception logging */
|
|
10
|
+
const ERROR = 3;
|
|
11
|
+
const NONE = Infinity;
|
|
12
|
+
const levels = {
|
|
13
|
+
ALL,
|
|
14
|
+
DEBUG,
|
|
15
|
+
INFO,
|
|
16
|
+
WARN,
|
|
17
|
+
ERROR,
|
|
18
|
+
NONE
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { ALL, DEBUG, ERROR, INFO, NONE, WARN, levels };
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { LoggerMeta } from "./utils.js";
|
|
2
|
+
import { Transport } from "./transports/transport.js";
|
|
3
|
+
|
|
4
|
+
//#region src/logger.d.ts
|
|
5
|
+
interface DuplicateLoggerEntry {
|
|
6
|
+
logger: Logger;
|
|
7
|
+
options: {
|
|
8
|
+
excludes?: string[];
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Base class for all Logger classes.
|
|
13
|
+
* It extends Map and can contain multiple Transports.
|
|
14
|
+
*/
|
|
15
|
+
declare class Logger<T extends Transport = Transport> extends Map<string, T> {
|
|
16
|
+
options: Record<string, unknown>;
|
|
17
|
+
name: string;
|
|
18
|
+
redirectLoggers: Map<string, Logger>;
|
|
19
|
+
duplicateLoggers: Map<string, DuplicateLoggerEntry>;
|
|
20
|
+
constructor(options?: Record<string, unknown>);
|
|
21
|
+
disable(name: string): void;
|
|
22
|
+
enable(name: string): void;
|
|
23
|
+
log(level: string, args: unknown[], meta?: LoggerMeta): void;
|
|
24
|
+
write(msg: string, ...rest: unknown[]): void;
|
|
25
|
+
redirect(level: string, logger: Logger): void;
|
|
26
|
+
unredirect(level: string): void;
|
|
27
|
+
duplicate(level: string, logger: Logger, options?: {
|
|
28
|
+
excludes?: string[];
|
|
29
|
+
}): void;
|
|
30
|
+
unduplicate(level: string): void;
|
|
31
|
+
reload(): void;
|
|
32
|
+
close(): void;
|
|
33
|
+
/** @deprecated use close() instead */
|
|
34
|
+
end(): void;
|
|
35
|
+
error(...args: unknown[]): void;
|
|
36
|
+
warn(...args: unknown[]): void;
|
|
37
|
+
info(...args: unknown[]): void;
|
|
38
|
+
debug(...args: unknown[]): void;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { DuplicateLoggerEntry, Logger };
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import util from "node:util";
|
|
2
|
+
|
|
3
|
+
//#region src/logger.ts
|
|
4
|
+
/**
|
|
5
|
+
* Base class for all Logger classes.
|
|
6
|
+
* It extends Map and can contain multiple Transports.
|
|
7
|
+
*/
|
|
8
|
+
var Logger = class Logger extends Map {
|
|
9
|
+
options;
|
|
10
|
+
name;
|
|
11
|
+
redirectLoggers;
|
|
12
|
+
duplicateLoggers;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
super();
|
|
15
|
+
this.options = Object.assign({}, options);
|
|
16
|
+
this.name = this.constructor.name;
|
|
17
|
+
this.redirectLoggers = /* @__PURE__ */ new Map();
|
|
18
|
+
this.duplicateLoggers = /* @__PURE__ */ new Map();
|
|
19
|
+
}
|
|
20
|
+
disable(name) {
|
|
21
|
+
const transport = this.get(name);
|
|
22
|
+
if (transport) transport.disable();
|
|
23
|
+
}
|
|
24
|
+
enable(name) {
|
|
25
|
+
const transport = this.get(name);
|
|
26
|
+
if (transport) transport.enable();
|
|
27
|
+
}
|
|
28
|
+
log(level, args, meta) {
|
|
29
|
+
let excludes;
|
|
30
|
+
const dupEntry = this.duplicateLoggers.get(level);
|
|
31
|
+
let dupLogger;
|
|
32
|
+
if (dupEntry) {
|
|
33
|
+
excludes = dupEntry.options.excludes;
|
|
34
|
+
dupLogger = dupEntry.logger;
|
|
35
|
+
dupLogger.log(level, args, meta);
|
|
36
|
+
} else {
|
|
37
|
+
const redirectLogger = this.redirectLoggers.get(level);
|
|
38
|
+
if (redirectLogger) {
|
|
39
|
+
redirectLogger.log(level, args, meta);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
for (const [key, transport] of this.entries()) if (transport.shouldLog(level) && !(excludes && excludes.includes(key))) transport.log(level, args, meta);
|
|
44
|
+
}
|
|
45
|
+
write(msg, ...rest) {
|
|
46
|
+
if (rest.length > 0) msg = util.format(msg, ...rest);
|
|
47
|
+
this.log("NONE", [msg], { raw: true });
|
|
48
|
+
}
|
|
49
|
+
redirect(level, logger) {
|
|
50
|
+
const lvl = level.toUpperCase();
|
|
51
|
+
if (!this.redirectLoggers.has(lvl) && logger instanceof Logger) this.redirectLoggers.set(lvl, logger);
|
|
52
|
+
}
|
|
53
|
+
unredirect(level) {
|
|
54
|
+
this.redirectLoggers.delete(level.toUpperCase());
|
|
55
|
+
}
|
|
56
|
+
duplicate(level, logger, options = {}) {
|
|
57
|
+
const lvl = level.toUpperCase();
|
|
58
|
+
if (!this.duplicateLoggers.has(lvl) && logger instanceof Logger) this.duplicateLoggers.set(lvl, {
|
|
59
|
+
logger,
|
|
60
|
+
options
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
unduplicate(level) {
|
|
64
|
+
this.duplicateLoggers.delete(level.toUpperCase());
|
|
65
|
+
}
|
|
66
|
+
reload() {
|
|
67
|
+
for (const transport of this.values()) transport.reload();
|
|
68
|
+
}
|
|
69
|
+
close() {
|
|
70
|
+
for (const transport of this.values()) transport.close();
|
|
71
|
+
}
|
|
72
|
+
/** @deprecated use close() instead */
|
|
73
|
+
end() {
|
|
74
|
+
process.emitWarning("logger.end() is deprecated, use logger.close()", {
|
|
75
|
+
type: "DeprecationWarning",
|
|
76
|
+
code: "DEP_EGG_LOGGER_END"
|
|
77
|
+
});
|
|
78
|
+
this.close();
|
|
79
|
+
}
|
|
80
|
+
error(...args) {
|
|
81
|
+
this.log("ERROR", args);
|
|
82
|
+
}
|
|
83
|
+
warn(...args) {
|
|
84
|
+
this.log("WARN", args);
|
|
85
|
+
}
|
|
86
|
+
info(...args) {
|
|
87
|
+
this.log("INFO", args);
|
|
88
|
+
}
|
|
89
|
+
debug(...args) {
|
|
90
|
+
this.log("DEBUG", args);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
//#endregion
|
|
95
|
+
export { Logger };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ConsoleTransportOptions, LoggerMeta } from "../utils.js";
|
|
2
|
+
import { Transport } from "./transport.js";
|
|
3
|
+
|
|
4
|
+
//#region src/transports/console.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Output log to console.
|
|
8
|
+
* EGG_LOG env variable has the highest priority for log level.
|
|
9
|
+
*/
|
|
10
|
+
declare class ConsoleTransport extends Transport {
|
|
11
|
+
options: ConsoleTransportOptions;
|
|
12
|
+
constructor(options?: Partial<ConsoleTransportOptions>);
|
|
13
|
+
get defaults(): Partial<ConsoleTransportOptions>;
|
|
14
|
+
log(level: string, args: unknown[], meta?: LoggerMeta): string | Buffer;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { ConsoleTransport };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { levels } from "../level.js";
|
|
2
|
+
import { normalizeLevel } from "../utils.js";
|
|
3
|
+
import { Transport } from "./transport.js";
|
|
4
|
+
|
|
5
|
+
//#region src/transports/console.ts
|
|
6
|
+
/**
|
|
7
|
+
* Output log to console.
|
|
8
|
+
* EGG_LOG env variable has the highest priority for log level.
|
|
9
|
+
*/
|
|
10
|
+
var ConsoleTransport = class extends Transport {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
super(options);
|
|
13
|
+
this.options.stderrLevel = normalizeLevel(this.options.stderrLevel);
|
|
14
|
+
if (process.env.EGG_LOG) this.options.level = normalizeLevel(process.env.EGG_LOG);
|
|
15
|
+
}
|
|
16
|
+
get defaults() {
|
|
17
|
+
return {
|
|
18
|
+
...super.defaults,
|
|
19
|
+
stderrLevel: "ERROR"
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
log(level, args, meta) {
|
|
23
|
+
const msg = super.log(level, args, meta);
|
|
24
|
+
if (levels[level] >= this.options.stderrLevel && levels[level] < levels["NONE"]) process.stderr.write(msg);
|
|
25
|
+
else process.stdout.write(msg);
|
|
26
|
+
return msg;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { ConsoleTransport };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FileTransportOptions, LoggerMeta } from "../utils.js";
|
|
2
|
+
import { Transport } from "./transport.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
|
|
5
|
+
//#region src/transports/file.d.ts
|
|
6
|
+
type WriteStream = fs.WriteStream & {
|
|
7
|
+
_onError?: (err: Error) => void;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Output log to file.
|
|
11
|
+
*/
|
|
12
|
+
declare class FileTransport extends Transport {
|
|
13
|
+
options: FileTransportOptions;
|
|
14
|
+
_stream: WriteStream | null;
|
|
15
|
+
constructor(options?: Partial<FileTransportOptions>);
|
|
16
|
+
get defaults(): Partial<FileTransportOptions>;
|
|
17
|
+
reload(): void;
|
|
18
|
+
log(level: string, args: unknown[], meta?: LoggerMeta): string | Buffer;
|
|
19
|
+
close(): void;
|
|
20
|
+
get writable(): boolean;
|
|
21
|
+
_write(buf: string | Buffer): void;
|
|
22
|
+
_createStream(): WriteStream;
|
|
23
|
+
_closeStream(): void;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { FileTransport };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import "../utils.js";
|
|
2
|
+
import { Transport } from "./transport.js";
|
|
3
|
+
import { logDate } from "utility";
|
|
4
|
+
import assert from "node:assert";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
8
|
+
//#region src/transports/file.ts
|
|
9
|
+
/**
|
|
10
|
+
* Output log to file.
|
|
11
|
+
*/
|
|
12
|
+
var FileTransport = class extends Transport {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
super(options);
|
|
15
|
+
assert(this.options.file, "should pass options.file");
|
|
16
|
+
this._stream = null;
|
|
17
|
+
this.reload();
|
|
18
|
+
}
|
|
19
|
+
get defaults() {
|
|
20
|
+
return {
|
|
21
|
+
...super.defaults,
|
|
22
|
+
file: null,
|
|
23
|
+
level: "INFO"
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
reload() {
|
|
27
|
+
this._closeStream();
|
|
28
|
+
this._stream = this._createStream();
|
|
29
|
+
}
|
|
30
|
+
log(level, args, meta) {
|
|
31
|
+
if (!this.writable) {
|
|
32
|
+
const err = /* @__PURE__ */ new Error(`${this.options.file} log stream had been closed`);
|
|
33
|
+
console.error(err.stack);
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
const buf = super.log(level, args, meta);
|
|
37
|
+
if (buf.length) this._write(buf);
|
|
38
|
+
return buf;
|
|
39
|
+
}
|
|
40
|
+
close() {
|
|
41
|
+
this._closeStream();
|
|
42
|
+
}
|
|
43
|
+
get writable() {
|
|
44
|
+
return !!(this._stream && !this._stream.closed && this._stream.writable && !this._stream.destroyed);
|
|
45
|
+
}
|
|
46
|
+
_write(buf) {
|
|
47
|
+
this._stream.write(buf);
|
|
48
|
+
}
|
|
49
|
+
_createStream() {
|
|
50
|
+
fs.mkdirSync(path.dirname(this.options.file), { recursive: true });
|
|
51
|
+
const stream = fs.createWriteStream(this.options.file, { flags: "a" });
|
|
52
|
+
const onError = (err) => {
|
|
53
|
+
console.error("%s ERROR %s [egg-logger] [%s] %s", logDate(","), process.pid, this.options.file, err.stack);
|
|
54
|
+
this.reload();
|
|
55
|
+
console.warn("%s WARN %s [egg-logger] [%s] reloaded", logDate(","), process.pid, this.options.file);
|
|
56
|
+
};
|
|
57
|
+
stream.once("error", onError);
|
|
58
|
+
stream._onError = onError;
|
|
59
|
+
return stream;
|
|
60
|
+
}
|
|
61
|
+
_closeStream() {
|
|
62
|
+
if (this._stream) {
|
|
63
|
+
this._stream.end();
|
|
64
|
+
if (this._stream._onError) this._stream.removeListener("error", this._stream._onError);
|
|
65
|
+
this._stream = null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
export { FileTransport };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FileTransportOptions } from "../utils.js";
|
|
2
|
+
import { FileTransport } from "./file.js";
|
|
3
|
+
|
|
4
|
+
//#region src/transports/file_buffer.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extends FileTransport, saves log in memory and flushes to file at intervals.
|
|
8
|
+
*/
|
|
9
|
+
declare class FileBufferTransport extends FileTransport {
|
|
10
|
+
_bufSize: number;
|
|
11
|
+
_buf: Array<string | Buffer>;
|
|
12
|
+
_timer: ReturnType<typeof setInterval> | null;
|
|
13
|
+
constructor(options?: Partial<FileTransportOptions>);
|
|
14
|
+
get defaults(): Partial<FileTransportOptions>;
|
|
15
|
+
close(): void;
|
|
16
|
+
flush(): void;
|
|
17
|
+
_closeStream(): void;
|
|
18
|
+
_write(buf: string | Buffer): void;
|
|
19
|
+
_createInterval(): ReturnType<typeof setInterval>;
|
|
20
|
+
_closeInterval(): void;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { FileBufferTransport };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import "../utils.js";
|
|
2
|
+
import { FileTransport } from "./file.js";
|
|
3
|
+
|
|
4
|
+
//#region src/transports/file_buffer.ts
|
|
5
|
+
/**
|
|
6
|
+
* Extends FileTransport, saves log in memory and flushes to file at intervals.
|
|
7
|
+
*/
|
|
8
|
+
var FileBufferTransport = class extends FileTransport {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
super(options);
|
|
11
|
+
this._bufSize = 0;
|
|
12
|
+
this._buf = [];
|
|
13
|
+
this._timer = this._createInterval();
|
|
14
|
+
}
|
|
15
|
+
get defaults() {
|
|
16
|
+
return {
|
|
17
|
+
...super.defaults,
|
|
18
|
+
flushInterval: 1e3,
|
|
19
|
+
maxBufferLength: 1e3
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
close() {
|
|
23
|
+
this._closeInterval();
|
|
24
|
+
super.close();
|
|
25
|
+
}
|
|
26
|
+
flush() {
|
|
27
|
+
if (this._buf.length > 0 && this.writable) {
|
|
28
|
+
if (this.options.encoding === "utf8") this._stream.write(this._buf.join(""));
|
|
29
|
+
else this._stream.write(Buffer.concat(this._buf, this._bufSize));
|
|
30
|
+
this._buf = [];
|
|
31
|
+
this._bufSize = 0;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
_closeStream() {
|
|
35
|
+
if (this._buf && this._buf.length > 0) this.flush();
|
|
36
|
+
super._closeStream();
|
|
37
|
+
}
|
|
38
|
+
_write(buf) {
|
|
39
|
+
this._bufSize += typeof buf === "string" ? Buffer.byteLength(buf) : buf.length;
|
|
40
|
+
this._buf.push(buf);
|
|
41
|
+
if (this._buf.length > (this.options.maxBufferLength ?? 1e3)) this.flush();
|
|
42
|
+
}
|
|
43
|
+
_createInterval() {
|
|
44
|
+
const timer = setInterval(() => this.flush(), this.options.flushInterval ?? 1e3);
|
|
45
|
+
timer.unref();
|
|
46
|
+
return timer;
|
|
47
|
+
}
|
|
48
|
+
_closeInterval() {
|
|
49
|
+
if (this._timer) {
|
|
50
|
+
clearInterval(this._timer);
|
|
51
|
+
this._timer = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { FileBufferTransport };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LoggerLevel } from "../level.js";
|
|
2
|
+
import { LoggerMeta, TransportOptions } from "../utils.js";
|
|
3
|
+
|
|
4
|
+
//#region src/transports/transport.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Transport is an output channel of the log that can be output to a file,
|
|
8
|
+
* console or service.
|
|
9
|
+
* A Logger can configure multiple Transports to meet a variety of complex needs.
|
|
10
|
+
*/
|
|
11
|
+
declare class Transport {
|
|
12
|
+
#private;
|
|
13
|
+
options: TransportOptions;
|
|
14
|
+
constructor(options?: Partial<TransportOptions>);
|
|
15
|
+
get defaults(): Partial<TransportOptions>;
|
|
16
|
+
get enabled(): boolean;
|
|
17
|
+
enable(): void;
|
|
18
|
+
disable(): void;
|
|
19
|
+
set level(level: LoggerLevel | number);
|
|
20
|
+
get level(): number;
|
|
21
|
+
shouldLog(level: string): boolean;
|
|
22
|
+
log(level: string, args: unknown[], meta?: LoggerMeta): string | Buffer;
|
|
23
|
+
reload(): void;
|
|
24
|
+
close(): void;
|
|
25
|
+
end(): void;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { Transport, type TransportOptions };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { levels } from "../level.js";
|
|
2
|
+
import { assign, formatLog, normalizeLevel } from "../utils.js";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
|
|
5
|
+
//#region src/transports/transport.ts
|
|
6
|
+
/**
|
|
7
|
+
* Transport is an output channel of the log that can be output to a file,
|
|
8
|
+
* console or service.
|
|
9
|
+
* A Logger can configure multiple Transports to meet a variety of complex needs.
|
|
10
|
+
*/
|
|
11
|
+
var Transport = class {
|
|
12
|
+
options;
|
|
13
|
+
#enabled = true;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = assign({}, this.defaults, options);
|
|
16
|
+
if (this.options.encoding === "utf-8") this.options.encoding = "utf8";
|
|
17
|
+
const normalizedLevel = normalizeLevel(this.options.level);
|
|
18
|
+
if (normalizedLevel !== void 0) this.options.level = normalizedLevel;
|
|
19
|
+
}
|
|
20
|
+
get defaults() {
|
|
21
|
+
return {
|
|
22
|
+
level: "NONE",
|
|
23
|
+
formatter: null,
|
|
24
|
+
contextFormatter: null,
|
|
25
|
+
json: false,
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
eol: os.EOL
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
get enabled() {
|
|
31
|
+
return this.#enabled;
|
|
32
|
+
}
|
|
33
|
+
enable() {
|
|
34
|
+
this.#enabled = true;
|
|
35
|
+
}
|
|
36
|
+
disable() {
|
|
37
|
+
this.#enabled = false;
|
|
38
|
+
}
|
|
39
|
+
set level(level) {
|
|
40
|
+
const normalized = normalizeLevel(level);
|
|
41
|
+
if (normalized !== void 0) this.options.level = normalized;
|
|
42
|
+
}
|
|
43
|
+
get level() {
|
|
44
|
+
return this.options.level;
|
|
45
|
+
}
|
|
46
|
+
shouldLog(level) {
|
|
47
|
+
if (!this.#enabled) return false;
|
|
48
|
+
if (this.options.level === levels["NONE"]) return false;
|
|
49
|
+
return this.options.level <= levels[level];
|
|
50
|
+
}
|
|
51
|
+
log(level, args, meta) {
|
|
52
|
+
if (!meta?.ctx && this.options.localStorage) {
|
|
53
|
+
const ctx = this.options.localStorage.getStore();
|
|
54
|
+
if (ctx) meta = {
|
|
55
|
+
...meta,
|
|
56
|
+
ctx
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return formatLog(level, args, meta, this.options);
|
|
60
|
+
}
|
|
61
|
+
reload() {}
|
|
62
|
+
close() {}
|
|
63
|
+
end() {}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { Transport };
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { LoggerLevel } from "./level.js";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
|
|
4
|
+
//#region src/utils.d.ts
|
|
5
|
+
interface LoggerMeta {
|
|
6
|
+
level?: string;
|
|
7
|
+
date?: string;
|
|
8
|
+
pid?: number;
|
|
9
|
+
hostname?: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
paddingMessage?: string;
|
|
12
|
+
ctx?: unknown;
|
|
13
|
+
raw?: boolean;
|
|
14
|
+
formatter?: (meta: LoggerMeta) => string;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
interface TransportOptions {
|
|
18
|
+
level?: LoggerLevel | number;
|
|
19
|
+
formatter?: ((meta: LoggerMeta) => string) | null;
|
|
20
|
+
contextFormatter?: ((meta: LoggerMeta) => string) | null;
|
|
21
|
+
paddingMessageFormatter?: ((ctx: unknown) => string) | null;
|
|
22
|
+
json?: boolean;
|
|
23
|
+
dateISOFormat?: boolean;
|
|
24
|
+
encoding?: string;
|
|
25
|
+
eol?: string;
|
|
26
|
+
localStorage?: AsyncLocalStorage<unknown>;
|
|
27
|
+
maxCauseChainLength?: number;
|
|
28
|
+
}
|
|
29
|
+
interface FileTransportOptions extends TransportOptions {
|
|
30
|
+
file?: string | null;
|
|
31
|
+
flushInterval?: number;
|
|
32
|
+
maxBufferLength?: number;
|
|
33
|
+
}
|
|
34
|
+
interface ConsoleTransportOptions extends TransportOptions {
|
|
35
|
+
stderrLevel?: LoggerLevel | number;
|
|
36
|
+
}
|
|
37
|
+
interface EggLoggerOptions extends Omit<TransportOptions, "level"> {
|
|
38
|
+
level?: LoggerLevel;
|
|
39
|
+
consoleLevel?: LoggerLevel;
|
|
40
|
+
file?: string | null;
|
|
41
|
+
dir?: string;
|
|
42
|
+
buffer?: boolean;
|
|
43
|
+
outputJSON?: boolean;
|
|
44
|
+
outputJSONOnly?: boolean;
|
|
45
|
+
jsonFile?: string;
|
|
46
|
+
concentrateError?: "duplicate" | "redirect" | "ignore";
|
|
47
|
+
concentrateErrorLoggerName?: string;
|
|
48
|
+
flushInterval?: number;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
interface EggLoggersOptions extends EggLoggerOptions {
|
|
52
|
+
type: string;
|
|
53
|
+
env?: string;
|
|
54
|
+
appLogName: string;
|
|
55
|
+
coreLogName: string;
|
|
56
|
+
agentLogName: string;
|
|
57
|
+
errorLogName: string;
|
|
58
|
+
coreLogger?: Partial<EggLoggersOptions>;
|
|
59
|
+
}
|
|
60
|
+
interface EggConsoleLoggerOptions extends TransportOptions {
|
|
61
|
+
env?: string;
|
|
62
|
+
}
|
|
63
|
+
interface EggLoggersConfig {
|
|
64
|
+
logger: EggLoggersOptions;
|
|
65
|
+
customLogger?: Record<string, EggLoggerOptions>;
|
|
66
|
+
}
|
|
67
|
+
declare function normalizeLevel(level?: LoggerLevel | number | string): number | undefined;
|
|
68
|
+
declare function defaultContextPaddingMessage(ctx: Record<string, unknown>): string;
|
|
69
|
+
declare function defaultFormatter(meta: LoggerMeta): string;
|
|
70
|
+
declare function consoleFormatter(meta: LoggerMeta): string;
|
|
71
|
+
declare function formatLog(level: string, args: unknown[], meta: LoggerMeta | undefined, options: TransportOptions): string | Buffer;
|
|
72
|
+
declare function assign<T>(target: Partial<T>, ...sources: Array<Partial<T> | null | undefined>): T;
|
|
73
|
+
declare function formatError(err: Error, options?: TransportOptions, causeLength?: number): string;
|
|
74
|
+
//#endregion
|
|
75
|
+
export { ConsoleTransportOptions, EggConsoleLoggerOptions, EggLoggerOptions, EggLoggersConfig, EggLoggersOptions, FileTransportOptions, LoggerMeta, TransportOptions, assign, consoleFormatter, defaultContextPaddingMessage, defaultFormatter, formatError, formatLog, normalizeLevel };
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { levels } from "./level.js";
|
|
2
|
+
import util from "node:util";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { performance } from "node:perf_hooks";
|
|
5
|
+
import { FrameworkBaseError, FrameworkErrorFormatter } from "@eggjs/errors";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import circularJSON from "circular-json-for-egg";
|
|
8
|
+
import iconv from "iconv-lite";
|
|
9
|
+
import { logDate } from "utility";
|
|
10
|
+
|
|
11
|
+
//#region src/utils.ts
|
|
12
|
+
const hostname = os.hostname();
|
|
13
|
+
const durationRegexp = /\b(\d+ms)\b/g;
|
|
14
|
+
const categoryRegexp = /(\[[\w\-_.:]+\])/g;
|
|
15
|
+
const httpMethodRegexp = /(GET|POST|PUT|PATCH|HEAD|DELETE) /g;
|
|
16
|
+
function normalizeLevel(level) {
|
|
17
|
+
if (typeof level === "number") return level;
|
|
18
|
+
if (typeof level === "string" && level) return levels[level.toUpperCase()];
|
|
19
|
+
}
|
|
20
|
+
function defaultContextPaddingMessage(ctx) {
|
|
21
|
+
const userId = ctx.userId || "-";
|
|
22
|
+
const traceId = ctx.tracer?.traceId || "-";
|
|
23
|
+
let use = 0;
|
|
24
|
+
if (ctx.performanceStarttime) use = Math.floor((performance.now() - ctx.performanceStarttime) * 1e3) / 1e3;
|
|
25
|
+
else if (ctx.starttime) use = Date.now() - ctx.starttime;
|
|
26
|
+
return "[" + userId + "/" + ctx.ip + "/" + traceId + "/" + use + "ms " + ctx.method + " " + ctx.url + "]";
|
|
27
|
+
}
|
|
28
|
+
function defaultFormatter(meta) {
|
|
29
|
+
let paddingMessage = " ";
|
|
30
|
+
if (meta.paddingMessage) paddingMessage = ` ${meta.paddingMessage} `;
|
|
31
|
+
else {
|
|
32
|
+
const ctx = meta.ctx;
|
|
33
|
+
if (ctx) paddingMessage = ` ${defaultContextPaddingMessage(ctx)} `;
|
|
34
|
+
}
|
|
35
|
+
return meta.date + " " + meta.level + " " + meta.pid + paddingMessage + meta.message;
|
|
36
|
+
}
|
|
37
|
+
function consoleFormatter(meta) {
|
|
38
|
+
let paddingMessage = " ";
|
|
39
|
+
if (meta.paddingMessage) paddingMessage = ` ${meta.paddingMessage} `;
|
|
40
|
+
let msg = meta.date + " " + meta.level + " " + meta.pid + paddingMessage + meta.message;
|
|
41
|
+
if (chalk.level === 0) return msg;
|
|
42
|
+
if (meta.level === "ERROR") return chalk.red(msg);
|
|
43
|
+
if (meta.level === "WARN") return chalk.yellow(msg);
|
|
44
|
+
msg = msg.replace(durationRegexp, chalk.green("$1"));
|
|
45
|
+
msg = msg.replace(categoryRegexp, chalk.blue("$1"));
|
|
46
|
+
msg = msg.replace(httpMethodRegexp, chalk.cyan("$1 "));
|
|
47
|
+
return msg;
|
|
48
|
+
}
|
|
49
|
+
function formatLog(level, args, meta, options) {
|
|
50
|
+
meta = meta ?? {};
|
|
51
|
+
let message;
|
|
52
|
+
let output;
|
|
53
|
+
let formatter = meta.formatter ?? options.formatter;
|
|
54
|
+
if (meta.ctx) {
|
|
55
|
+
if (options.contextFormatter) {
|
|
56
|
+
formatter = options.contextFormatter;
|
|
57
|
+
if (!meta.paddingMessage) meta.paddingMessage = options.paddingMessageFormatter ? options.paddingMessageFormatter(meta.ctx) : defaultContextPaddingMessage(meta.ctx);
|
|
58
|
+
} else if (options.paddingMessageFormatter && !meta.paddingMessage) meta.paddingMessage = options.paddingMessageFormatter(meta.ctx);
|
|
59
|
+
}
|
|
60
|
+
if (args[0] instanceof Error) message = formatError(args[0], options);
|
|
61
|
+
else message = util.format(...args);
|
|
62
|
+
if (meta.raw === true) output = message;
|
|
63
|
+
else if (options.json === true || formatter) {
|
|
64
|
+
meta.level = level;
|
|
65
|
+
meta.date = options.dateISOFormat ? (/* @__PURE__ */ new Date()).toISOString() : logDate(",");
|
|
66
|
+
meta.pid = process.pid;
|
|
67
|
+
meta.hostname = hostname;
|
|
68
|
+
meta.message = message;
|
|
69
|
+
if (options.json === true) {
|
|
70
|
+
const outputMeta = {
|
|
71
|
+
...meta,
|
|
72
|
+
ctx: void 0
|
|
73
|
+
};
|
|
74
|
+
output = JSON.stringify(outputMeta);
|
|
75
|
+
} else output = formatter(meta);
|
|
76
|
+
} else output = message;
|
|
77
|
+
if (!output) return Buffer.from("");
|
|
78
|
+
output += options.eol;
|
|
79
|
+
return options.encoding === "utf8" ? output : iconv.encode(output, options.encoding);
|
|
80
|
+
}
|
|
81
|
+
function assign(target, ...sources) {
|
|
82
|
+
const t = target;
|
|
83
|
+
for (const source of sources) {
|
|
84
|
+
if (source == null) continue;
|
|
85
|
+
const s = source;
|
|
86
|
+
for (const key of Object.keys(s)) {
|
|
87
|
+
const val = s[key];
|
|
88
|
+
if (val !== void 0) t[key] = val;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return target;
|
|
92
|
+
}
|
|
93
|
+
function formatError(err, options, causeLength) {
|
|
94
|
+
if (FrameworkBaseError.isFrameworkError(err)) return FrameworkErrorFormatter.format(err);
|
|
95
|
+
const msg = errorToString(err, options, causeLength);
|
|
96
|
+
return util.format("%s\npid: %s\nhostname: %s\n", msg, process.pid, hostname);
|
|
97
|
+
}
|
|
98
|
+
function errorToString(err, options, causeLength = 0) {
|
|
99
|
+
if (causeLength > (options?.maxCauseChainLength ?? 10)) return "too long cause chain";
|
|
100
|
+
const e = err;
|
|
101
|
+
let errName = e.name || "no_name";
|
|
102
|
+
if (e.name === "Error" && typeof e.code === "string") errName = e.code + errName;
|
|
103
|
+
let errMessage = e.message || "no_message";
|
|
104
|
+
if (e.host) errMessage += ` (${e.host})`;
|
|
105
|
+
const errStack = e.stack || "no_stack";
|
|
106
|
+
const errProperties = Object.keys(e).map((key) => inspectProp(key, e[key])).join("\n");
|
|
107
|
+
let errorString = util.format("nodejs.%s: %s\n%s\n%s", errName, errMessage, errStack.substring(errStack.indexOf("\n") + 1), errProperties);
|
|
108
|
+
if (e.name === "AggregateError" && e.errors) for (let i = 0; i < e.errors.length; i++) {
|
|
109
|
+
const subErrorMsg = errorToString(e.errors[i], options, causeLength + 1);
|
|
110
|
+
errorString = util.format("%s\n[error-%d]:\n\n%s", errorString, i, subErrorMsg);
|
|
111
|
+
}
|
|
112
|
+
if (e.cause) {
|
|
113
|
+
const causeMsg = errorToString(e.cause, options, causeLength + 1);
|
|
114
|
+
errorString = util.format("%s\ncause:\n\n%s", errorString, causeMsg);
|
|
115
|
+
}
|
|
116
|
+
return errorString;
|
|
117
|
+
}
|
|
118
|
+
function inspectProp(key, value) {
|
|
119
|
+
return `${key}: ${formatObject(value)}`;
|
|
120
|
+
}
|
|
121
|
+
function formatString(str) {
|
|
122
|
+
if (str.length > 1e4) return `${str.substring(0, 1e4)}...(${str.length})`;
|
|
123
|
+
return str;
|
|
124
|
+
}
|
|
125
|
+
function formatBuffer(buf) {
|
|
126
|
+
const tail = buf.data.length > 50 ? ` ...(${buf.data.length}) ` : "";
|
|
127
|
+
return `<Buffer ${buf.data.slice(0, 50).map((i) => {
|
|
128
|
+
const hex = i.toString(16);
|
|
129
|
+
return hex.length === 1 ? `0${hex}` : hex;
|
|
130
|
+
}).join(" ")}${tail}>`;
|
|
131
|
+
}
|
|
132
|
+
function formatObject(obj) {
|
|
133
|
+
try {
|
|
134
|
+
return circularJSON.stringify(obj, (_key, v) => {
|
|
135
|
+
if (typeof v === "string") return formatString(v);
|
|
136
|
+
if (v && v.type === "Buffer" && Array.isArray(v.data)) return formatBuffer(v);
|
|
137
|
+
if (v instanceof RegExp) return util.inspect(v);
|
|
138
|
+
return v;
|
|
139
|
+
});
|
|
140
|
+
} catch {
|
|
141
|
+
return String(obj);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
export { assign, consoleFormatter, defaultContextPaddingMessage, defaultFormatter, formatError, formatLog, normalizeLevel };
|
package/dist/vendor.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/vendor.d.ts
|
|
2
|
+
declare module 'circular-json-for-egg' {
|
|
3
|
+
const circularJSON: {
|
|
4
|
+
stringify(obj: unknown, replacer?: (key: string, value: unknown) => unknown, space?: string | number): string;
|
|
5
|
+
parse(text: string): unknown;
|
|
6
|
+
};
|
|
7
|
+
export default circularJSON;
|
|
8
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eggjs/logger",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1-beta.0",
|
|
4
4
|
"description": "egg logger",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"egg",
|
|
@@ -17,15 +17,59 @@
|
|
|
17
17
|
"url": "git+https://github.com/eggjs/egg.git",
|
|
18
18
|
"directory": "packages/logger"
|
|
19
19
|
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": "./dist/index.js",
|
|
29
|
+
"./egg/console_logger": "./dist/egg/console_logger.js",
|
|
30
|
+
"./egg/custom_logger": "./dist/egg/custom_logger.js",
|
|
31
|
+
"./egg/error_logger": "./dist/egg/error_logger.js",
|
|
32
|
+
"./egg/logger": "./dist/egg/logger.js",
|
|
33
|
+
"./egg/loggers": "./dist/egg/loggers.js",
|
|
34
|
+
"./level": "./dist/level.js",
|
|
35
|
+
"./logger": "./dist/logger.js",
|
|
36
|
+
"./transports/console": "./dist/transports/console.js",
|
|
37
|
+
"./transports/file": "./dist/transports/file.js",
|
|
38
|
+
"./transports/file_buffer": "./dist/transports/file_buffer.js",
|
|
39
|
+
"./transports/transport": "./dist/transports/transport.js",
|
|
40
|
+
"./utils": "./dist/utils.js",
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
20
43
|
"publishConfig": {
|
|
21
44
|
"access": "public"
|
|
22
45
|
},
|
|
23
46
|
"dependencies": {
|
|
47
|
+
"chalk": "^5.4.1",
|
|
48
|
+
"circular-json-for-egg": "^1.0.0",
|
|
49
|
+
"iconv-lite": "^0.6.3",
|
|
50
|
+
"utility": "^2.5.0",
|
|
51
|
+
"@eggjs/errors": "3.0.1-beta.0"
|
|
24
52
|
},
|
|
25
53
|
"devDependencies": {
|
|
54
|
+
"@types/node": "^24.10.2",
|
|
55
|
+
"coffee": "5",
|
|
56
|
+
"mm": "^4.0.2",
|
|
57
|
+
"oxlint": "^1.32.0",
|
|
58
|
+
"rimraf": "^6.1.2",
|
|
59
|
+
"typescript": "^5.9.3",
|
|
60
|
+
"vitest": "^4.0.15",
|
|
61
|
+
"@eggjs/supertest": "9.0.1-beta.0",
|
|
62
|
+
"@eggjs/koa": "3.1.1-beta.0",
|
|
63
|
+
"@eggjs/tsconfig": "3.1.1-beta.0"
|
|
26
64
|
},
|
|
27
65
|
"engines": {
|
|
28
66
|
"node": ">= 22.18.0"
|
|
67
|
+
},
|
|
68
|
+
"scripts": {
|
|
69
|
+
"build": "tsdown",
|
|
70
|
+
"clean": "rimraf dist",
|
|
71
|
+
"lint": "oxlint --type-aware",
|
|
72
|
+
"typecheck": "tsgo --noEmit",
|
|
73
|
+
"test": "vitest run"
|
|
29
74
|
}
|
|
30
|
-
}
|
|
31
|
-
|
|
75
|
+
}
|