Logs 日志工具
使用 @mono/logs 进行统一日志记录、模块化打标和错误追踪
Logs 日志工具
@mono/logs 是项目内统一的日志工具包,基于 consola 封装,提供:
- 环境感知的日志配置
- 模块级 logger
- 开发环境彩色输出
- 生产环境紧凑格式和时间戳
- 简单一致的 API
安装方式
在 monorepo 中直接通过 workspace 依赖使用:
{
"dependencies": {
"@mono/logs": "workspace:*"
}
}快速开始
使用默认 logger
import { logger } from "@mono/logs";
logger.info("应用启动成功");
logger.warn("配置项缺失,将使用默认值");
logger.error("数据库连接失败");创建模块级 logger
import { createModuleLogger } from "@mono/logs";
const authLogger = createModuleLogger("auth");
const paymentLogger = createModuleLogger("payment");
authLogger.info("用户登录成功");
paymentLogger.warn("支付回调签名校验失败");提示: 推荐每个领域模块创建自己的 logger,而不是手动在消息里拼接前缀。
日志级别
当前包使用的默认策略:
development:显示debug及以上级别日志production:显示info及以上级别日志
常用级别:
logger.trace("最细粒度调试信息");
logger.debug("调试信息");
logger.info("普通信息");
logger.success("操作成功");
logger.warn("警告信息");
logger.error("错误信息");
logger.fatal("致命错误");实战示例
1. 在认证模块中记录登录行为
import { createModuleLogger } from "@mono/logs";
const authLogger = createModuleLogger("auth");
export async function signIn(email: string) {
authLogger.info("开始登录流程", { email });
try {
const user = await findUserByEmail(email);
if (!user) {
authLogger.warn("用户不存在", { email });
return null;
}
authLogger.success("登录成功", { userId: user.id });
return user;
} catch (error) {
authLogger.error("登录失败", {
email,
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
}2. 在 API 路由中记录请求耗时
import { createModuleLogger } from "@mono/logs";
const apiLogger = createModuleLogger("api");
export async function GET(request: Request) {
const start = Date.now();
apiLogger.debug("收到请求", {
method: request.method,
url: request.url,
});
try {
const data = await getDashboardData();
const duration = Date.now() - start;
apiLogger.info("请求处理完成", {
duration,
status: 200,
});
return Response.json(data);
} catch (error) {
apiLogger.error("请求处理失败", {
error: error instanceof Error ? error.message : String(error),
});
return Response.json({ error: "Internal Server Error" }, { status: 500 });
}
}3. 在邮件发送场景中记录成功和失败
import { createModuleLogger } from "@mono/logs";
const mailLogger = createModuleLogger("mail");
export async function sendWelcomeEmail(to: string) {
mailLogger.info("准备发送欢迎邮件", { to });
try {
await sendViaProvider({
to,
subject: "Welcome",
});
mailLogger.success("欢迎邮件发送成功", { to });
} catch (error) {
mailLogger.error("欢迎邮件发送失败", {
to,
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
}4. 在批处理任务中记录任务进度
import { createModuleLogger } from "@mono/logs";
const jobLogger = createModuleLogger("jobs");
export async function processBatch(batchId: string, items: string[]) {
jobLogger.info("批处理任务开始", {
batchId,
total: items.length,
});
for (const [index, item] of items.entries()) {
jobLogger.debug("处理单条记录", {
batchId,
item,
progress: `${index + 1}/${items.length}`,
});
await processItem(item);
}
jobLogger.success("批处理任务完成", { batchId });
}输出格式说明
开发环境
开发环境下:
- 开启颜色输出
- 不显示时间戳
- 更适合本地调试阅读
生产环境
生产环境下:
- 不使用颜色
- 显示时间戳
- 输出更紧凑
- 更适合容器日志、日志采集平台和监控系统
与日志服务集成
虽然 @mono/logs 当前主要输出到标准输出,但它天然适合和以下平台集成:
- Vercel / Docker / Kubernetes 日志流
- Datadog
- Better Stack
- CloudWatch
- Elasticsearch / OpenSearch
- Loki + Grafana
常见做法是:
- 应用通过
logger输出到 stdout / stderr - 部署平台或日志 agent 负责采集
- 外部日志平台做检索、告警和可视化
示例思路:
import { logger } from "@mono/logs";
export async function handleWebhook(payload: unknown) {
logger.info("收到 webhook 事件", {
source: "stripe",
payloadType: typeof payload,
});
// 后续由平台采集 stdout 输出到外部日志系统
}配置行为
包内部会根据 NODE_ENV 自动切换配置:
const isDev = process.env.NODE_ENV === "development";
const isProd = process.env.NODE_ENV === "production";对应行为:
isProd时默认 level 为3- 非生产环境默认 level 为
4 - 生产环境显示日期并启用紧凑格式
- 开发环境启用颜色
注意:实际底层由
consola控制展示行为,因此建议以本包导出的 logger 为唯一入口,避免各处自行创建 logger 造成风格不一致。
API 一览
logger
默认日志实例。
import { logger } from "@mono/logs";
logger.info("hello");
logger.error(new Error("boom"));createModuleLogger(module: string)
创建带 tag 的 logger。
import { createModuleLogger } from "@mono/logs";
const logger = createModuleLogger("uploads");
logger.info("开始上传文件");最佳实践
1. 每个模块使用自己的 logger
const authLogger = createModuleLogger("auth");
const storageLogger = createModuleLogger("storage");2. 记录结构化上下文
logger.info("订单创建成功", {
orderId,
userId,
amount,
});不要只写模糊文本:
logger.info("订单成功");3. 不要记录敏感信息
避免输出:
- 密码
- token
- cookie
- 身份证号
- 完整手机号 / 邮箱(必要时脱敏)
logger.info("用户登录成功", {
userId,
email: maskEmail(email),
});4. 错误日志要带上下文
try {
await saveUser(data);
} catch (error) {
logger.error("保存用户失败", {
userId: data.id,
error: error instanceof Error ? error.message : String(error),
});
throw error;
}5. 用合适的级别
debug:调试过程info:正常业务事件warn:可恢复问题error:失败但系统可继续运行fatal:系统级不可恢复故障
测试中的使用建议
在测试里通常只需要验证:
- logger 是否可创建
- 模块 logger 是否带 tag
- 错误对象是否能被安全记录
- 环境配置是否正确生效
如果测试输出过多,可以在测试环境中减少日志输出,或者仅测试 logger 接口行为。
总结
@mono/logs 的目标不是做复杂日志平台,而是提供一个:
- 足够轻量
- 输出风格统一
- 便于模块隔离
- 适合生产采集
的日志基础设施。
如果你在新增模块,建议第一步就是:
const logger = createModuleLogger("your-module");然后在关键成功、失败和异常路径中补齐必要日志。