gin 框架是款高性能的 GoWeb 框架,可以快速开发部署 api 服务。在使用过程中我们需要记录各种各样的日志,下面介绍下我们怎么自定义日志记录格式或扩展日志。
gin 简单剖析
api 服务创建
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
以上是 github 中官方介绍的一个简单的 demo,三步创建了一个 api 服务
-
gin.Default 获取到一个 Engine 实例
-
engine.GET() 添加一个 Get 请求的路由逻辑
-
engine.Run() 启动服务
gin.Default 剖析
func New() *Engine {
debugPrintWARNINGNew()
engine := &Engine{
RouterGroup: RouterGroup{
Handlers: nil,
basePath: "/",
root: true,
},
FuncMap: template.FuncMap{},
RedirectTrailingSlash: true,
RedirectFixedPath: false,
HandleMethodNotAllowed: false,
ForwardedByClientIP: true,
AppEngine: defaultAppEngine,
UseRawPath: false,
UnescapePathValues: true,
trees: make(methodTrees, 0, 9),
delims: render.Delims{"{{", "}}"},
}
engine.RouterGroup.engine = engine
engine.pool.New = func() interface{} {
return engine.allocateContext()
}
return engine
}
// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
gin.Default 通过 New 创建了 Engine 实例, 并 Use 了 Logger Recovery 两个 HandlerFunc 中间件。注释也介绍了
默认返回一个引擎实例,其中包含日志记录器和崩溃恢复中间件。
那么我们是不是可以通过自己的 Logger 中间件来记录日志? 写到这里发现官方文档其实是有介绍的,少走弯路还是先看文档额~~不过直接看源码也没坏处,哈哈
日志中间件
func (c *Context) Next() {
c.index++
s := int8(len(c.handlers))
for ; c.index < s; c.index++ {
c.handlers[c.index](c)
}
}
gin 通过循环当前的中间件处理链 Handler,逐个调用中间件。
自定义日志中间件
-
日志记录(logrus)
logrus 是第三方包,github 上比较活跃,已经实现了很多常用功能,日常开发中用到的较多。 -
日志分割(rotatelogs)
logrus 没有提供日志切分,go-file-rotatelogs 可以实现 linux logratate 的大多数功能。
使用 logrus 的 hook 来加载 github.com/lestrrat/go-file-rotatelogs 模块.每次当我们写入日志的时候,logrus 都会调用 go-file-rotatelogs 来判断日志是否要进行切分…
// Next should be used only inside middleware. // It executes the pending handlers in the chain inside the calling handler. // See example in GitHub. func (c *Context) Next() { c.index++ s := int8(len(c.handlers)) for ; c.index < s; c.index++ { c.handlers[c.index](c) } }
这里面为了计算程序的执行时长, 我们又调用了一次 c.Next(),让后面的中间件执行,这样日志中间件拿到了程序其它所有中间件执行的总时长,认为是程序的处理时间。
c.Next 循环的时候都是同一个 Context 指针上下文,index 下标为共享的数据,我们可以通过调用一次 c.Next 让 log 中间件插一脚。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于