Оригинальный автор, публичный аккаунт [программист чтение], прошу обратить внимание на паблик аккаунт, просьба указывать источник перепечатываемой статьи.
Мы знаем, что каждый веб-запрос, инициированный пользователем к серверу, будет нести много метаинформации запроса на сервер через заголовок или тело протокола HTTP, например запрошенный 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.Engine
Экземпляр по умолчанию использует ПО промежуточного слоя журнала.gin.Logger()
, поэтому, когда мы используем второй способ созданияgin.Engine
, вы можете позвонитьgin.Engine
серединаUse()
вызов методаgin.Logger()
,следующее:
router := gin.New()
router.Use(gin.Logger())
вывод лога в консоль
Журнал запросов Gin framework по умолчанию выводится в консоль нашей работающей программы, а некоторые шрифты в выходном журнале окрашены, как показано на следующем рисунке:
Конечно, мы можем использоватьDisableConsoleColor()
Функция отключает цветной вывод лога консоли, код такой
gin.DisableConsoleColor()//禁用请求日志控制台字体颜色
router := gin.Default()
router.GET("test",func(c *gin.Context){
c.JSON(200,"test")
})
После выполнения веб-запроса шрифт журнала в выводе консоли не имеет цвета:
Хотя фреймворк Gin по умолчанию использует цвет шрифта начального журнала, вы можете использоватьDisableConsoleColor()
функцию отключить, но когда она отключена, при запуске в программе необходимо повторно открыть цвет шрифта вывода журнала консоли, вы можете использоватьForceConsoleColor()
Функция перезапускается и используется следующим образом:
gin.ForceConsoleColor()
вывод журнала в файл
Журнал запросов фреймворка Gin по умолчанию выводится в консоль, но чаще, особенно при работе в сети, мы хотим сохранить журнал запросов пользователя в файл журнала для лучшего анализа и резервного копирования.
1. DefaultWriter
В рамках Gin черезgin.DefaultWriter
Переменные могут контролировать способ сохранения журнала,gin.DefaultWriter
Определение в рамках Gin выглядит следующим образом:
var DefaultWriter io.Writer = os.Stdout
Из вышеприведенного определения мы видим, чтоgin.DefaultWriter
имеет типio.Writer
, значение по умолчаниюos.Stdout
, который является выводом консоли, поэтому мы можем изменитьgin.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.log
файл, когда мы инициируем веб-запрос, журнал запросов будет сохранен вaccess.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, но формат по умолчанию может не соответствовать нашим потребностям, поэтому мы можем использовать формат журнала, предоставляемый средой Gin.gin.LoggterWithFormatter()
промежуточное ПО, настраиваемый формат журнала,gin.LoggterWithFormatter()
Промежуточное ПО определяется следующим образом:
func LoggerWithFormatter(f LogFormatter) HandlerFunc
отgin.LoggterWithFormatter()
Определение промежуточного программного обеспечения может видеть, что промежуточное программное обеспечение принимает тип данныхLogFormatter
параметр,LogFormatter
Определяется следующим образом:
type LogFormatter func(params LogFormatterParams) string
отLogFormatter
Определение рассматривает тип какfunc(params LogFormatterParams) string
функция, параметры которойLogFormatterParams
, который определяется следующим образом:
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")
}
После запуска вышеуказанной программы инициируйте веб-запрос, и консоль выведет журнал запросов в следующем формате:
::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.LoggerWithWriter
Чтобы записать журнал в файл, используйтеgin.LoggerWithFormatter
Настройте формат журнала, но на самом деле нижние слои этих трех промежуточных программ вызываютgin.LoggerWithConfig
промежуточное ПО, то есть мы используемgin.LoggerWithConfig
промежуточного программного обеспечения, вы можете выполнять все функции вышеуказанного промежуточного программного обеспечения,gin.LoggerWithConfig
определяется следующим образом:
func LoggerWithConfig(conf LoggerConfig) HandlerFunc
gin.LoggerWithConfig
Параметры промежуточного программного обеспечения:LoggerConfig
структуру, которая определяется следующим образом:
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")
}
После запуска вышеуказанной программы инициируйте веб-запрос, и консоль выведет журнал запросов в следующем формате:
::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-запросов соответствует поведению запросов пользователя, и запись каждого журнала запросов пользователей очень важна для нас, чтобы отслеживать поведение пользователей, фильтровать незаконные запросы пользователей и устранять различные проблемы, вызванные работой программы.Поэтому при разработке веб-приложений обязательно записывать поведение запросов пользователей, а также регулярно анализировать и фильтровать.
Ваше внимание — самое большое поощрение на моем писательском пути!