mirror of
https://github.com/gin-gonic/gin.git
synced 2025-04-06 03:57:46 +08:00
Otherwise, caller needs to invoke WriteHeaderNow himself after AbortWithStatus(), which is error-prone. Also modified ErrorLoggerT() such that it always writes log to response body. Otherwise calling AbortWithStatus() will fail to write body because c.Writer.Written() is set true by WriteHeaderNow().
124 lines
2.7 KiB
Go
124 lines
2.7 KiB
Go
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
|
|
// Use of this source code is governed by a MIT style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package gin
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
green = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
|
|
white = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
|
|
yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109})
|
|
red = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
|
|
blue = string([]byte{27, 91, 57, 55, 59, 52, 52, 109})
|
|
magenta = string([]byte{27, 91, 57, 55, 59, 52, 53, 109})
|
|
cyan = string([]byte{27, 91, 57, 55, 59, 52, 54, 109})
|
|
reset = string([]byte{27, 91, 48, 109})
|
|
)
|
|
|
|
func ErrorLogger() HandlerFunc {
|
|
return ErrorLoggerT(ErrorTypeAny)
|
|
}
|
|
|
|
func ErrorLoggerT(typ ErrorType) HandlerFunc {
|
|
return func(c *Context) {
|
|
c.Next()
|
|
errors := c.Errors.ByType(typ)
|
|
if len(errors) > 0 {
|
|
c.JSON(-1, errors)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Instances a Logger middleware that will write the logs to gin.DefaultWriter
|
|
// By default gin.DefaultWriter = os.Stdout
|
|
func Logger() HandlerFunc {
|
|
return LoggerWithWriter(DefaultWriter)
|
|
}
|
|
|
|
// Instance a Logger middleware with the specified writter buffer.
|
|
// Example: os.Stdout, a file opened in write mode, a socket...
|
|
func LoggerWithWriter(out io.Writer, notlogged ...string) 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(c *Context) {
|
|
// Start timer
|
|
start := time.Now()
|
|
path := c.Request.URL.Path
|
|
|
|
// Process request
|
|
c.Next()
|
|
|
|
// Log only when path is not being skipped
|
|
if _, ok := skip[path]; !ok {
|
|
// Stop timer
|
|
end := time.Now()
|
|
latency := end.Sub(start)
|
|
|
|
clientIP := c.ClientIP()
|
|
method := c.Request.Method
|
|
statusCode := c.Writer.Status()
|
|
statusColor := colorForStatus(statusCode)
|
|
methodColor := colorForMethod(method)
|
|
comment := c.Errors.ByType(ErrorTypePrivate).String()
|
|
|
|
fmt.Fprintf(out, "[GIN] %v |%s %3d %s| %13v | %s |%s %s %-7s %s\n%s",
|
|
end.Format("2006/01/02 - 15:04:05"),
|
|
statusColor, statusCode, reset,
|
|
latency,
|
|
clientIP,
|
|
methodColor, reset, method,
|
|
path,
|
|
comment,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func colorForStatus(code int) string {
|
|
switch {
|
|
case code >= 200 && code < 300:
|
|
return green
|
|
case code >= 300 && code < 400:
|
|
return white
|
|
case code >= 400 && code < 500:
|
|
return yellow
|
|
default:
|
|
return red
|
|
}
|
|
}
|
|
|
|
func colorForMethod(method string) string {
|
|
switch method {
|
|
case "GET":
|
|
return blue
|
|
case "POST":
|
|
return cyan
|
|
case "PUT":
|
|
return yellow
|
|
case "DELETE":
|
|
return red
|
|
case "PATCH":
|
|
return green
|
|
case "HEAD":
|
|
return magenta
|
|
case "OPTIONS":
|
|
return white
|
|
default:
|
|
return reset
|
|
}
|
|
}
|