package tracing import ( "context" "errors" "log/slog" ) // FanoutHandler 是一个将日志记录扇出到多个 slog.Handler 的组合处理器, // 用于同时输出本地 JSON 日志与 OTel 日志桥接。 type FanoutHandler struct { handlers []slog.Handler } // NewFanoutHandler 创建扇出处理器(忽略 nil handler)。 func NewFanoutHandler(handlers ...slog.Handler) *FanoutHandler { filtered := make([]slog.Handler, 0, len(handlers)) for _, h := range handlers { if h != nil { filtered = append(filtered, h) } } return &FanoutHandler{handlers: filtered} } // Enabled 任一子处理器启用即返回 true。 func (f *FanoutHandler) Enabled(ctx context.Context, level slog.Level) bool { for _, h := range f.handlers { if h.Enabled(ctx, level) { return true } } return false } // Handle 将记录分发给每个启用的子处理器(各自使用副本,避免相互污染)。 func (f *FanoutHandler) Handle(ctx context.Context, r slog.Record) error { var errs []error for _, h := range f.handlers { if h.Enabled(ctx, r.Level) { if err := h.Handle(ctx, r.Clone()); err != nil { errs = append(errs, err) } } } return errors.Join(errs...) } // WithAttrs 为每个子处理器附加属性。 func (f *FanoutHandler) WithAttrs(attrs []slog.Attr) slog.Handler { next := make([]slog.Handler, len(f.handlers)) for i, h := range f.handlers { next[i] = h.WithAttrs(attrs) } return &FanoutHandler{handlers: next} } // WithGroup 为每个子处理器开启分组。 func (f *FanoutHandler) WithGroup(name string) slog.Handler { if name == "" { return f } next := make([]slog.Handler, len(f.handlers)) for i, h := range f.handlers { next[i] = h.WithGroup(name) } return &FanoutHandler{handlers: next} }