[Серия] — промежуточное ПО для маршрутизации go-gin-api — ведение журнала (3)

Go Gin

Обзор

Сначала синхронизируйте обзор проекта:

Последняя опубликованная статья посвящена планированию каталога проекта и проверке параметров, в которой для проверки параметров используется версия validator.v8, которая была обновлена ​​до версии validator.v9, а последний код можно просмотреть на github.

В этой статье мы поделимся: Промежуточное ПО для маршрутизации — ведение журнала.

Журнал - это особенно важная вещь, которая нам удобна для устранения проблемы.В этой статье мы реализуем лог в текстовый файл.

Вот что я запланировал и параметры, которые нужно записать:

- request 请求数据
    - request_time
    - request_method
    - request_uri
    - request_proto
    - request_ua
    - request_referer
    - request_post_data
    - request_client_ip
    
- response 返回数据
    - response_time
    - response_code
    - response_msg
    - response_data
    
- cost_time 花费时间

Фреймворк Gin поставляется с промежуточным программным обеспечением Logger.Мы знаем, соответствует ли промежуточное программное обеспечение Logger, которое поставляется с фреймворком, нашим потребностям?

gin.Logger()

Давайте сначала воспользуемся gin.Logger(), чтобы увидеть эффект.

Добавьте код в метод SetupRouter route.go:

engine.Use(gin.Logger())

После запуска запроса несколько раз, вывод журнала находится в командной строке:

[GIN] 2019/08/30 - 21:24:16 | 200 |     178.072µs |             ::1 | GET      /ping
[GIN] 2019/08/30 - 21:24:27 | 200 |     367.997µs |             ::1 | POST     /product
[GIN] 2019/08/30 - 21:24:28 | 200 |    2.521592ms |             ::1 | POST     /product

Сначала решим первую задачу, как вывести лог в текст?

Добавьте код в метод SetupRouter route.go:

f, _ := os.Create(config.AppAccessLogName)
gin.DefaultWriter = io.MultiWriter(f)
engine.Use(gin.Logger())

После запуска запроса несколько раз вывод лога в файл:

[GIN] 2019/08/30 - 21:36:07 | 200 |     369.023µs |             ::1 | GET      /ping
[GIN] 2019/08/30 - 21:36:08 | 200 |      27.585µs |             ::1 | GET      /ping
[GIN] 2019/08/30 - 21:36:10 | 200 |      14.302µs |             ::1 | POST     /product

Хотя запись в файл прошла успешно, записанные параметры не те, что нам нужны.

Как это сделать?

Нам нужно настроить промежуточное программное обеспечение журнала для записи в соответствии с нужными нам параметрами.

Пользовательский регистратор()

middleware/logger/logger.go

package logger

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"go-gin-api/app/config"
	"go-gin-api/app/util"
	"log"
	"os"
)

type bodyLogWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}
func (w bodyLogWriter) Write(b []byte) (int, error) {
	w.body.Write(b)
	return w.ResponseWriter.Write(b)
}
func (w bodyLogWriter) WriteString(s string) (int, error) {
	w.body.WriteString(s)
	return w.ResponseWriter.WriteString(s)
}

func SetUp() gin.HandlerFunc {
	return func(c *gin.Context) {
		bodyLogWriter := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
		c.Writer = bodyLogWriter

		//开始时间
		startTime := util.GetCurrentMilliTime()

		//处理请求
		c.Next()

		responseBody := bodyLogWriter.body.String()

		var responseCode int
		var responseMsg  string
		var responseData interface{}

		if responseBody != "" {
			response := util.Response{}
			err := json.Unmarshal([]byte(responseBody), &response)
			if err == nil {
				responseCode = response.Code
				responseMsg  = response.Message
				responseData = response.Data
			}
		}

		//结束时间
		endTime := util.GetCurrentMilliTime()

		if c.Request.Method == "POST" {
			c.Request.ParseForm()
		}

		//日志格式
		accessLogMap := make(map[string]interface{})

		accessLogMap["request_time"]      = startTime
		accessLogMap["request_method"]    = c.Request.Method
		accessLogMap["request_uri"]       = c.Request.RequestURI
		accessLogMap["request_proto"]     = c.Request.Proto
		accessLogMap["request_ua"]        = c.Request.UserAgent()
		accessLogMap["request_referer"]   = c.Request.Referer()
		accessLogMap["request_post_data"] = c.Request.PostForm.Encode()
		accessLogMap["request_client_ip"] = c.ClientIP()

		accessLogMap["response_time"] = endTime
		accessLogMap["response_code"] = responseCode
		accessLogMap["response_msg"]  = responseMsg
		accessLogMap["response_data"] = responseData

		accessLogMap["cost_time"] = fmt.Sprintf("%vms", endTime - startTime)

		accessLogJson, _ := util.JsonEncode(accessLogMap)

		if f, err := os.OpenFile(config.AppAccessLogName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666); err != nil {
			log.Println(err)
		} else {
			f.WriteString(accessLogJson + "\n")
		}
	}
}

После запуска запроса несколько раз вывод лога в файл:

{"cost_time":"0ms","request_client_ip":"::1","request_method":"GET","request_post_data":"","request_proto":"HTTP/1.1","request_referer":"","request_time":1567172568233,"request_ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36","request_uri":"/ping","response_code":1,"response_data":null,"response_msg":"pong","response_time":1567172568233}
{"cost_time":"0ms","request_client_ip":"::1","request_method":"GET","request_post_data":"","request_proto":"HTTP/1.1","request_referer":"","request_time":1567172569158,"request_ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36","request_uri":"/ping","response_code":1,"response_data":null,"response_msg":"pong","response_time":1567172569158}
{"cost_time":"0ms","request_client_ip":"::1","request_method":"POST","request_post_data":"name=admin","request_proto":"HTTP/1.1","request_referer":"","request_time":1567172629565,"request_ua":"PostmanRuntime/7.6.0","request_uri":"/product","response_code":-1,"response_data":null,"response_msg":"Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag","response_time":1567172629565}

OK, все нужные нам параметры записаны!

Задайте несколько вопросов:

1. Существуют ли инструменты ведения журнала с открытым исходным кодом?

Конечно есть,из которых логрус самый используемый.Этот инструмент мощный.Я им тоже поделился.Вы можете прочитать оригинал статьи."Сбор логов с логрусом".

2. Зачем входить в текст?

Потому что лог-платформа может использовать ELK.

Используйте Logstash для сбора текстовых файлов, используйте механизм Elasticsearch для анализа поиска и, наконец, отобразите их на платформе Kibana.

3. При большом количестве запросов не будет ли проблем с записью в файл?

Может быть, этот кусок может использовать асинхронность, мы можем использовать go's chan, смотрите код конкретной реализации, я не буду его выкладывать.

Адрес источника

GitHub.com/Бессердечный не…

серия статей go-gin-api