logger.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package middleware
  2. import (
  3. "bytes"
  4. "fmt"
  5. "time"
  6. "git.qianqiusoft.com/public/glog"
  7. "git.qianqiusoft.com/qianqiusoft/light-apiengine/config"
  8. "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
  9. "github.com/gin-gonic/gin"
  10. )
  11. /**
  12. * 自定义日志响应类,主要是把resp的响应内容写入到body中
  13. */
  14. type loggerRespWriter struct {
  15. gin.ResponseWriter
  16. respBody *bytes.Buffer
  17. }
  18. // 写字节数组
  19. func (w loggerRespWriter) Write(b []byte) (int, error) {
  20. w.respBody.Write(b) // 保存
  21. return w.ResponseWriter.Write(b)
  22. }
  23. // 写字符串
  24. func (w loggerRespWriter) WriteString(s string) (int, error) {
  25. w.respBody.WriteString(s) // 保存
  26. return w.ResponseWriter.WriteString(s)
  27. }
  28. /**
  29. * 日志信息
  30. */
  31. type LogInfo struct {
  32. ReqClientIp string
  33. ReqTime time.Time
  34. ReqMethod string
  35. ReqUrl string
  36. ReqProto string
  37. ReqUa string
  38. ReqReferer string
  39. Header []byte
  40. LoginId string
  41. ReqHeader []byte
  42. ReqBody []byte
  43. RespTime time.Time
  44. RespBody []byte
  45. CostTime float64
  46. }
  47. var bucket utils.SyncSlice
  48. // 日志chan
  49. var __logInfoChan chan *LogInfo
  50. // app名称
  51. var __appName string = ""
  52. // 日志处理函数
  53. var __logHandler func(info []LogInfo) = nil
  54. func init() {
  55. defer func() {
  56. if p := recover(); p != nil {
  57. glog.Errorln("ecover", p)
  58. }
  59. }()
  60. // 设置app名称
  61. __appName = config.AppConfig.GetKey("app_name")
  62. __logInfoChan = make(chan *LogInfo, 2000)
  63. // 日志处理
  64. logProcess()
  65. }
  66. // 设置日志处理接口
  67. func SetLogHandler(handler func(info []LogInfo)) {
  68. __logHandler = handler
  69. }
  70. // 获取日志中间件
  71. func LoggerMiddleware() gin.HandlerFunc {
  72. return func(c *gin.Context) {
  73. respWriter := &loggerRespWriter{
  74. ResponseWriter: c.Writer,
  75. respBody: bytes.NewBuffer([]byte{}),
  76. }
  77. c.Writer = respWriter // 注入自定writer
  78. logInfo := &LogInfo{}
  79. logInfo.ReqTime = time.Now()
  80. // 下一个请求
  81. c.Next()
  82. hByte := bytes.Buffer{}
  83. bByte := make([]byte, 1024)
  84. cReq := c.Request.Clone(c)
  85. cReq.Header.Write(&hByte)
  86. rbn, _ := cReq.Body.Read(bByte)
  87. // 设置对象
  88. logInfo.RespBody = respWriter.respBody.Bytes()
  89. logInfo.RespTime = time.Now()
  90. logInfo.ReqMethod = c.Request.Method
  91. logInfo.ReqUrl = c.Request.RequestURI
  92. logInfo.ReqProto = c.Request.Proto
  93. logInfo.ReqUa = c.Request.UserAgent()
  94. logInfo.ReqReferer = c.Request.Referer()
  95. logInfo.ReqBody = bByte[0:rbn]
  96. logInfo.ReqHeader = hByte.Bytes()
  97. logInfo.ReqClientIp = c.ClientIP()
  98. logInfo.CostTime = float64(logInfo.RespTime.Sub(logInfo.ReqTime).Seconds())
  99. token := c.GetHeader("token")
  100. if token != "" {
  101. tk := utils.GetGlobalTokenStore().Get(token)
  102. if tk != nil {
  103. logInfo.LoginId = tk.LoginID
  104. }
  105. }
  106. if logInfo.LoginId == "" {
  107. logInfo.LoginId = "__no_login__"
  108. }
  109. __logInfoChan <- logInfo
  110. }
  111. }
  112. // 日志处理进程
  113. func logProcess() {
  114. go func() {
  115. defer func() {
  116. if rec := recover(); rec != nil {
  117. fmt.Println(rec)
  118. }
  119. }()
  120. for {
  121. select {
  122. case <-time.Tick(6 * time.Second):
  123. if __logHandler != nil {
  124. logs := []LogInfo{}
  125. for _, v := range bucket.Reset() {
  126. logs = append(logs, *v.(*LogInfo))
  127. }
  128. __logHandler(logs)
  129. }
  130. case logInfo := <-__logInfoChan:
  131. if __logHandler != nil {
  132. bucket.Append(logInfo)
  133. }
  134. }
  135. }
  136. }()
  137. }