mirror of https://github.com/cloudreve/Cloudreve
				
				
				
			
		
			
				
	
	
		
			206 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
package logging
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
	"github.com/fatih/color"
 | 
						|
	"github.com/gin-gonic/gin"
 | 
						|
	"github.com/gofrs/uuid"
 | 
						|
	"runtime"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// Logger interface for logging messages.
 | 
						|
type Logger interface {
 | 
						|
	Panic(format string, v ...any)
 | 
						|
	Error(format string, v ...any)
 | 
						|
	Warning(format string, v ...any)
 | 
						|
	Info(format string, v ...any)
 | 
						|
	Debug(format string, v ...any)
 | 
						|
	// Copy a new logger with a prefix.
 | 
						|
	CopyWithPrefix(prefix string) Logger
 | 
						|
 | 
						|
	// SupportColor returns if current logger support outputting colors.
 | 
						|
	SupportColor() bool
 | 
						|
}
 | 
						|
 | 
						|
// LoggerCtx defines keys for logger with correlation ID
 | 
						|
type LoggerCtx struct{}
 | 
						|
 | 
						|
// CorrelationIDCtx defines keys for correlation ID
 | 
						|
type CorrelationIDCtx struct{}
 | 
						|
type LogLevel string
 | 
						|
 | 
						|
const (
 | 
						|
	// LevelError 错误
 | 
						|
	LevelError LogLevel = "error"
 | 
						|
	// LevelWarning 警告
 | 
						|
	LevelWarning LogLevel = "warning"
 | 
						|
	// LevelInformational 提示
 | 
						|
	LevelInformational LogLevel = "info"
 | 
						|
	// LevelDebug 除错
 | 
						|
	LevelDebug LogLevel = "debug"
 | 
						|
)
 | 
						|
 | 
						|
// NewConsoleLogger initializes a new logging that prints logs to Stdout.
 | 
						|
