You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-library/utils/golog/slog.go

214 lines
5.9 KiB

package golog
import (
"context"
"fmt"
"github.com/dtapps/go-library/utils/gotime"
"github.com/dtapps/go-library/utils/gotrace_id"
"gopkg.in/natefinch/lumberjack.v2"
"io"
"log/slog"
"os"
)
type SLogFun func() *SLog
type SLogConfig struct {
LogPath string // 日志文件路径
LogName string // 日志文件名
MaxSize int // 单位为MB,默认为512MB
MaxBackups int // 保留旧文件的最大个数
MaxAge int // 文件最多保存多少天 0=不删除
LocalTime bool // 采用本地时间
Compress bool // 是否压缩日志
JsonFormat bool // 是否输出为json格式
ShowLine bool // 显示代码行
LogSaveFile bool // 是否保存到文件
LogInConsole bool // 是否同时输出到控制台
}
type SLog struct {
config *SLogConfig
jsonHandler *slog.JSONHandler
textHandler *slog.TextHandler
logger *slog.Logger
}
func NewSlog(ctx context.Context, config *SLogConfig) *SLog {
sl := &SLog{config: config}
opts := slog.HandlerOptions{
AddSource: sl.config.ShowLine,
Level: slog.LevelDebug,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
a.Value = slog.StringValue(a.Value.Time().Format(gotime.DateTimeFormat))
//return slog.Attr{}
}
return a
},
}
// 是否保存到文件
if sl.config.LogSaveFile {
lumberjackLogger := lumberjack.Logger{
Filename: sl.config.LogPath + sl.config.LogName, // ⽇志⽂件路径
MaxSize: sl.config.MaxSize, // 单位为MB,默认为512MB
MaxAge: sl.config.MaxAge, // 文件最多保存多少天
MaxBackups: sl.config.MaxBackups, // 保留旧文件的最大个数
LocalTime: sl.config.LocalTime, // 采用本地时间
Compress: sl.config.Compress, // 是否压缩日志
}
// 是否json格式输出
if sl.config.JsonFormat {
if sl.config.LogInConsole {
sl.jsonHandler = slog.NewJSONHandler(io.MultiWriter(os.Stdout, &lumberjackLogger), &opts)
} else {
sl.jsonHandler = slog.NewJSONHandler(&lumberjackLogger, &opts)
}
sl.logger = slog.New(sl.jsonHandler)
} else {
if sl.config.LogInConsole {
sl.textHandler = slog.NewTextHandler(io.MultiWriter(os.Stdout, &lumberjackLogger), &opts)
} else {
sl.textHandler = slog.NewTextHandler(&lumberjackLogger, &opts)
}
sl.logger = slog.New(sl.textHandler)
}
} else {
// 是否json格式输出
if sl.config.JsonFormat {
sl.jsonHandler = slog.NewJSONHandler(os.Stdout, &opts)
sl.logger = slog.New(sl.jsonHandler)
} else {
sl.textHandler = slog.NewTextHandler(os.Stdout, &opts)
sl.logger = slog.New(sl.textHandler)
}
}
return sl
}
// WithLogger 跟踪编号
func (sl *SLog) WithLogger() *LoggerOperation {
if sl.config.JsonFormat {
logger := slog.New(sl.jsonHandler)
return &LoggerOperation{
logger: logger,
}
} else {
logger := slog.New(sl.textHandler)
return &LoggerOperation{
logger: logger,
}
}
}
// WithTraceId 跟踪编号
func (sl *SLog) WithTraceId(ctx context.Context) *LoggerOperation {
if sl.config.JsonFormat {
jsonHandler := sl.jsonHandler.WithAttrs([]slog.Attr{
slog.String("trace_id", gotrace_id.GetTraceIdContext(ctx)),
})
logger := slog.New(jsonHandler)
return &LoggerOperation{
logger: logger,
}
} else {
textHandler := sl.textHandler.WithAttrs([]slog.Attr{
slog.String("trace_id", gotrace_id.GetTraceIdContext(ctx)),
})
logger := slog.New(textHandler)
return &LoggerOperation{
logger: logger,
}
}
}
// WithTraceIdStr 跟踪编号
func (sl *SLog) WithTraceIdStr(traceId string) *LoggerOperation {
if sl.config.JsonFormat {
jsonHandler := sl.jsonHandler.WithAttrs([]slog.Attr{
slog.String("trace_id", traceId),
})
logger := slog.New(jsonHandler)
return &LoggerOperation{
logger: logger,
}
} else {
textHandler := sl.textHandler.WithAttrs([]slog.Attr{
slog.String("trace_id", traceId),
})
logger := slog.New(textHandler)
return &LoggerOperation{
logger: logger,
}
}
}
type LoggerOperation struct {
logger *slog.Logger
}
// Debug logs at LevelDebug.
func (l *LoggerOperation) Debug(msg any) {
l.logger.Debug(fmt.Sprintf("%v", msg))
}
// Debugf formats the message according to the format specifier
func (l *LoggerOperation) Debugf(template string, args ...any) {
l.logger.Debug(fmt.Sprintf(template, args...))
}
// DebugContext logs at LevelDebug with the given context.
func (l *LoggerOperation) DebugContext(ctx context.Context, msg string, args ...any) {
l.logger.DebugContext(ctx, msg, args...)
}
// Info logs at LevelInfo.
func (l *LoggerOperation) Info(msg any) {
l.logger.Info(fmt.Sprintf("%v", msg))
}
// Infof formats the message according to the format specifier
func (l *LoggerOperation) Infof(template string, args ...any) {
l.logger.Info(fmt.Sprintf(template, args...))
}
// InfoContext logs at LevelInfo with the given context.
func (l *LoggerOperation) InfoContext(ctx context.Context, msg string, args ...any) {
l.logger.InfoContext(ctx, msg, args...)
}
// Warn logs at LevelWarn.
func (l *LoggerOperation) Warn(msg any) {
l.logger.Warn(fmt.Sprintf("%v", msg))
}
// Warnf formats the message according to the format specifier
func (l *LoggerOperation) Warnf(template string, args ...any) {
l.logger.Warn(fmt.Sprintf(template, args...))
}
func (l *LoggerOperation) WarnContext(ctx context.Context, msg string, args ...any) {
l.logger.WarnContext(ctx, msg, args...)
}
// Error logs at LevelError.
func (l *LoggerOperation) Error(msg any) {
l.logger.Error(fmt.Sprintf("%v", msg))
}
// Errorf formats the message according to the format specifier
func (l *LoggerOperation) Errorf(template string, args ...any) {
l.logger.Error(fmt.Sprintf(template, args...))
}
// ErrorContext logs at LevelError with the given context.
func (l *LoggerOperation) ErrorContext(ctx context.Context, msg string, args ...any) {
l.logger.ErrorContext(ctx, msg, args...)
}