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

@@ -1,12 +1,15 @@
import { join } from "node:path";
import type { RuntimeMode } from "../shared/api";
import type { ResolvedLoggingConfig } from "./checker/types";
import type { Logger } from "./logger";
import type { StartServerOptions } from "./server";
import type { StaticAssets } from "./static";
import { loadConfig, type ResolvedConfig } from "./checker/config-loader";
import { ProbeEngine } from "./checker/engine";
import { ProbeStore } from "./checker/store";
import { createRuntimeLogger } from "./logger";
import { startServer } from "./server";
export interface BootstrapDependencies {
@@ -15,7 +18,9 @@ export interface BootstrapDependencies {
targets: ResolvedConfig["targets"],
maxConcurrentChecks: number,
retentionMs: number,
logger: Logger,
) => BootstrapEngine;
createLogger?: (config: ResolvedLoggingConfig, mode: string, version: string) => Promise<Logger>;
createStore?: (dbPath: string) => ProbeStore;
exit?: (code: number) => never;
loadConfig?: (configPath: string) => Promise<ResolvedConfig>;
@@ -39,8 +44,14 @@ export async function bootstrap(options: BootstrapOptions, dependencies: Bootstr
const createStore = dependencies.createStore ?? ((dbPath: string) => new ProbeStore(dbPath));
const createEngine =
dependencies.createEngine ??
((store: ProbeStore, targets: ResolvedConfig["targets"], maxConcurrentChecks: number, retentionMs: number) =>
new ProbeEngine(store, targets, maxConcurrentChecks, retentionMs));
((
store: ProbeStore,
targets: ResolvedConfig["targets"],
maxConcurrentChecks: number,
retentionMs: number,
logger: Logger,
) => new ProbeEngine(store, targets, maxConcurrentChecks, retentionMs, logger));
const buildLogger = dependencies.createLogger ?? createRuntimeLogger;
const serve = dependencies.startServer ?? startServer;
const onSignal =
dependencies.onSignal ??
@@ -52,18 +63,42 @@ export async function bootstrap(options: BootstrapOptions, dependencies: Bootstr
let store: ProbeStore | undefined;
let engine: BootstrapEngine | undefined;
let logger: Logger | undefined;
try {
const config = await load(options.configPath);
try {
logger = await buildLogger(config.logging, options.mode, options.version);
} catch (logInitError) {
logError("日志初始化失败:", logInitError instanceof Error ? logInitError.message : logInitError);
exit(1);
}
logger!.info({ configPath: options.configPath, mode: options.mode, version: options.version }, "配置加载成功");
store = createStore(join(config.dataDir, "probe.db"));
store.syncTargets(config.targets);
logger!.info({ dataDir: config.dataDir }, "数据库初始化成功");
engine = createEngine(store, config.targets, config.maxConcurrentChecks, config.retentionMs);
engine = createEngine(
store,
config.targets,
config.maxConcurrentChecks,
config.retentionMs,
logger!.child({ component: "engine" }),
);
engine.start();
logger!.info(
{ maxConcurrentChecks: config.maxConcurrentChecks, targetCount: config.targets.length },
"调度引擎启动",
);
const shutdown = () => {
logger?.info("收到退出信号,开始优雅关机");
engine?.stop();
store?.close();
logger?.flush();
exit(0);
};
onSignal("SIGINT", shutdown);
@@ -71,6 +106,7 @@ export async function bootstrap(options: BootstrapOptions, dependencies: Bootstr
serve({
config: { host: config.host, port: config.port },
logger: logger!.child({ component: "server" }),
mode: options.mode,
staticAssets: options.staticAssets,
store,
@@ -79,7 +115,12 @@ export async function bootstrap(options: BootstrapOptions, dependencies: Bootstr
} catch (error) {
engine?.stop();
store?.close();
logError("启动失败:", error instanceof Error ? error.message : error);
if (logger) {
logger.fatal({ error: error instanceof Error ? error.message : String(error) }, "启动失败");
logger.flush();
} else {
logError("启动失败:", error instanceof Error ? error.message : error);
}
exit(1);
}
}