logger.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package logger
  2. import (
  3. "bytes"
  4. "github.com/gin-gonic/gin"
  5. "github.com/sirupsen/logrus"
  6. "io/ioutil"
  7. "net/http"
  8. "strings"
  9. "time"
  10. )
  11. // LogToFile 日志记录到文件
  12. func LogToFile() gin.HandlerFunc {
  13. return func(ctx *gin.Context) {
  14. // 初始化bodyLogWriter
  15. blw := &bodyLogWriter{
  16. body: bytes.NewBufferString(""),
  17. ResponseWriter: ctx.Writer,
  18. }
  19. ctx.Writer = blw
  20. // 开始时间
  21. startTime := time.Now()
  22. // 请求方式
  23. reqMethod := ctx.Request.Method
  24. // 请求路由
  25. reqUri := ctx.Request.RequestURI
  26. //如果是查询日志,则跳出,不记录日志
  27. if strings.Contains(reqUri, "/api/blade-log/usual") {
  28. ctx.Next()
  29. return
  30. }
  31. //请求参数
  32. request := getRequestBody(ctx)
  33. if v, ok := request.(string); ok && len(v) > 2560 {
  34. request = "none"
  35. }
  36. // 请求IP
  37. clientIP := ctx.ClientIP()
  38. // 处理请求
  39. ctx.Next()
  40. // 结束时间
  41. endTime := time.Now()
  42. // 执行时间
  43. latencyTime := endTime.Sub(startTime)
  44. // 状态码
  45. statusCode := ctx.Writer.Status()
  46. // 响应
  47. response := blw.body.String()
  48. if len(response) > 2560 {
  49. response = "none"
  50. }
  51. //日志格式
  52. Logger.WithFields(logrus.Fields{
  53. "status_code": statusCode,
  54. "latency_time": latencyTime,
  55. "client_ip": clientIP,
  56. "req_method": reqMethod,
  57. "request": request,
  58. "response": response,
  59. "req_uri": reqUri,
  60. "t": time.Now().UnixMilli(), //用于es中按时间排序
  61. }).Info()
  62. }
  63. }
  64. func getRequestBody(ctx *gin.Context) interface{} {
  65. if strings.Contains(ctx.ContentType(), "multipart/form-data") {
  66. return "multipart"
  67. }
  68. switch ctx.Request.Method {
  69. case http.MethodGet:
  70. fallthrough
  71. case http.MethodDelete:
  72. return ctx.Request.URL.Query()
  73. case http.MethodPost:
  74. fallthrough
  75. case http.MethodPut:
  76. fallthrough
  77. case http.MethodPatch:
  78. var bodyBytes []byte
  79. bodyBytes, err := ioutil.ReadAll(ctx.Request.Body)
  80. if err != nil {
  81. return nil
  82. }
  83. ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
  84. return string(bodyBytes)
  85. }
  86. return nil
  87. }
  88. // bodyLogWriter 定义一个存储响应内容的结构体
  89. type bodyLogWriter struct {
  90. gin.ResponseWriter
  91. body *bytes.Buffer
  92. }
  93. // Write 读取响应数据
  94. func (w bodyLogWriter) Write(b []byte) (int, error) {
  95. w.body.Write(b)
  96. return w.ResponseWriter.Write(b)
  97. }