1
0

feat: 运行时日志系统,Pino + pino-pretty + pino-roll,console/file 双输出,敏感信息 redaction

This commit is contained in:
2026-05-21 12:21:59 +08:00
parent 0d709c7681
commit 007d74934d
26 changed files with 1713 additions and 114 deletions

View File

@@ -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",
);
});
});
});