跳转到内容

结构化日志

createLogger 提供了结构化的 JSON 日志,支持日志级别控制、上下文传递、自动脱敏与完全禁用(no-op)。

import { createLogger } from "@ventostack/observability";
const logger = createLogger({
level: "info", // 最低日志级别
});
logger.debug("调试信息", { userId: "123" });
logger.info("用户登录", { userId: "123", ip: "1.2.3.4" });
logger.warn("请求缓慢", { path: "/api/users", latency: 2500 });
logger.error("数据库查询失败", { error: err.message, query: "SELECT..." });
logger.fatal("系统崩溃", { reason: "out of memory" });

从低到高:debug < info < warn < error < fatal

设置 level: "warn" 时,只有 warnerrorfatal 级别的日志会输出。

每条日志输出为 JSON(通过自定义 output 函数可改为其他格式):

{
"level": "info",
"timestamp": "2024-01-01T10:00:00.000Z",
"message": "用户登录",
"userId": "123",
"ip": "1.2.3.4"
}
const logger = createLogger({ enabled: false });
// 所有方法均为 no-op,不产生任何副作用
logger.info("这条日志不会输出");
const logger = createLogger({ level: "info" });
// 创建携带请求上下文的子 logger
const requestLogger = logger.child({ requestId: "abc-123", userId: "user_1" });
// 子 logger 的每条日志都会包含 requestId 和 userId
requestLogger.info("处理订单");
// { requestId: "abc-123", userId: "user_1", message: "处理订单", ... }

框架默认自动脱敏以下字段(不区分大小写,替换为 ***):

  • 基础安全字段:password、token、secret、key、cookie、authorization
  • 个人信息字段:phone、email、idcard、creditcard、ssn
  • 认证相关:apikey、access_token、refresh_token、mfa_secret
  • 会话相关:sessionid、session_id
  • 重置相关:resettoken、reset_token、temptoken、temp_token
  • MFA 相关:mfarecovery、mfa_recovery
  • 基础设施:private_key、connection_string、database_url、refresh_token_jti

审计日志的 metadata 字段在写入时会自动执行脱敏(调用 sanitize() 函数),无需调用方手动处理。

可自定义脱敏字段列表:

const logger = createLogger({
sensitiveFields: ["password", "ssn", "creditCard"],
});
logger.info("用户数据", { password: "123456", name: "Alice" });
// 输出中 password 字段会被替换为 "***"
const logger = createLogger({
output: (entry) => {
// 自定义输出目标,如文件、远程日志服务等
process.stderr.write(JSON.stringify(entry) + "\n");
},
});
interface Logger {
debug(message: string, meta?: Record<string, unknown>): void;
info(message: string, meta?: Record<string, unknown>): void;
warn(message: string, meta?: Record<string, unknown>): void;
error(message: string, meta?: Record<string, unknown>): void;
fatal(message: string, meta?: Record<string, unknown>): void;
child(defaultMeta: Record<string, unknown>): Logger;
}
interface LoggerOptions {
level?: LogLevel; // "debug" | "info" | "warn" | "error" | "fatal"
enabled?: boolean; // false 时返回 no-op 记录器
output?: (entry: LogEntry) => void;
sensitiveFields?: string[]; // 自定义脱敏字段
}
  • 当前 createLogger 不支持动态修改日志级别(setLevel 不存在)
  • 生产环境如需文件日志,可结合 createFileLogger 使用
  • 如需接入远程日志系统,可使用 createLogHook