Go Web Lightweight Framework Gin Learning Series: Журнал HTTP-запросов

Go

Оригинальный автор, публичный аккаунт [программист чтение], прошу обратить внимание на паблик аккаунт, просьба указывать источник перепечатываемой статьи.

Мы знаем, что каждый веб-запрос, инициированный пользователем к серверу, будет нести много метаинформации запроса на сервер через заголовок или тело протокола 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-запросов соответствует поведению запросов пользователя, и запись каждого журнала запросов пользователей очень важна для нас, чтобы отслеживать поведение пользователей, фильтровать незаконные запросы пользователей и устранять различные проблемы, вызванные работой программы.Поэтому при разработке веб-приложений обязательно записывать поведение запросов пользователей, а также регулярно анализировать и фильтровать.


Ваше внимание — самое большое поощрение на моем писательском пути!