func NewConsoleLogger(level LogLevel) Logger {
 | 
						|
	logFunc := func(level string) loggingFunc {
 | 
						|
		return func(logger *consoleLogger, s string, a ...any) {
 | 
						|
			msg := fmt.Sprintf(s, a...)
 | 
						|
			logger.println(level, msg)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	logger := &consoleLogger{
 | 
						|
		warning: logFunc("Warn"),
 | 
						|
		panic: func(logger *consoleLogger, s string, a ...any) {
 | 
						|
			msg := fmt.Sprintf(s, a...)
 | 
						|
			logger.println("Panic", msg)
 | 
						|
			panic(msg)
 | 
						|
		},
 | 
						|
		error: logFunc("Error"),
 | 
						|
		info:  logFunc("Info"),
 | 
						|
		debug: logFunc("Debug"),
 | 
						|
	}
 | 
						|
 | 
						|
	switch level {
 | 
						|
	case LevelError:
 | 
						|
		logger.warning = noopLoggingFunc
 | 
						|
		logger.info = noopLoggingFunc
 | 
						|
		logger.debug = noopLoggingFunc
 | 
						|
	case LevelWarning:
 | 
						|
		logger.info = noopLoggingFunc
 | 
						|
		logger.debug = noopLoggingFunc
 | 
						|
	case LevelInformational:
 | 
						|
		logger.debug = noopLoggingFunc
 | 
						|
	case LevelDebug:
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	return logger
 | 
						|
}
 | 
						|
 | 
						|
// FromContext retrieves a logger from context.
 | 
						|
func FromContext(ctx context.Context) Logger {
 | 
						|
	v, ok := ctx.Value(LoggerCtx{}).(Logger)
 | 
						|
	if !ok {
 | 
						|
		v = NewConsoleLogger(LevelDebug)
 | 
						|
	}
 | 
						|
	return v
 | 
						|
}
 | 
						|
 | 
						|
// CorrelationID retrieves a correlation ID from context.
 | 
						|
func CorrelationID(ctx context.Context) uuid.UUID {
 | 
						|
	v, ok := ctx.Value(CorrelationIDCtx{}).(uuid.UUID)
 | 
						|
	if !ok {
 | 
						|
		v = uuid.Nil
 | 
						|
	}
 | 
						|
	return v
 | 
						|
}
 | 
						|
 | 
						|
type consoleLogger struct {
 | 
						|
	warning loggingFunc
 | 
						|
	panic   loggingFunc
 | 
						|
	error   loggingFunc
 | 
						|
	info    loggingFunc
 | 
						|
	debug   loggingFunc
 | 
						|
	prefix  string
 | 
						|
}
 | 
						|
 | 
						|
func (ll *consoleLogger) Panic(format string, v ...any) {
 | 
						|
	ll.panic(ll, format, v...)
 | 
						|
}
 | 
						|
 | 
						|
func (ll *consoleLogger) Error(format string, v ...any) {
 | 
						|
	ll.error(ll, format, v...)
 | 
						|
}
 | 
						|
 | 
						|
func (ll *consoleLogger) Warning(format string, v ...any) {
 | 
						|
	ll.warning(ll, format, v...)
 | 
						|
}
 | 
						|
 | 
						|
func (ll *consoleLogger) Info(format string, v ...any) {
 | 
						|
	ll.info(ll, format, v...)
 | 
						|
}
 | 
						|
 | 
						|
func (ll *consoleLogger) Debug(format string, v ...any) {
 | 
						|
	ll.debug(ll, format, v...)
 | 
						|
}
 | 
						|
 | 
						|
// println 打印
 | 
						|
func (ll *consoleLogger) println(level string, msg string) {
 | 
						|
	c := color.New()
 | 
						|
	_, filename, line, _ := runtime.Caller(3)
 | 
						|
 | 
						|
	_, _ = c.Printf(
 | 
						|
		"%s\t %s [%s:%d]%s %s\n",
 | 
						|
		colors[level]("["+level+"]"),
 | 
						|
		time.Now().Format("2006-01-02 15:04:05"),
 | 
						|
		filename,
 | 
						|
		line,
 | 
						|
		ll.prefix,
 | 
						|
		msg,
 | 
						|
	)
 | 
						|
}
 | 
						|
 | 
						|
func (ll *consoleLogger) CopyWithPrefix(prefix string) Logger {
 | 
						|
	return &consoleLogger{
 | 
						|
		warning: ll.warning,
 | 
						|
		panic:   ll.panic,
 | 
						|
		error:   ll.error,
 | 
						|
		info:    ll.info,
 | 
						|
		debug:   ll.debug,
 | 
						|
		prefix:  ll.prefix + " " + prefix,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (ll *consoleLogger) SupportColor() bool {
 | 
						|
	return !color.NoColor
 | 
						|
}
 | 
						|
 | 
						|
type loggingFunc func(*consoleLogger, string, ...any)
 | 
						|
 | 
						|
func noopLoggingFunc(*consoleLogger, string, ...any) {}
 | 
						|
 | 
						|
var colors = map[string]func(a ...interface{}) string{
 | 
						|
	"Warn":  color.New(color.FgYellow).Add(color.Bold).SprintFunc(),
 | 
						|
	"Panic": color.New(color.BgRed).Add(color.Bold).SprintFunc(),
 | 
						|
	"Error": color.New(color.FgRed).Add(color.Bold).SprintFunc(),
 | 
						|
	"Info":  color.New(color.FgCyan).Add(color.Bold).SprintFunc(),
 | 
						|
	"Debug": color.New(color.FgWhite).Add(color.Bold).SprintFunc(),
 | 
						|
}
 | 
						|
 | 
						|
// Request helper fund to log request.
 | 
						|
func Request(l Logger, incoming bool, code int, method, clientIP, path, err string, start time.Time) {
 | 
						|
	param := gin.LogFormatterParams{
 | 
						|
		StatusCode: code,
 | 
						|
		Method:     method,
 | 
						|
	}
 | 
						|
	param.StatusCode = code
 | 
						|
 | 
						|
	var statusColor, methodColor, resetColor string
 | 
						|
	if l.SupportColor() {
 | 
						|
		statusColor = param.StatusCodeColor()
 | 
						|
		methodColor = param.MethodColor()
 | 
						|
		resetColor = param.ResetColor()
 | 
						|
	}
 | 
						|
 | 
						|
	category := "Incoming"
 | 
						|
	if !incoming {
 | 
						|
		category = "Outgoing"
 | 
						|
	}
 | 
						|
 | 
						|
	l.Info(
 | 
						|
		"[%s] %s %3d %s| %13v | %15s |%s %-7s %s %#v",
 | 
						|
		category,
 | 
						|
		statusColor, param.StatusCode, resetColor,
 | 
						|
		time.Now().Sub(start),
 | 
						|
		clientIP,
 | 
						|
		methodColor, method, resetColor,
 | 
						|
		path,
 | 
						|
	)
 | 
						|
	if err != "" {
 | 
						|
		l.Error("%s", err)
 | 
						|
	}
 | 
						|
}
 |