跳转到内容

结构化日志

createLogger 提供了结构化的 JSON 日志,支持日志级别控制、上下文传递和多目标输出。

import { createLogger } from "@ventostack/observability";
const logger = createLogger({
level: "info", // 最低日志级别
service: "my-app", // 服务名称(出现在每条日志中)
});
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..." });

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

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

每条日志输出为 JSON(生产环境)或格式化文本(开发环境):

{
"level": "info",
"timestamp": "2024-01-01T10:00:00.000Z",
"service": "my-app",
"message": "用户登录",
"userId": "123",
"ip": "1.2.3.4",
"requestId": "abc-123"
}

@ventostack/core 已内置开箱即用的 requestLogger,默认输出结构化 JSON 日志,也支持传入 @ventostack/observability 的 Logger:

import { requestLogger, errorHandler } from "@ventostack/core";
import { createLogger } from "@ventostack/observability";
const logger = createLogger({ level: "info" });
const app = createApp({ port: 3000 });
app.use(errorHandler({ logger }));
app.use(requestLogger({ logger }));

requestLogger 会自动记录方法、路径、状态码和耗时。无需手写中间件。

const logger = createLogger({ level: "info", service: "api" });
// 创建携带请求上下文的子 logger
const requestLogger = logger.child({ requestId: "abc-123", userId: "user_1" });
// 子 logger 的每条日志都会包含 requestId 和 userId
requestLogger.info("处理订单");
// { requestId: "abc-123", userId: "user_1", message: "处理订单", ... }
const logger = createLogger({ level: "info" });
// 临时开启 debug 模式(生产环境排查问题)
router.post("/admin/log-level", adminOnly, async (ctx) => {
const { level } = await ctx.request.json() as { level: string };
logger.setLevel(level);
return ctx.json({ level });
});
interface Logger {
debug(message: string, context?: Record<string, unknown>): void;
info(message: string, context?: Record<string, unknown>): void;
warn(message: string, context?: Record<string, unknown>): void;
error(message: string, context?: Record<string, unknown>): void;
child(context: Record<string, unknown>): Logger;
setLevel(level: string): void;
}