00 / 00
日志工具
服务端与浏览器日志记录工具,基于 evlog 封装
这是什么
@repo/logger 是模板里的统一日志工具,帮你记录服务端请求、后台任务、浏览器错误和关键业务事件。它分成两个入口:
@repo/logger/server:服务端、Hono、oRPC、后台任务使用@repo/logger/client:浏览器端错误、交互事件和用户上下文使用
底层基于 evlog 的结构化日志模型,默认会对常见敏感字段做脱敏。
能做什么
- 服务端事件 -- 记录接口、任务、支付、上传等结构化事件
- 请求日志 -- Hono 和 TanStack Start 中间件可以挂载 request-scoped logger
- 浏览器日志 -- 浏览器端可以输出到控制台,也可以投递到日志收集接口
- 身份上下文 -- 登录后把用户 ID 写入浏览器日志上下文,退出时清理
- 错误解析 --
createError()/parseError()用于把未知错误整理成响应安全的结构
怎么用
服务端初始化
在应用启动时初始化一次:
import { initLogger, LOG_SERVICES } from "@repo/logger/server";
initLogger({
env: {
environment: process.env.NODE_ENV,
service: LOG_SERVICES.WEB_SERVER,
version: process.env.SOURCE_COMMIT,
},
});服务端记录事件
import { log } from "@repo/logger/server";
log.info({ event: "payment_created", orderId: "order_123" });
log.warn({ event: "upload_retry", attempt: 2 });
log.error({ event: "rpc_handler_error", error });独立任务或脚本
import { createLogger } from "@repo/logger/server";
const logger = createLogger({ job: "sync_users" });
logger.set({ users: { processed: 42 } });
logger.emit({ event: "job_completed" });解析错误
import { createError, parseError } from "@repo/logger/server";
throw createError({
message: "Checkout failed",
status: 402,
why: "Card declined by issuer",
});
const parsed = parseError(error);浏览器端
import { initLog, LOG_SERVICES, log, setIdentity } from "@repo/logger/client";
initLog({
batchedTransport: {
drain: {
credentials: "include",
endpoint: "/_logs/ingest",
},
},
service: LOG_SERVICES.WEB_CLIENT,
});
setIdentity({ user: { id: "user_123" } });
log.info({ event: "profile_saved" });大概原理
项目里主要做三件事:
- 服务端通过
initLogger()设置 service、版本、环境和脱敏规则 - Hono / TanStack Start 中间件把请求信息挂到 request logger 上
- 浏览器端通过
initLog()把事件输出到控制台或发送到日志收集接口
服务端日志输出到标准输出(stdout),部署平台(Cloudflare、Zeabur、Docker、K8s)会自动采集。浏览器日志是否发送到后端,由 batchedTransport.drain.endpoint 决定。
最佳实践
- 用对象记录事件,例如
{ event, userId, orderId },不要只写一句话 - 给事件名取稳定名称,方便后续检索和告警
- 不要记录敏感信息(密码、token、身份证号、完整手机号/邮箱)
- 服务端优先用
@repo/logger/server,浏览器端优先用@repo/logger/client - 浏览器登录后调用
setIdentity(),退出后调用clearIdentity() - 错误日志要附带上下文,方便定位问题
相关链接
这篇文档有问题?