-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmain.go
126 lines (103 loc) · 3.12 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"context"
"log/slog"
"os"
"runtime"
"time"
)
func main() {
l := New(LevelDebug)
l.Debug("custom debug message", "hello", "world")
l.Trace("custom trace message", "hello", "world")
l.Info("custom info message", "hello", "world")
l.SetLevel(LevelInfo)
l.Debug("custom debug message", "hello", "world")
l.Trace("custom trace message", "hello", "world")
l.Info("custom info message", "hello", "world")
}
type Level = slog.Level
const (
LevelDebug = slog.LevelDebug
LevelTrace = slog.Level(-2) // 自定义日志级别
LevelInfo = slog.LevelInfo
LevelWarn = slog.LevelWarn
LevelError = slog.LevelError
)
type Logger struct {
l *slog.Logger
lvl *slog.LevelVar // 用来动态调整日志级别
}
func New(level slog.Level) *Logger {
var lvl slog.LevelVar
lvl.Set(level)
h := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
// Level: level, // 静态设置日志级别
Level: &lvl, // 支持动态设置日志级别
// 修改日志中的 Attr 键值对(即日志记录中附加的 key/value)
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.LevelKey {
level := a.Value.Any().(slog.Level)
levelLabel := level.String()
switch level {
case LevelTrace:
// NOTE: 如果不设置,默认日志级别打印为 "level":"DEBUG+2"
levelLabel = "TRACE"
}
a.Value = slog.StringValue(levelLabel)
}
// NOTE: 可以在这里修改时间输出格式
// if a.Key == slog.TimeKey {
// if t, ok := a.Value.Any().(time.Time); ok {
// a.Value = slog.StringValue(t.Format(time.DateTime))
// }
// }
return a
},
}))
return &Logger{l: h, lvl: &lvl}
}
// SetLevel 动态调整日志级别
func (l *Logger) SetLevel(level Level) {
l.lvl.Set(level)
}
func (l *Logger) Debug(msg string, args ...any) {
l.l.Debug(msg, args...)
}
func (l *Logger) Info(msg string, args ...any) {
l.Log(context.Background(), LevelInfo, msg, args...)
}
// Trace 自定义的日志级别
func (l *Logger) Trace(msg string, args ...any) {
l.Log(context.Background(), LevelTrace, msg, args...)
}
func (l *Logger) Warn(msg string, args ...any) {
l.Log(context.Background(), LevelWarn, msg, args...)
}
func (l *Logger) Error(msg string, args ...any) {
l.Log(context.Background(), LevelError, msg, args...)
}
func (l *Logger) Log(ctx context.Context, level slog.Level, msg string, args ...any) {
l.log(ctx, level, msg, args...)
}
// log is the low-level logging method for methods that take ...any.
// It must always be called directly by an exported logging method
// or function, because it uses a fixed call depth to obtain the pc.
func (l *Logger) log(ctx context.Context, level slog.Level, msg string, args ...any) {
if !l.l.Enabled(ctx, level) {
return
}
var pc uintptr
var pcs [1]uintptr
// skip [runtime.Callers, this function, this function's caller]
// NOTE: 这里修改 skip 为 4,*slog.Logger.log 源码中 skip 为 3
runtime.Callers(4, pcs[:])
pc = pcs[0]
r := slog.NewRecord(time.Now(), level, msg, pc)
r.Add(args...)
if ctx == nil {
ctx = context.Background()
}
_ = l.l.Handler().Handle(ctx, r)
}