初始化提交

This commit is contained in:
chenxin committed 2026-08-21 16:00:13 +08:00
commit 887c1f449e
963 files changed
+166869

No files matched your search

+136
View File
@@ -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,
}
}