mm_logger 0.0.0-stage → 1.0.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/.gitattributes +5 -0
- package/LICENSE +15 -0
- package/README.md +325 -2
- package/eslint.config.js +68 -0
- package/examples/basic.js +70 -0
- package/examples/http.js +71 -0
- package/examples/query.js +84 -0
- package/index.js +27 -0
- package/jest.config.js +18 -0
- package/lib/colors.js +200 -0
- package/lib/console_logger.js +71 -0
- package/lib/level.js +15 -0
- package/lib/logger.js +1098 -0
- package/package.json +55 -4
- package/test/colors.test.js +265 -0
- package/test/console_logger.test.js +92 -0
- package/test.js +57 -0
package/package.json
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_logger",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "高性能 Node.js 日志模块,支持多级别日志、文件轮转、事件钩子和灵活配置。",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node test.js",
|
|
8
|
+
"test:unit": "jest --coverage"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"mm_mod",
|
|
12
|
+
"mm_infra",
|
|
13
|
+
"mm_observability",
|
|
14
|
+
"log",
|
|
15
|
+
"logger",
|
|
16
|
+
"logging",
|
|
17
|
+
"file",
|
|
18
|
+
"rotation",
|
|
19
|
+
"nodejs",
|
|
20
|
+
"javascript",
|
|
21
|
+
"module",
|
|
22
|
+
"enterprise",
|
|
23
|
+
"tracing",
|
|
24
|
+
"masking",
|
|
25
|
+
"security",
|
|
26
|
+
"performance"
|
|
27
|
+
],
|
|
28
|
+
"layer": "infra",
|
|
29
|
+
"group": "observability",
|
|
30
|
+
"author": {
|
|
31
|
+
"name": "qww",
|
|
32
|
+
"email": "qiwenwu@elins.cn",
|
|
33
|
+
"url": "http://qww.elins.cn"
|
|
34
|
+
},
|
|
35
|
+
"license": "ISC",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/qiwenwu/mm_logger.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/qiwenwu/mm_logger/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/qiwenwu/mm_logger#readme",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"log4js": "^6.9.1",
|
|
46
|
+
"mm_helper": "^1.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"jest": "^30.5.2"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=12.0.0"
|
|
53
|
+
},
|
|
54
|
+
"directories": {
|
|
55
|
+
"lib": "."
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
const ENV_KEYS = [
|
|
6
|
+
'NO_COLOR',
|
|
7
|
+
'FORCE_COLOR',
|
|
8
|
+
'CI',
|
|
9
|
+
'TERM',
|
|
10
|
+
'WT_SESSION',
|
|
11
|
+
'ConEmuANSI',
|
|
12
|
+
'ANSICON',
|
|
13
|
+
'TERM_PROGRAM',
|
|
14
|
+
'GITHUB_ACTIONS',
|
|
15
|
+
'GITLAB_CI',
|
|
16
|
+
'CIRCLECI',
|
|
17
|
+
'TRAVIS',
|
|
18
|
+
'BUILDKITE'
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
let saved_platform;
|
|
22
|
+
let saved_tty;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 清理与颜色相关的环境变量
|
|
26
|
+
*/
|
|
27
|
+
function clearEnv() {
|
|
28
|
+
ENV_KEYS.forEach((key) => {
|
|
29
|
+
delete process.env[key];
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 重载 colors 模块以重置内部缓存
|
|
35
|
+
* @returns {Object} colors 模块对象
|
|
36
|
+
*/
|
|
37
|
+
function loadColors() {
|
|
38
|
+
jest.resetModules();
|
|
39
|
+
return require('../lib/colors');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 创建输出流桩
|
|
44
|
+
* @param {boolean} is_tty 是否为 TTY
|
|
45
|
+
* @returns {Object} 流桩对象
|
|
46
|
+
*/
|
|
47
|
+
function createStream(is_tty) {
|
|
48
|
+
return { isTTY: is_tty };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 设置 process.platform
|
|
53
|
+
* @param {string} platform 平台名称
|
|
54
|
+
*/
|
|
55
|
+
function setPlatform(platform) {
|
|
56
|
+
Object.defineProperty(process, 'platform', { value: platform, configurable: true });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 设置 process.stdout.isTTY,避免模块加载时触发平台探测
|
|
61
|
+
* @param {boolean} is_tty 是否为 TTY
|
|
62
|
+
*/
|
|
63
|
+
function setStreamTty(is_tty) {
|
|
64
|
+
Object.defineProperty(process.stdout, 'isTTY', { value: is_tty, configurable: true });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
saved_platform = process.platform;
|
|
69
|
+
saved_tty = process.stdout.isTTY;
|
|
70
|
+
clearEnv();
|
|
71
|
+
setStreamTty(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
afterEach(() => {
|
|
75
|
+
clearEnv();
|
|
76
|
+
setPlatform(saved_platform);
|
|
77
|
+
setStreamTty(saved_tty);
|
|
78
|
+
jest.restoreAllMocks();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('supportsColor', () => {
|
|
82
|
+
it('未传流时默认使用 process.stdout', () => {
|
|
83
|
+
const { supportsColor } = loadColors();
|
|
84
|
+
expect(typeof supportsColor()).toBe('boolean');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('设置 NO_COLOR 时禁用颜色', () => {
|
|
88
|
+
process.env.NO_COLOR = '1';
|
|
89
|
+
const { supportsColor } = loadColors();
|
|
90
|
+
expect(supportsColor(createStream(true))).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('NO_COLOR 为空字符串时也禁用颜色(回归)', () => {
|
|
94
|
+
process.env.NO_COLOR = '';
|
|
95
|
+
const { supportsColor } = loadColors();
|
|
96
|
+
expect(supportsColor(createStream(true))).toBe(false);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('FORCE_COLOR 为真值时启用颜色', () => {
|
|
100
|
+
process.env.FORCE_COLOR = '1';
|
|
101
|
+
const { supportsColor } = loadColors();
|
|
102
|
+
expect(supportsColor(createStream(false))).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('FORCE_COLOR=0 时禁用颜色', () => {
|
|
106
|
+
process.env.FORCE_COLOR = '0';
|
|
107
|
+
const { supportsColor } = loadColors();
|
|
108
|
+
expect(supportsColor(createStream(true))).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('FORCE_COLOR=false 时禁用颜色', () => {
|
|
112
|
+
process.env.FORCE_COLOR = 'false';
|
|
113
|
+
const { supportsColor } = loadColors();
|
|
114
|
+
expect(supportsColor(createStream(true))).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('FORCE_COLOR 为空字符串时继续检测', () => {
|
|
118
|
+
process.env.FORCE_COLOR = '';
|
|
119
|
+
const { supportsColor } = loadColors();
|
|
120
|
+
expect(supportsColor(createStream(false))).toBe(false);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('非 TTY 流禁用颜色', () => {
|
|
124
|
+
const { supportsColor } = loadColors();
|
|
125
|
+
expect(supportsColor(createStream(false))).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('TERM=dumb 时禁用颜色', () => {
|
|
129
|
+
process.env.TERM = 'dumb';
|
|
130
|
+
const { supportsColor } = loadColors();
|
|
131
|
+
expect(supportsColor(createStream(true))).toBe(false);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('CI 环境无已知 CI 标识时禁用颜色', () => {
|
|
135
|
+
process.env.CI = '1';
|
|
136
|
+
const { supportsColor } = loadColors();
|
|
137
|
+
expect(supportsColor(createStream(true))).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('CI 环境且有 GITHUB_ACTIONS 时启用颜色', () => {
|
|
141
|
+
process.env.CI = '1';
|
|
142
|
+
process.env.GITHUB_ACTIONS = '1';
|
|
143
|
+
const { supportsColor } = loadColors();
|
|
144
|
+
expect(supportsColor(createStream(true))).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('Windows 平台下按终端能力判断', () => {
|
|
148
|
+
setPlatform('win32');
|
|
149
|
+
jest.spyOn(os, 'release').mockReturnValue('10.0.19045');
|
|
150
|
+
const { supportsColor } = loadColors();
|
|
151
|
+
expect(supportsColor(createStream(true))).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('非 Windows 平台 TTY 即启用颜色', () => {
|
|
155
|
+
setPlatform('linux');
|
|
156
|
+
const { supportsColor } = loadColors();
|
|
157
|
+
expect(supportsColor(createStream(true))).toBe(true);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe('windowsSupportsVT', () => {
|
|
162
|
+
it('WT_SESSION 存在时支持 VT', () => {
|
|
163
|
+
process.env.WT_SESSION = '1';
|
|
164
|
+
const { windowsSupportsVT } = loadColors();
|
|
165
|
+
expect(windowsSupportsVT()).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('ConEmuANSI=ON 时支持 VT', () => {
|
|
169
|
+
process.env.ConEmuANSI = 'ON';
|
|
170
|
+
const { windowsSupportsVT } = loadColors();
|
|
171
|
+
expect(windowsSupportsVT()).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('ANSICON 存在时支持 VT', () => {
|
|
175
|
+
process.env.ANSICON = '1';
|
|
176
|
+
const { windowsSupportsVT } = loadColors();
|
|
177
|
+
expect(windowsSupportsVT()).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('TERM_PROGRAM=vscode 时支持 VT', () => {
|
|
181
|
+
process.env.TERM_PROGRAM = 'vscode';
|
|
182
|
+
const { windowsSupportsVT } = loadColors();
|
|
183
|
+
expect(windowsSupportsVT()).toBe(true);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('系统版本足够新时支持 VT', () => {
|
|
187
|
+
jest.spyOn(os, 'release').mockReturnValue('10.0.19045');
|
|
188
|
+
const { windowsSupportsVT } = loadColors();
|
|
189
|
+
expect(windowsSupportsVT()).toBe(true);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('主版本过低时不支持 VT', () => {
|
|
193
|
+
jest.spyOn(os, 'release').mockReturnValue('6.1.7601');
|
|
194
|
+
const { windowsSupportsVT } = loadColors();
|
|
195
|
+
expect(windowsSupportsVT()).toBe(false);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('构建号过低时不支持 VT', () => {
|
|
199
|
+
jest.spyOn(os, 'release').mockReturnValue('10.0.10000');
|
|
200
|
+
const { windowsSupportsVT } = loadColors();
|
|
201
|
+
expect(windowsSupportsVT()).toBe(false);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('版本号解析不出数字时不支持 VT', () => {
|
|
205
|
+
jest.spyOn(os, 'release').mockReturnValue('');
|
|
206
|
+
const { windowsSupportsVT } = loadColors();
|
|
207
|
+
expect(windowsSupportsVT()).toBe(false);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('release 抛错时不支持 VT', () => {
|
|
211
|
+
jest.spyOn(os, 'release').mockImplementation(() => {
|
|
212
|
+
throw new Error('boom');
|
|
213
|
+
});
|
|
214
|
+
const { windowsSupportsVT } = loadColors();
|
|
215
|
+
expect(windowsSupportsVT()).toBe(false);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('结果会被缓存', () => {
|
|
219
|
+
process.env.WT_SESSION = '1';
|
|
220
|
+
const { windowsSupportsVT } = loadColors();
|
|
221
|
+
expect(windowsSupportsVT()).toBe(true);
|
|
222
|
+
expect(windowsSupportsVT()).toBe(true);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
describe('createColors', () => {
|
|
227
|
+
it('启用颜色时各着色器输出 ANSI 序列', () => {
|
|
228
|
+
const { createColors } = loadColors();
|
|
229
|
+
const c = createColors(true);
|
|
230
|
+
|
|
231
|
+
expect(c.enabled).toBe(true);
|
|
232
|
+
expect(c.blue('x')).toBe('\u001b[34mx\u001b[39m');
|
|
233
|
+
expect(c.ansi256(200)('x')).toBe('\u001b[38;5;200mx\u001b[39m');
|
|
234
|
+
expect(c.rgb(1, 2, 3)('x')).toBe('\u001b[38;2;1;2;3mx\u001b[39m');
|
|
235
|
+
expect(c.bgRgb(1, 2, 3)('x')).toBe('\u001b[48;2;1;2;3mx\u001b[49m');
|
|
236
|
+
expect(c.style('bold red')('x')).toBe('\u001b[1;31mx\u001b[39;22m');
|
|
237
|
+
expect(c.style(['bold', 'red'])('x')).toBe('\u001b[1;31mx\u001b[39;22m');
|
|
238
|
+
expect(c.style('bold nope')('x')).toBe('\u001b[1mx\u001b[22m');
|
|
239
|
+
expect(c.style('nope')('x')).toBe('x');
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('禁用颜色时各着色器原样返回', () => {
|
|
243
|
+
const { createColors } = loadColors();
|
|
244
|
+
const c = createColors(false);
|
|
245
|
+
|
|
246
|
+
expect(c.enabled).toBe(false);
|
|
247
|
+
expect(c.blue('x')).toBe('x');
|
|
248
|
+
expect(c.blue(123)).toBe('123');
|
|
249
|
+
expect(c.ansi256(200)('x')).toBe('x');
|
|
250
|
+
expect(c.rgb(1, 2, 3)('x')).toBe('x');
|
|
251
|
+
expect(c.bgRgb(1, 2, 3)('x')).toBe('x');
|
|
252
|
+
expect(c.style('bold red')('x')).toBe('x');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('默认导出与 forStream 返回可用着色器', () => {
|
|
256
|
+
const colorsModule = loadColors();
|
|
257
|
+
|
|
258
|
+
expect(colorsModule.STYLES.reset).toEqual([0, 0]);
|
|
259
|
+
expect(colorsModule.colors.enabled).toBe(false);
|
|
260
|
+
|
|
261
|
+
const streamed = colorsModule.forStream(createStream(true));
|
|
262
|
+
expect(typeof streamed.red).toBe('function');
|
|
263
|
+
expect(streamed.red('x')).toContain('x');
|
|
264
|
+
});
|
|
265
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ConsoleLogger = require('../lib/console_logger');
|
|
4
|
+
|
|
5
|
+
describe('ConsoleLogger', () => {
|
|
6
|
+
let spies;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
spies = {
|
|
10
|
+
info: jest.spyOn(console, 'info').mockImplementation(() => {}),
|
|
11
|
+
debug: jest.spyOn(console, 'debug').mockImplementation(() => {}),
|
|
12
|
+
error: jest.spyOn(console, 'error').mockImplementation(() => {}),
|
|
13
|
+
log: jest.spyOn(console, 'log').mockImplementation(() => {}),
|
|
14
|
+
warn: jest.spyOn(console, 'warn').mockImplementation(() => {})
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
Object.values(spies).forEach((spy) => spy.mockRestore());
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('info 输出到 console.info', () => {
|
|
23
|
+
const logger = new ConsoleLogger();
|
|
24
|
+
logger.info('hello', 1);
|
|
25
|
+
expect(spies.info).toHaveBeenCalledTimes(1);
|
|
26
|
+
expect(spies.info.mock.calls[0][0]).toContain('hello');
|
|
27
|
+
expect(spies.info.mock.calls[0][1]).toBe(1);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('debug 输出到 console.debug', () => {
|
|
31
|
+
const logger = new ConsoleLogger();
|
|
32
|
+
logger.debug('hello');
|
|
33
|
+
expect(spies.debug).toHaveBeenCalledTimes(1);
|
|
34
|
+
expect(spies.debug.mock.calls[0][0]).toContain('hello');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('error 输出到 console.error', () => {
|
|
38
|
+
const logger = new ConsoleLogger();
|
|
39
|
+
logger.error('hello');
|
|
40
|
+
expect(spies.error).toHaveBeenCalledTimes(1);
|
|
41
|
+
expect(spies.error.mock.calls[0][0]).toContain('hello');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('success 输出到 console.log', () => {
|
|
45
|
+
const logger = new ConsoleLogger();
|
|
46
|
+
logger.success('hello');
|
|
47
|
+
expect(spies.log).toHaveBeenCalledTimes(1);
|
|
48
|
+
expect(spies.log.mock.calls[0][0]).toContain('hello');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('warn 输出到 console.warn', () => {
|
|
52
|
+
const logger = new ConsoleLogger();
|
|
53
|
+
logger.warn('hello');
|
|
54
|
+
expect(spies.warn).toHaveBeenCalledTimes(1);
|
|
55
|
+
expect(spies.warn.mock.calls[0][0]).toContain('hello');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('着色器分流', () => {
|
|
59
|
+
it('error 与 warn 使用基于 stderr 的着色器,其余使用 stdout', () => {
|
|
60
|
+
jest.resetModules();
|
|
61
|
+
jest.doMock('../lib/colors', () => ({
|
|
62
|
+
colors: {
|
|
63
|
+
blue: (s) => `OUT:${s}`,
|
|
64
|
+
white: (s) => `OUT:${s}`,
|
|
65
|
+
green: (s) => `OUT:${s}`
|
|
66
|
+
},
|
|
67
|
+
forStream: jest.fn(() => ({
|
|
68
|
+
red: (s) => `ERR:${s}`,
|
|
69
|
+
yellow: (s) => `ERR:${s}`
|
|
70
|
+
}))
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
const IsolatedLogger = require('../lib/console_logger');
|
|
74
|
+
const logger = new IsolatedLogger();
|
|
75
|
+
|
|
76
|
+
logger.info('a');
|
|
77
|
+
logger.debug('b');
|
|
78
|
+
logger.success('c');
|
|
79
|
+
logger.error('d');
|
|
80
|
+
logger.warn('e');
|
|
81
|
+
|
|
82
|
+
expect(spies.info.mock.calls[0][0]).toBe('OUT:a');
|
|
83
|
+
expect(spies.debug.mock.calls[0][0]).toBe('OUT:b');
|
|
84
|
+
expect(spies.log.mock.calls[0][0]).toBe('OUT:c');
|
|
85
|
+
expect(spies.error.mock.calls[0][0]).toBe('ERR:d');
|
|
86
|
+
expect(spies.warn.mock.calls[0][0]).toBe('ERR:e');
|
|
87
|
+
|
|
88
|
+
jest.dontMock('../lib/colors');
|
|
89
|
+
jest.resetModules();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
});
|
package/test.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description 日志模块测试文件
|
|
3
|
+
*/
|
|
4
|
+
const { getLogger } = require('./index.js');
|
|
5
|
+
|
|
6
|
+
// 创建日志实例
|
|
7
|
+
const log = getLogger({
|
|
8
|
+
level: 'debug',
|
|
9
|
+
console: true,
|
|
10
|
+
file: true,
|
|
11
|
+
dir: './test_logs',
|
|
12
|
+
json: false
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
console.log('=== 开始测试日志模块 ===');
|
|
16
|
+
|
|
17
|
+
// 测试基本日志功能
|
|
18
|
+
log.debug('这是一条debug级别日志');
|
|
19
|
+
log.info('这是一条info级别日志');
|
|
20
|
+
log.success('这是一条success级别日志');
|
|
21
|
+
log.warn('这是一条warn级别日志');
|
|
22
|
+
log.error('这是一条error级别日志');
|
|
23
|
+
log.fatal('这是一条fatal级别日志');
|
|
24
|
+
|
|
25
|
+
// 测试HTTP日志
|
|
26
|
+
log.http('info', 'HTTP GET /api/users 200 OK');
|
|
27
|
+
log.http('warn', 'HTTP POST /api/users 400 Bad Request', { error: 'Invalid input' });
|
|
28
|
+
log.http('error', 'HTTP POST /api/users 500 Internal Server Error', { error: 'Server error' });
|
|
29
|
+
|
|
30
|
+
// 测试带额外参数
|
|
31
|
+
log.info('带对象参数', { user_id: 1 }, { name: 'test', value: 123 });
|
|
32
|
+
log.debug('带多个参数', '参数1', '参数2');
|
|
33
|
+
|
|
34
|
+
console.log('=== 日志记录测试完成 ===');
|
|
35
|
+
console.log('请检查控制台输出和日志文件');
|
|
36
|
+
|
|
37
|
+
// 测试日志查询功能(可选)
|
|
38
|
+
setTimeout(async () => {
|
|
39
|
+
try {
|
|
40
|
+
console.log('\n=== 测试日志查询 ===');
|
|
41
|
+
const today = new Date().toISOString().split('T')[0];
|
|
42
|
+
const result = await log.find({
|
|
43
|
+
date: today,
|
|
44
|
+
keyword: 'HTTP',
|
|
45
|
+
level: 'info',
|
|
46
|
+
page_now: 1,
|
|
47
|
+
page_size: 10
|
|
48
|
+
});
|
|
49
|
+
console.log(result);
|
|
50
|
+
console.log(`找到 ${result.count} 条日志`);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.log('查询日志时发生错误:', e.message);
|
|
53
|
+
}
|
|
54
|
+
}, 1000);
|
|
55
|
+
|
|
56
|
+
console.log('=== 测试日志查询 ===');
|
|
57
|
+
console.log('read', log.read());
|