feat: 运行时日志系统,Pino + pino-pretty + pino-roll,console/file 双输出,敏感信息 redaction
This commit is contained in:
@@ -2086,4 +2086,259 @@ targets:
|
||||
"expect.status 是未知字段",
|
||||
);
|
||||
});
|
||||
|
||||
describe("logging 配置", () => {
|
||||
test("logging 全部缺省时使用默认值", async () => {
|
||||
const configPath = join(tempDir, "logging-default.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
);
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.logging.consoleLevel).toBe("info");
|
||||
expect(config.logging.fileLevel).toBe("info");
|
||||
expect(config.logging.filePath).toBe(join(config.dataDir, "logs/dial.log"));
|
||||
expect(config.logging.rotationFrequency).toBe("daily");
|
||||
expect(config.logging.rotationMaxFiles).toBe(14);
|
||||
expect(config.logging.rotationSizeRaw).toBe("50MB");
|
||||
expect(config.logging.rotationSizeBytes).toBe(52428800);
|
||||
});
|
||||
|
||||
test("logging.level 设置全局等级继承到 console 和 file", async () => {
|
||||
const configPath = join(tempDir, "logging-global-level.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`logging:
|
||||
level: "debug"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
);
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.logging.consoleLevel).toBe("debug");
|
||||
expect(config.logging.fileLevel).toBe("debug");
|
||||
});
|
||||
|
||||
test("logging.console.level 覆盖全局等级", async () => {
|
||||
const configPath = join(tempDir, "logging-console-level.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`logging:
|
||||
level: "warn"
|
||||
console:
|
||||
level: "trace"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
);
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.logging.consoleLevel).toBe("trace");
|
||||
expect(config.logging.fileLevel).toBe("warn");
|
||||
});
|
||||
|
||||
test("logging.file.level 独立覆盖", async () => {
|
||||
const configPath = join(tempDir, "logging-file-level.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`logging:
|
||||
level: "info"
|
||||
file:
|
||||
level: "error"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
);
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.logging.consoleLevel).toBe("info");
|
||||
expect(config.logging.fileLevel).toBe("error");
|
||||
});
|
||||
|
||||
test("logging.file.path 绝对路径保持不变", async () => {
|
||||
const configPath = join(tempDir, "logging-abs-path.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`logging:
|
||||
file:
|
||||
path: "/var/log/dial/app.log"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
);
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.logging.filePath).toBe("/var/log/dial/app.log");
|
||||
});
|
||||
|
||||
test("logging.file.path 相对路径基于配置文件目录解析", async () => {
|
||||
const configPath = join(tempDir, "logging-rel-path.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`logging:
|
||||
file:
|
||||
path: "custom-logs/app.log"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
);
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.logging.filePath).toBe(join(tempDir, "custom-logs/app.log"));
|
||||
});
|
||||
|
||||
test("logging.file.rotation 自定义参数", async () => {
|
||||
const configPath = join(tempDir, "logging-rotation.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`logging:
|
||||
file:
|
||||
rotation:
|
||||
size: "100MB"
|
||||
frequency: "hourly"
|
||||
maxFiles: 30
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
);
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.logging.rotationSizeRaw).toBe("100MB");
|
||||
expect(config.logging.rotationSizeBytes).toBe(104857600);
|
||||
expect(config.logging.rotationFrequency).toBe("hourly");
|
||||
expect(config.logging.rotationMaxFiles).toBe(30);
|
||||
});
|
||||
|
||||
test("logging.level 非法等级抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"logging-bad-level.yaml",
|
||||
`logging:
|
||||
level: "verbose"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
"logging.level",
|
||||
);
|
||||
});
|
||||
|
||||
test("logging.console.level 非法等级抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"logging-bad-console-level.yaml",
|
||||
`logging:
|
||||
console:
|
||||
level: "nope"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
"logging.console.level",
|
||||
);
|
||||
});
|
||||
|
||||
test("logging.file.level 非法等级抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"logging-bad-file-level.yaml",
|
||||
`logging:
|
||||
file:
|
||||
level: 123
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
"logging.file.level",
|
||||
);
|
||||
});
|
||||
|
||||
test("logging.file.rotation.size 非法格式抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"logging-bad-rotation-size.yaml",
|
||||
`logging:
|
||||
file:
|
||||
rotation:
|
||||
size: "100TB"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
"无效的 size 格式",
|
||||
);
|
||||
});
|
||||
|
||||
test("logging.file.rotation.frequency 非法值抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"logging-bad-frequency.yaml",
|
||||
`logging:
|
||||
file:
|
||||
rotation:
|
||||
frequency: "monthly"
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
"logging.file.rotation.frequency",
|
||||
);
|
||||
});
|
||||
|
||||
test("logging.file.rotation.maxFiles 非整数抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"logging-bad-maxfiles.yaml",
|
||||
`logging:
|
||||
file:
|
||||
rotation:
|
||||
maxFiles: 3.5
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
"logging.file.rotation.maxFiles",
|
||||
);
|
||||
});
|
||||
|
||||
test("logging.file.path 空字符串抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"logging-empty-path.yaml",
|
||||
`logging:
|
||||
file:
|
||||
path: ""
|
||||
targets:
|
||||
- id: "t"
|
||||
type: http
|
||||
http:
|
||||
url: "http://example.com"
|
||||
`,
|
||||
"logging.file.path",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user