你有没有遇到过这种情况:用户说他提交了订单,但后台查不到;或者某个接口突然变慢,却不知道是哪个环节出了问题?这时候,最靠谱的“目击证人”往往不是代码,也不是监控图表,而是日志——尤其是客户端请求处理过程中的日志记录。
为什么需要记录客户端请求
每个来自浏览器、App 或第三方服务的请求,都是系统运行的一次“动作”。如果不记录,就像在黑夜里开车,出了问题只能靠猜。而一旦把请求进来的时间、来源、参数、处理路径都记下来,排查问题就变成了“看录像回放”。
比如某天运营反馈说促销活动页面打不开,开发一查日志,发现大量请求卡在用户鉴权环节,进一步追踪发现是认证服务响应超时。如果没有这些日志,可能得花半天时间从前端到网关一层层排查。
记录哪些关键信息
不是所有日志都有用。太多无意义的日志反而会淹没关键信息。一个有效的客户端请求日志,通常包含以下几个字段:
- 请求唯一ID(用于链路追踪)
- 客户端IP和User-Agent
- 请求路径和方法(GET/POST等)
- 请求参数(敏感信息需脱敏)
- 进入时间和处理耗时
- 响应状态码和大小
- 关联的用户ID或会话ID
这些信息组合起来,就能还原出一次请求的完整生命周期。
实际代码怎么写
以一个常见的Node.js服务为例,可以用中间件的方式统一记录:
const logger = require('winston');
app.use((req, res, next) => {
const start = Date.now();
const requestId = generateId(); // 生成唯一请求ID
req.log = logger.child({ requestId });
req.log.info('request received', {
method: req.method,
url: req.url,
ip: req.ip,
userAgent: req.get('User-Agent'),
query: req.query,
body: maskSensitiveData(req.body) // 脱敏处理
});
const originalEnd = res.end;
res.end = function(chunk) {
const duration = Date.now() - start;
req.log.info('response sent', {
statusCode: res.statusCode,
contentLength: chunk ? Buffer.byteLength(chunk) : 0,
durationMs: duration
});
originalEnd.call(this, chunk);
};
next();
});
避免踩坑
日志不是越多越好。曾经有个项目每条请求都打印完整Body,结果日志文件一天就涨到几十GB,磁盘爆满导致服务瘫痪。后来加上了采样机制,只记录1%的请求详情,常规请求只记关键字段,问题才缓解。
另外,别忘了设置合理的日志保留策略。生产环境一般保留7到30天,太长占用存储,太短查历史问题时又找不到数据。
配合工具才能发挥最大价值
光有日志不够,还得能快速检索。ELK(Elasticsearch + Logstash + Kibana)或者 Loki + Grafana 这类组合,能把分散的日志集中起来,支持按关键词、状态码、耗时等条件过滤。比如想查昨天所有500错误的请求,几秒钟就能出结果。
再加上分布式追踪系统(如Jaeger或Zipkin),还能把一个请求经过的多个服务串联起来,真正实现端到端可观测。