| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- package middleware
- import (
- "bytes"
- "fmt"
- "time"
- "git.qianqiusoft.com/public/glog"
- "git.qianqiusoft.com/qianqiusoft/light-apiengine/config"
- "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
- "github.com/gin-gonic/gin"
- )
- /**
- * 自定义日志响应类,主要是把resp的响应内容写入到body中
- */
- type loggerRespWriter struct {
- gin.ResponseWriter
- respBody *bytes.Buffer
- }
- // 写字节数组
- func (w loggerRespWriter) Write(b []byte) (int, error) {
- w.respBody.Write(b) // 保存
- return w.ResponseWriter.Write(b)
- }
- // 写字符串
- func (w loggerRespWriter) WriteString(s string) (int, error) {
- w.respBody.WriteString(s) // 保存
- return w.ResponseWriter.WriteString(s)
- }
- /**
- * 日志信息
- */
- type LogInfo struct {
- ReqClientIp string
- ReqTime time.Time
- ReqMethod string
- ReqUrl string
- ReqProto string
- ReqUa string
- ReqReferer string
- Header []byte
- LoginId string
- ReqHeader []byte
- ReqBody []byte
- RespTime time.Time
- RespBody []byte
- CostTime float64
- }
- var bucket utils.SyncSlice
- // 日志chan
- var __logInfoChan chan *LogInfo
- // app名称
- var __appName string = ""
- // 日志处理函数
- var __logHandler func(info []LogInfo) = nil
- func init() {
- defer func() {
- if p := recover(); p != nil {
- glog.Errorln("ecover", p)
- }
- }()
- // 设置app名称
- __appName = config.AppConfig.GetKey("logger_app_name")
- if __appName == "" {
- __appName = config.AppConfig.GetKey("app_name")
- }
- __logInfoChan = make(chan *LogInfo, 2000)
- // 日志处理
- logProcess()
- }
- // 设置日志处理接口
- func SetLogHandler(handler func(info []LogInfo)) {
- __logHandler = handler
- }
- // 获取日志中间件
- func LoggerMiddleware() gin.HandlerFunc {
- return func(c *gin.Context) {
- respWriter := &loggerRespWriter{
- ResponseWriter: c.Writer,
- respBody: bytes.NewBuffer([]byte{}),
- }
- c.Writer = respWriter // 注入自定writer
- logInfo := &LogInfo{}
- logInfo.ReqTime = time.Now()
- // 下一个请求
- c.Next()
- hByte := bytes.Buffer{}
- bByte := make([]byte, 1024)
- cReq := c.Request.Clone(c)
- cReq.Header.Write(&hByte)
- rbn, _ := cReq.Body.Read(bByte)
- // 设置对象
- logInfo.RespBody = respWriter.respBody.Bytes()
- logInfo.RespTime = time.Now()
- logInfo.ReqMethod = c.Request.Method
- logInfo.ReqUrl = c.Request.RequestURI
- logInfo.ReqProto = c.Request.Proto
- logInfo.ReqUa = c.Request.UserAgent()
- logInfo.ReqReferer = c.Request.Referer()
- logInfo.ReqBody = bByte[0:rbn]
- logInfo.ReqHeader = hByte.Bytes()
- logInfo.ReqClientIp = c.ClientIP()
- logInfo.CostTime = float64(logInfo.RespTime.Sub(logInfo.ReqTime).Seconds())
- token := c.GetHeader("token")
- if token != "" {
- tk := utils.GetGlobalTokenStore().Get(token)
- if tk != nil {
- logInfo.LoginId = tk.LoginID
- }
- }
- if logInfo.LoginId == "" {
- logInfo.LoginId = "__no_login__"
- }
- __logInfoChan <- logInfo
- }
- }
- // 日志处理进程
- func logProcess() {
- go func() {
- defer func() {
- if rec := recover(); rec != nil {
- fmt.Println(rec)
- }
- }()
- for {
- select {
- case <-time.Tick(6 * time.Second):
- if __logHandler != nil {
- logs := []LogInfo{}
- for _, v := range bucket.Reset() {
- logs = append(logs, *v.(*LogInfo))
- }
- __logHandler(logs)
- }
- case logInfo := <-__logInfoChan:
- if __logHandler != nil {
- bucket.Append(logInfo)
- }
- }
- }
- }()
- }
|