很多 Go 项目一提到“请求追踪”,就容易先想到链路平台、结构化日志或复杂中间件;但对不少中小型服务来说,先把一次 HTTP 请求在日志里完整串起来,往往更重要。本文用标准库 log 做一个最小可用示例,说明请求日志该打在哪些位置、怎样快速看懂一条请求的执行过程,以及什么时候再考虑升级到 logrus、zap 这类更完整的日志方案。
请求追踪最少要记哪些信息
在 Golang 里做日志追踪,并不一定要引入额外框架。只要把打点位置选对,标准库自带的 log 包就足以覆盖大部分基础场景。
一条请求想要被清楚还原,最关键的是三个节点:
- 请求开始:记录请求进入服务的时间、方法和路径。
- 处理过程:在关键业务步骤补充日志,帮助判断请求卡在哪一步。
- 请求结束:记录处理完成时间,并输出总耗时。
这三个点连起来后,排查问题时通常就能回答几个最常见的问题:请求有没有进来、执行到了哪里、总共花了多久。对刚起步的接口服务来说,这已经能解决相当一部分定位需求。
用标准库 log 实现一个基础追踪器
下面这个例子就是最朴素的做法,没有额外封装,也没有复杂配置,重点是把请求的开始和结束日志明确打出来。
package main
import (
"fmt"
"log"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", requestHandler)
log.Println("Server started on port 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func requestHandler(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
log.Printf("Request started: %s %s", r.Method, r.URL.Path)
// 模拟处理过程
time.Sleep(1 * time.Second)
log.Printf("Request finished: %s %s, duration: %v", r.Method, r.URL.Path, time.Since(startTime))
fmt.Fprintf(w, "Hello, Golang!")
}
这段代码的结构很直接:
main函数里注册了/路由,并通过http.ListenAndServe(":8080", nil)启动 HTTP 服务。- 服务启动时先输出
Server started on port 8080,方便确认程序已经对外监听。 - 进入
requestHandler后,先用time.Now()记录请求开始时间。 - 随后通过
log.Printf("Request started: %s %s", r.Method, r.URL.Path)把请求方法和路径写入日志。 - 中间用
time.Sleep(1 * time.Second)模拟业务处理过程。 - 结束时再通过
time.Since(startTime)计算耗时,并输出完成日志。 - 最后返回
Hello, Golang!作为响应内容。
这种方式的价值不在“功能多”,而在于足够直观。只看日志内容,就能顺着时间线判断某个请求是否正常结束,以及耗时是否异常。
怎么看懂这一套日志的作用
如果把这段处理逻辑看成一条线,请求进入服务后先落一条开始日志,中间执行业务,最后再落一条结束日志。这样做有两个直接好处。
先确认请求是否真正进入处理函数
只要出现 Request started,就说明请求已经到达对应处理函数;如果连这条都没有,排查方向就应该回到路由、监听端口、网关转发或上游调用。

再根据耗时判断问题出在处理阶段还是外部环节
结束日志里带有 duration,可以帮助你快速判断这次请求是不是明显变慢。哪怕示例里只模拟了 1 * time.Second,实际业务里也能用同样方法观察数据库查询、远程调用或本地计算是否拖长了响应时间。
从这个角度看,请求追踪并不神秘,本质上就是把“什么时候开始、做了什么、什么时候结束”这条时间线记录清楚。日志写得越贴近请求流程,排错时就越省时间。
什么时候该从标准库升级到第三方日志库
标准库 log 适合先把基础能力搭起来,但项目规模一旦上去,单纯的文本日志通常就会开始吃力。原文提到的几个典型场景就很有代表性:
- 需要结构化日志,方便字段检索和统一分析。
- 需要按日志级别过滤输出。
- 需要输出 JSON 格式,对接日志平台或分析系统。
这时候可以考虑换成 logrus、zap 等第三方库。它们和标准库在使用思路上并没有本质区别,核心仍然是在关键环节打点,只是输出能力、字段组织方式和后续处理体验更强。
换句话说,升级的触发点不该是“别人都在用”,而应该是你已经遇到明确需求:日志需要被机器稳定解析,需要按级别筛选,或者需要更高性能、更统一的格式。否则,先用标准库把请求开始、过程、结束这条骨架跑通,往往是更务实的选择。
更适合落地的实践顺序
对多数 Go Web 服务来说,请求日志追踪可以按一个很简单的顺序推进:先用标准库把入口、过程、出口三个位置记录完整,确认日志能真实反映请求执行路径;之后再根据项目复杂度决定是否升级到结构化日志方案。
这样做的好处是,团队一开始就能获得稳定、可读、能排查问题的日志,而不是在工具选型上花太多精力。无论最终用的是 log、logrus 还是 zap,真正决定日志是否有用的,始终是打点位置是否准确、耗时信息是否完整,以及日志是否能对应回具体请求流程。








