123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- package http_middleware
- import (
- "bytes"
- "fmt"
- "git.aionnect.com/aionnect/go-common/utils/date"
- "git.aionnect.com/aionnect/go-common/utils/logger"
- "github.com/gin-gonic/gin"
- "io"
- "io/ioutil"
- "net/http"
- "strings"
- )
- type bodyBuffer struct {
- bytes.Buffer
- }
- func (b *bodyBuffer) String() string {
- str := b.Buffer.String()
- return strings.Replace(strings.Replace(str, "\n", "", -1), "\t", "", -1)
- }
- type reqBodyLogReader struct {
- io.ReadCloser
- buffer *bodyBuffer
- }
- func (r *reqBodyLogReader) Read(p []byte) (n int, err error) {
- b, err := ioutil.ReadAll(r.ReadCloser)
- if nil != err {
- return 0, err
- }
- oldReader := r.ReadCloser
- defer func(oldReader io.ReadCloser) {
- _ = oldReader.Close()
- }(oldReader)
- _, _ = r.buffer.Write(b)
- r.ReadCloser = ioutil.NopCloser(bytes.NewReader(b))
- return r.ReadCloser.Read(p)
- }
- func (r *reqBodyLogReader) Close() error {
- return r.ReadCloser.Close()
- }
- type respBodyLogWriter struct {
- gin.ResponseWriter
- buffer *bodyBuffer
- }
- func (w *respBodyLogWriter) Write(b []byte) (int, error) {
- _, _ = w.buffer.Write(b)
- return w.ResponseWriter.Write(b)
- }
- const HTTPRequestStartTime = "httpRequestStartTime"
- // 日志中间件
- func Logger(hostPrefix string, logger *logger.Logger, notLogged ...string) gin.HandlerFunc {
- var skip map[string]struct{}
- if length := len(notLogged); length > 0 {
- skip = make(map[string]struct{}, length)
- for _, path := range notLogged {
- skip[path] = struct{}{}
- }
- }
- return func(ctxt *gin.Context) {
- start := date.Now()
- ctxt.Set(HTTPRequestStartTime, start)
- reqReader := &reqBodyLogReader{buffer: &bodyBuffer{Buffer: *bytes.NewBufferString("")}, ReadCloser: ctxt.Request.Body}
- ctxt.Request.Body = reqReader
- respWriter := &respBodyLogWriter{buffer: &bodyBuffer{Buffer: *bytes.NewBufferString("")}, ResponseWriter: ctxt.Writer}
- ctxt.Writer = respWriter
- ctxt.Next()
- if ctxt.Writer.Status() < http.StatusBadRequest { // httpStatus大于等于400的不应在此记录,而应该panic抛给下面的Recovery方法处理
- path := ctxt.Request.URL.Path
- if _, ok := skip[path]; !ok {
- end := date.Now()
- latency := end.Sub(start)
- httpStatus := ctxt.Writer.Status()
- clientIP := ctxt.ClientIP()
- req, fields := splitUri(hostPrefix, ctxt)
- comment := ctxt.Errors.ByType(gin.ErrorTypePrivate).String()
- logHttpRequest := true
- if i, ok := ctxt.Get(IsNoLogHTTPRequest); ok {
- if isNoLogHttpRequest, ok := i.(bool); ok && isNoLogHttpRequest {
- logHttpRequest = false
- }
- }
- if logHttpRequest {
- logger = logger.WithField("requestBody", reqReader.buffer.String())
- }
- if i, ok := ctxt.Get(IsLogHTTPResponse); ok {
- if isLogHttpResponse, ok := i.(bool); ok && isLogHttpResponse {
- logger = logger.WithField("responseBody", respWriter.buffer.String())
- }
- }
- logger.
- WithCaller(7).
- WithField("tag", "API").
- WithField("lib", "gin").
- WithField("httpStatus", httpStatus).
- WithField("latency", fmt.Sprintf("%v", latency)).
- WithField("clientIP", clientIP).
- WithField("comment", comment).
- WithFields(fields).
- Info(req)
- }
- }
- }
- }
|