github.com/segakazzz/buffalo@v0.16.22-0.20210119082501-1f52048d3feb/request_logger.go (about) 1 package buffalo 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "net/http" 7 "time" 8 9 humanize "github.com/dustin/go-humanize" 10 "github.com/segakazzz/buffalo/internal/httpx" 11 ) 12 13 // RequestLogger can be be overridden to a user specified 14 // function that can be used to log the request. 15 var RequestLogger = RequestLoggerFunc 16 17 func randString(i int) (string, error) { 18 if i == 0 { 19 i = 64 20 } 21 b := make([]byte, i) 22 _, err := rand.Read(b) 23 return hex.EncodeToString(b), err 24 } 25 26 // RequestLoggerFunc is the default implementation of the RequestLogger. 27 // By default it will log a uniq "request_id", the HTTP Method of the request, 28 // the path that was requested, the duration (time) it took to process the 29 // request, the size of the response (and the "human" size), and the status 30 // code of the response. 31 func RequestLoggerFunc(h Handler) Handler { 32 return func(c Context) error { 33 rs, err := randString(10) 34 if err != nil { 35 return err 36 } 37 var irid interface{} 38 if irid = c.Session().Get("requestor_id"); irid == nil { 39 rs, err := randString(10) 40 if err != nil { 41 return err 42 } 43 irid = rs 44 c.Session().Set("requestor_id", irid) 45 c.Session().Save() 46 } 47 48 rid := irid.(string) + "-" + rs 49 c.Set("request_id", rid) 50 c.LogField("request_id", rid) 51 52 start := time.Now() 53 defer func() { 54 ws, ok := c.Response().(*Response) 55 if !ok { 56 ws = &Response{ResponseWriter: c.Response()} 57 ws.Status = http.StatusOK 58 } 59 req := c.Request() 60 ct := httpx.ContentType(req) 61 if ct != "" { 62 c.LogField("content_type", ct) 63 } 64 c.LogFields(map[string]interface{}{ 65 "method": req.Method, 66 "path": req.URL.String(), 67 "duration": time.Since(start), 68 "size": ws.Size, 69 "human_size": humanize.Bytes(uint64(ws.Size)), 70 "status": ws.Status, 71 }) 72 c.Logger().Info(req.URL.String()) 73 }() 74 return h(c) 75 } 76 }