Files
cms-server/logger/slog.go
2026-01-21 19:19:17 +08:00

98 lines
2.2 KiB
Go

package logger
import (
"context"
"io"
"log/slog"
"os"
"strings"
"github.com/spf13/viper"
"go.opentelemetry.io/contrib/bridges/otelslog"
"go.opentelemetry.io/otel/trace"
)
type multiHandler struct {
handlers []slog.Handler
}
func (m *multiHandler) Enabled(ctx context.Context, l slog.Level) bool {
for _, h := range m.handlers {
if h.Enabled(ctx, l) {
return true
}
}
return false
}
func (m *multiHandler) Handle(ctx context.Context, r slog.Record) error {
span := trace.SpanFromContext(ctx)
if span.SpanContext().HasTraceID() {
r.AddAttrs(
slog.String("trace_id", span.SpanContext().TraceID().String()),
slog.String("span_id", span.SpanContext().SpanID().String()),
)
}
for _, h := range m.handlers {
_ = h.Handle(ctx, r)
}
return nil
}
func (m *multiHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
newHandlers := make([]slog.Handler, len(m.handlers))
for i, h := range m.handlers {
newHandlers[i] = h.WithAttrs(attrs)
}
return &multiHandler{handlers: newHandlers}
}
func (m *multiHandler) WithGroup(name string) slog.Handler {
newHandlers := make([]slog.Handler, len(m.handlers))
for i, h := range m.handlers {
newHandlers[i] = h.WithGroup(name)
}
return &multiHandler{handlers: newHandlers}
}
func Init() {
levelStr := strings.ToLower(viper.GetString("server.log_level"))
var level slog.Level
switch levelStr {
case "debug":
level = slog.LevelDebug
case "warn":
level = slog.LevelWarn
case "error":
level = slog.LevelError
default:
level = slog.LevelInfo
}
var writer io.Writer = os.Stdout
if level == slog.LevelDebug {
file, _ := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
writer = io.MultiWriter(os.Stdout, file)
}
localHandler := slog.NewJSONHandler(writer, &slog.HandlerOptions{
Level: level,
AddSource: true,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
return slog.String(a.Key, a.Value.Time().Format("2006-01-02 15:04:05"))
}
return a
},
})
otelHandler := otelslog.NewHandler(viper.GetString("server.service_name"))
combinedHandler := &multiHandler{
handlers: []slog.Handler{localHandler, otelHandler},
}
slog.SetDefault(slog.New(combinedHandler))
}