原创作者,公众号【程序员读书】,欢迎关注公众号,转载文章请注明出处哦。
我们知道,用户向服务器发起的每一次Web请求,都会通过HTTP协议头部或Body携带许多的请求元信息给服务器,如请求的URL地址,请求方法,请求头部和请求IP地址等等诸多原始信息,而在Gin框架中,我们可以使用日志的方式记录和输出这些信息,记录用户的每一次请求行为。
下面是一条Gin框架在控制台中输出的日志:
[GIN] 2019/05/04 - 22:08:56 | 200 | 5.9997ms | ::1 | GET /test
好了,下面看看要如何输出上面的日志吧!
日志中件间
在Gin框架中,要输出用户的http请求日志,最直接简单的方式就是借助日志中间件,下面Gin框架的中间件定义:
func Logger() HandlerFunc
gin.Engine
router := gin.Default()
gin.Engine
router := gin.New()
Default()gin.Enginegin.Logger()gin.Enginegin.EngineUse()gin.Logger()
router := gin.New()
router.Use(gin.Logger())
在控制台输出日志
Gin框架请求日志默认是在我们运行程序的控制台中输出,而且输出的日志中有些字体有标颜色,如下图所示:
DisableConsoleColor()
gin.DisableConsoleColor()//禁用请求日志控制台字体颜色
router := gin.Default()
router.GET("test",func(c *gin.Context){
c.JSON(200,"test")
})
运行后发出Web请求,在控制台输出日志字体则没有颜色:
DisableConsoleColor()ForceConsoleColor()
gin.ForceConsoleColor()
在文件输出日志
Gin框架的请求日志默认在控制台输出,但更多的时候,尤其上线运行时,我们希望将用户的请求日志保存到日志文件中,以便更好的分析与备份。
1. DefaultWriter
gin.DefaultWritergin.DefaultWriter
var DefaultWriter io.Writer = os.Stdout
gin.DefaultWriterio.Writeros.Stdoutgin.DefaultWriter
package main
import (
"github.com/gin-gonic/gin"
"io"
"os"
)
func main() {
gin.DisableConsoleColor()//保存到文件不需要颜色
file, _ := os.Create("access.log")
gin.DefaultWriter = file
//gin.DefaultWriter = io.MultiWriter(file) 效果是一样的
router := gin.Default()
router.GET("/test", func(c *gin.Context) {
c.String(200, "test")
})
_ = router.Run(":8080")
}
access.logaccess.log
通过下面的代码,也可能让请求日志同行保存到文件和在控制台输出:
file, _ := os.Create("access.log")
gin.DefaultWriter = io.MultiWriter(file,os.Stdout) //同时保存到文件和在控制台中输出
2. LoggerWithWriter
gin.LoggerWithWriter
func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc
示例代码:
package main
import (
"github.com/gin-gonic/gin"
"os"
)
func main() {
gin.DisableConsoleColor()
router := gin.New()
file, _ := os.Create("access.log")
router.Use(gin.LoggerWithWriter(file,""))
router.GET("test", func(c *gin.Context) {
c.JSON(200,"test")
})
_ = router.Run()
}
gin.LoggerWithWriter/test/ping
router.Use(gin.LoggerWithWriter(file,"/test"))//指定/test请求不输出日志
router.GET("test", func(c *gin.Context) {
c.JSON(200,"test")
})
router.GET("ping", func(c *gin.Context) {
c.JSON(200,"pong")
})
定制日志格式
1. LogFormatterParams
gin.LoggterWithFormatter()gin.LoggterWithFormatter()
func LoggerWithFormatter(f LogFormatter) HandlerFunc
gin.LoggterWithFormatter()LogFormatterLogFormatter
type LogFormatter func(params LogFormatterParams) string
LogFormatterfunc(params LogFormatterParams) stringLogFormatterParams
type LogFormatterParams struct {
Request *http.Request
TimeStamp time.Time
StatusCode int
Latency time.Duration
ClientIP string
Method string
Path string
ErrorMessage string
BodySize int
Keys map[string]interface{}
}
定制日志格式示例代码:
func main() {
router := gin.New()
router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
//定制日志格式
return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
param.ClientIP,
param.TimeStamp.Format(time.RFC1123),
param.Method,
param.Path,
param.Request.Proto,
param.StatusCode,
param.Latency,
param.Request.UserAgent(),
param.ErrorMessage,
)
}))
router.Use(gin.Recovery())
router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
_ = router.Run(":8080")
}
运行上面的程序后,发起Web请求,控制台会输出以下格式的请求日志:
::1 - [Wed, 08 May 2019 21:53:17 CST] "GET /ping HTTP/1.1 200 1.0169ms "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36" "
2. LoggerWithConfig
gin.Logger()gin.LoggerWithWritergin.LoggerWithFormattergin.LoggerWithConfiggin.LoggerWithConfiggin.LoggerWithConfig
func LoggerWithConfig(conf LoggerConfig) HandlerFunc
gin.LoggerWithConfigLoggerConfig
type LoggerConfig struct {
// 设置日志格式
// 可选 默认值为:gin.defaultLogFormatter
Formatter LogFormatter
// Output用于设置日志将写到哪里去
// 可选. 默认值为:gin.DefaultWriter.
Output io.Writer
// 可选,SkipPaths切片用于定制哪些请求url不在请求日志中输出.
SkipPaths []string
}
gin.LoggerConfig
func main() {
router := gin.New()
file, _ := os.Create("access.log")
c := gin.LoggerConfig{
Output:file,
SkipPaths:[]string{"/test"},
Formatter: func(params gin.LogFormatterParams) string {
return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
params.ClientIP,
params.TimeStamp.Format(time.RFC1123),
params.Method,
params.Path,
params.Request.Proto,
params.StatusCode,
params.Latency,
params.Request.UserAgent(),
params.ErrorMessage,
)
},
}
router.Use(gin.LoggerWithConfig(c))
router.Use(gin.Recovery())
router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
router.GET("/test", func(c *gin.Context) {
c.String(200, "test")
})
_ = router.Run(":8080")
}
运行上面的程序后,发起Web请求,控制台会输出以下格式的请求日志:
::1 - [Wed, 08 May 2019 22:39:43 CST] "GET /ping HTTP/1.1 200 0s "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36" "
::1 - [Wed, 08 May 2019 22:39:46 CST] "GET /ping HTTP/1.1 200 0s "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36" "
小结
每条HTTP请求日志,都对应一次用户的请求行为,记录每一条用户请求日志,对于我们追踪用户行为,过滤用户非法请求,排查程序运行产生的各种问题至关重要,因此,开发Web应用时一定要记录用户请求行为,并且定时分析过滤。
你的关注,是我写作路上最大的鼓励!