github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/log/access_log_middleware.go (about)

     1  package log
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"io/ioutil"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/weedge/lib/log/tapper"
    11  	"github.com/weedge/lib/net"
    12  	hack "github.com/weedge/lib/strings"
    13  
    14  	"github.com/gin-gonic/gin"
    15  	jsoniter "github.com/json-iterator/go"
    16  	"go.uber.org/zap"
    17  	"google.golang.org/grpc"
    18  )
    19  
    20  const (
    21  	LOGID     = "logId"
    22  	REFERER   = "referer"
    23  	COOKIE    = "cookie"
    24  	CLIENT_IP = "client_ip"
    25  	LOCAL_IP  = "local_ip"
    26  	MODULE    = "module"
    27  	UA        = "ua"
    28  	HOST      = "host"
    29  	URI       = "uri"
    30  	TRACE     = "trace"
    31  	NOTICES   = "notice"
    32  	MONITOR   = "monitor"
    33  	RESPONSE  = "response"
    34  	REQUEST   = "request"
    35  	CODE      = "code"
    36  	COST      = "cost"
    37  	METHOD    = "method"
    38  	ERR       = "err"
    39  )
    40  
    41  const (
    42  	REQUEST_PARAM_CTX = "REQUEST_PARAM_CTX"
    43  )
    44  
    45  var (
    46  	LOCALIP        = net.GetLocalIPv4()
    47  	MaxRespLen     = 0
    48  	MaxReqParamLen = 4096
    49  	IgnoreReqUris  = make([]string, 0)
    50  )
    51  
    52  type bodyLogWriter struct {
    53  	gin.ResponseWriter
    54  	body *bytes.Buffer
    55  }
    56  
    57  func (w bodyLogWriter) WriteString(s string) (int, error) {
    58  	if w.body != nil {
    59  		w.body.WriteString(s)
    60  	}
    61  	return w.ResponseWriter.WriteString(s)
    62  }
    63  
    64  func (w bodyLogWriter) Write(b []byte) (int, error) {
    65  	if w.body != nil {
    66  		w.body.Write(b)
    67  	}
    68  	return w.ResponseWriter.Write(b)
    69  }
    70  func SetLogPrintMaxRespLen(maxRespLen int) {
    71  	MaxRespLen = maxRespLen
    72  }
    73  func SetLogPrintMaxReqParamLen(maxReqParamLen int) {
    74  	MaxReqParamLen = maxReqParamLen
    75  }
    76  func SetLogRequestParam(ctx context.Context, body interface{}) {
    77  	data := ""
    78  	switch body := body.(type) {
    79  	case string:
    80  		data = body
    81  	default:
    82  		if b, e := jsoniter.Marshal(body); e == nil {
    83  			data = hack.String(b)
    84  		}
    85  	}
    86  
    87  	switch c := ctx.(type) {
    88  	case *gin.Context:
    89  		c.Set(REQUEST_PARAM_CTX, data)
    90  	case nil:
    91  	default:
    92  	}
    93  }
    94  
    95  // add ignore request uri
    96  func AddIgnoreReqUri(uri ...string) {
    97  	IgnoreReqUris = append(IgnoreReqUris, uri...)
    98  }
    99  
   100  // gin access log
   101  func GinLogger() gin.HandlerFunc {
   102  	// 本地IP
   103  	// 当前模块名
   104  	return func(c *gin.Context) {
   105  		// 开始时间
   106  		start := time.Now()
   107  		// 请求url
   108  		path := c.Request.URL.Path
   109  		raw := c.Request.URL.RawQuery
   110  		if raw != "" {
   111  			path = path + "?" + raw
   112  		}
   113  		// 请求报文
   114  		body, _ := ioutil.ReadAll(c.Request.Body)
   115  		c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
   116  
   117  		// 获取当前context trace log
   118  		traceLog, _ := tapper.GetTraceLogFromGinContext(c)
   119  
   120  		blw := new(bodyLogWriter)
   121  		if MaxRespLen <= 0 {
   122  			blw = &bodyLogWriter{body: nil, ResponseWriter: c.Writer}
   123  		} else {
   124  			blw = &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
   125  		}
   126  		c.Writer = blw
   127  
   128  		// 处理请求
   129  		c.Next()
   130  
   131  		// 获取响应报文
   132  		response := ""
   133  		if blw.body != nil {
   134  			response = blw.body.String()
   135  		}
   136  
   137  		bodyStr := ""
   138  		flag := false
   139  		if v, ok := c.Get(REQUEST_PARAM_CTX); ok {
   140  			switch v := v.(type) {
   141  			case string:
   142  				bodyStr = v
   143  				flag = true
   144  			}
   145  		}
   146  		if !flag {
   147  			for _, val := range IgnoreReqUris {
   148  				if strings.Contains(path, val) {
   149  					bodyStr = ""
   150  					flag = true
   151  					break
   152  				}
   153  			}
   154  		}
   155  		if !flag {
   156  			bodyStr = string(body)
   157  		}
   158  
   159  		refer := c.Request.Referer()
   160  		if len(refer) <= 0 {
   161  			refer = traceLog.Refer
   162  		}
   163  
   164  		// 结束时间
   165  		end := time.Now()
   166  		// 执行时间 单位:微秒
   167  		latency := end.Sub(start).Nanoseconds() / 1e3
   168  
   169  		_, trace := tapper.GetTraceFromContext(c)
   170  		_, notice := tapper.GetNoticeFromContext(c)
   171  		_, monitor := tapper.GetMonitorFromContext(c)
   172  
   173  		fields := []zap.Field{
   174  			zap.String(LOGID, traceLog.LogId),
   175  			zap.String(URI, path),
   176  			zap.String(REFERER, refer),
   177  			zap.Any(COOKIE, c.Request.Cookies()),
   178  			zap.String(CLIENT_IP, c.ClientIP()),
   179  			zap.String(LOCAL_IP, LOCALIP),
   180  			zap.String(MODULE, traceLog.Caller),
   181  			zap.String("request_param", _trancate(bodyStr, MaxReqParamLen)),
   182  			zap.String(UA, c.Request.UserAgent()),
   183  			zap.String(HOST, c.Request.Host),
   184  			zap.String(TRACE, trace.Marshal()),
   185  			zap.String(NOTICES, notice.Marshal()),
   186  			zap.String(MONITOR, monitor.Marshal()),
   187  			zap.Int(CODE, c.Writer.Status()),
   188  			zap.String(RESPONSE, _trancate(response, MaxRespLen)),
   189  			zap.Int64(COST, latency),
   190  		}
   191  
   192  		AccessInfo("", fields...)
   193  	}
   194  }
   195  
   196  // grpc access log
   197  func GrpcLogger() grpc.UnaryServerInterceptor {
   198  	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
   199  		// 开始时间
   200  		start := time.Now()
   201  		var traceLog *tapper.TraceLog
   202  		// 添加context信息
   203  		ctx, traceLog = tapper.GetTraceLogFromContext(ctx)
   204  		resp, err := handler(ctx, req)
   205  		// 结束时间
   206  		end := time.Now()
   207  		// 执行时间 单位:微秒
   208  		latency := end.Sub(start).Nanoseconds() / 1e3
   209  		AccessInfo("",
   210  			zap.Any(LOGID, traceLog.LogId),
   211  			zap.String(METHOD, info.FullMethod),
   212  			zap.Any(REQUEST, req),
   213  			zap.String(NOTICES, ""),
   214  			zap.Any(RESPONSE, resp),
   215  			zap.Any(ERR, err),
   216  			zap.Int64(COST, latency))
   217  		return resp, err
   218  	}
   219  }
   220  
   221  func _trancate(s string, l int) string {
   222  	if len(s) > l {
   223  		return s[:l]
   224  	}
   225  	return s
   226  }