logrus日志配置
代码
package log
import (
"bytes"
"net/http"
"os"
"runtime"
"strconv"
"strings"
"time"
"raysync-ftp/common"
"raysync-ftp/config"
"github.com/gin-gonic/gin"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/sirupsen/logrus"
)
const (
green = "\033[97;42m"
white = "\033[90;47m"
yellow = "\033[90;43m"
red = "\033[97;41m"
blue = "\033[97;44m"
magenta = "\033[97;45m"
cyan = "\033[97;46m"
reset = "\033[0m"
)
func getLogLevelWithConsoleColor(level logrus.Level, writer *bytes.Buffer) {
switch level {
case logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel:
writer.WriteString("\033[91m")
case logrus.WarnLevel:
writer.WriteString("\033[93m")
case logrus.InfoLevel:
writer.WriteString("\033[92m")
case logrus.DebugLevel:
writer.WriteString("\033[96m")
case logrus.TraceLevel:
writer.WriteString("\033[96m")
}
writer.WriteString(strings.ToUpper(level.String()))
writer.WriteString("\033[0m")
}
type Formatter struct {
TimestampFormat string
ForceColor bool
}
func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) {
buffer := entry.Buffer
if buffer == nil {
buffer = &bytes.Buffer{}
}
buffer.WriteString("[")
buffer.WriteString(entry.Time.Format(f.TimestampFormat))
buffer.WriteString("] [")
if f.ForceColor {
getLogLevelWithConsoleColor(entry.Level, buffer)
} else {
buffer.WriteString(strings.ToUpper(entry.Level.String()))
}
buffer.WriteString("] ")
if entry.Caller != nil {
idx := strings.LastIndexByte(entry.Caller.File, '/')
idx = strings.LastIndexByte(entry.Caller.File[:idx], '/')
buffer.WriteString("[")
buffer.WriteString(entry.Caller.File[idx+1:])
buffer.WriteByte(':')
buffer.WriteString(strconv.Itoa(entry.Caller.Line))
buffer.WriteString("] ")
}
buffer.WriteString(entry.Message)
buffer.WriteByte('\n')
return buffer.Bytes(), nil
}
func Init(dir string) {
if common.Mode == "release" && dir != "" {
logs, _ := rotatelogs.New(dir+"/raysync-ftp_%Y-%m-%d.log",
rotatelogs.WithMaxAge(30*24*time.Hour),
rotatelogs.WithLinkName(dir+"/raysync-ftp.log"),
)
logrus.SetOutput(logs)
} else {
logrus.SetOutput(os.Stdout)
}
logrus.SetFormatter(&Formatter{
TimestampFormat: "2006-01-02 15:04:05.000 UTC-07:00",
ForceColor: runtime.GOOS != "windows",
})
if common.Mode != "release" {
logrus.SetLevel(logrus.DebugLevel)
} else {
l, err := logrus.ParseLevel(config.GetLogLevel())
if err != nil {
logrus.SetLevel(l)
}
}
logrus.SetReportCaller(true)
logrus.Infof(`build information: build time %v, go version %v, platform %v/%v`, common.BuildDate, runtime.Version(), runtime.GOOS, runtime.GOARCH)
}
func StatusCodeColor(code int) string {
switch {
case code >= http.StatusOK && code < http.StatusMultipleChoices:
return green
case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
return white
case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
return yellow
default:
return red
}
}
func MethodColor(method string) string {
switch method {
case http.MethodGet:
return blue
case http.MethodPost:
return cyan
case http.MethodPut:
return yellow
case http.MethodDelete:
return red
case http.MethodPatch:
return green
case http.MethodHead:
return magenta
case http.MethodOptions:
return white
default:
return reset
}
}
func GinLogrus() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
c.Next()
timeStamp := time.Now()
latency := timeStamp.Sub(start)
clientIP := c.ClientIP()
method := c.Request.Method
statusCode := c.Writer.Status()
errorMessage := c.Errors.ByType(gin.ErrorTypePrivate).String()
if raw != "" {
path = path + "?" + raw
}
var statusColor, methodColor, resetColor string
if runtime.GOOS != "windows" {
statusColor = StatusCodeColor(statusCode)
methodColor = MethodColor(method)
resetColor = reset
}
logrus.Infof("[%s] [%s %s %s] [%s] [%s %d %s] | %v | %s",
clientIP,
methodColor, method, resetColor,
path,
statusColor, statusCode, resetColor,
latency,
errorMessage,
)
}
}
输出效果