初始化提交
This commit is contained in:
commit
887c1f449e
963 files changed
+166869
No files matched your search
@@ -0,0 +1,136 @@
|
||||
// Package logger 提供结构化日志配置。
|
||||
package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Config 日志配置。
|
||||
type Config struct {
|
||||
Level slog.Level
|
||||
AddSource bool
|
||||
JSON bool // true = JSONHandler,false = 彩色 TextHandler
|
||||
}
|
||||
|
||||
// New 创建配置好的 Logger。
|
||||
// 开发环境(JSON=false)输出彩色终端文本,生产环境输出 JSON 供采集。
|
||||
func New(cfg Config) *slog.Logger {
|
||||
var h slog.Handler
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: cfg.Level,
|
||||
AddSource: cfg.AddSource,
|
||||
}
|
||||
if cfg.JSON {
|
||||
h = slog.NewJSONHandler(os.Stdout, opts)
|
||||
} else {
|
||||
h = newColorHandler(os.Stdout, opts)
|
||||
}
|
||||
return slog.New(h)
|
||||
}
|
||||
|
||||
// ANSI 颜色代码
|
||||
const (
|
||||
colorReset = "\033[0m"
|
||||
colorRed = "\033[31m"
|
||||
colorGreen = "\033[32m"
|
||||
colorYellow = "\033[33m"
|
||||
colorBlue = "\033[34m"
|
||||
colorPurple = "\033[35m"
|
||||
colorCyan = "\033[36m"
|
||||
colorGray = "\033[37m"
|
||||
)
|
||||
|
||||
// levelColor 日志级别 → ANSI 颜色映射
|
||||
var levelColor = map[slog.Level]string{
|
||||
slog.LevelDebug: colorGray,
|
||||
slog.LevelInfo: colorGreen,
|
||||
slog.LevelWarn: colorYellow,
|
||||
slog.LevelError: colorRed,
|
||||
}
|
||||
|
||||
// levelLabel 日志级别 → 短标签映射
|
||||
var levelLabel = map[slog.Level]string{
|
||||
slog.LevelDebug: "DEBUG",
|
||||
slog.LevelInfo: "INFO",
|
||||
slog.LevelWarn: "WARN",
|
||||
slog.LevelError: "ERROR",
|
||||
}
|
||||
|
||||
// colorHandler 带颜色的 slog.Handler 包装。
|
||||
type colorHandler struct {
|
||||
inner slog.Handler
|
||||
mu sync.Mutex
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
func newColorHandler(w io.Writer, opts *slog.HandlerOptions) *colorHandler {
|
||||
return &colorHandler{
|
||||
inner: slog.NewTextHandler(w, opts),
|
||||
writer: w,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *colorHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
||||
return h.inner.Enabled(ctx, level)
|
||||
}
|
||||
|
||||
func (h *colorHandler) Handle(ctx context.Context, r slog.Record) error {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
// 时间(使用 -07:00 让 Go 自动填充时区偏移)
|
||||
timeStr := r.Time.Format("2006-01-02T15:04:05.000-07:00")
|
||||
|
||||
// Level 带颜色
|
||||
lvl := r.Level
|
||||
color := levelColor[lvl]
|
||||
label := levelLabel[lvl]
|
||||
|
||||
// 消息
|
||||
msg := r.Message
|
||||
|
||||
// 组装属性
|
||||
var attrs []string
|
||||
r.Attrs(func(a slog.Attr) bool {
|
||||
attrs = append(attrs, fmt.Sprintf("%s=%v", a.Key, a.Value.Any()))
|
||||
return true
|
||||
})
|
||||
|
||||
// 输出格式:[时间] Level颜色(LEVEL) 消息 attr1=val1 attr2=val2
|
||||
var buf strings.Builder
|
||||
buf.WriteString(timeStr)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(color)
|
||||
buf.WriteString(fmt.Sprintf("%-5s", label))
|
||||
buf.WriteString(colorReset)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(msg)
|
||||
for _, a := range attrs {
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(a)
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
|
||||
_, err := fmt.Fprint(h.writer, buf.String())
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *colorHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
return &colorHandler{
|
||||
inner: h.inner.WithAttrs(attrs),
|
||||
writer: h.writer,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *colorHandler) WithGroup(name string) slog.Handler {
|
||||
return &colorHandler{
|
||||
inner: h.inner.WithGroup(name),
|
||||
writer: h.writer,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user