package logger import ( "context" "io" "log/slog" "sync" ) type MyJsonHandler struct { output io.Writer mu sync.Mutex jsonHandler slog.Handler } var stackChan = make(chan string, 100) func newMyJsonHandler(output io.Writer, opts *slog.HandlerOptions) *MyJsonHandler { if opts == nil { opts = &slog.HandlerOptions{} } ra := opts.ReplaceAttr opts.ReplaceAttr = func(groups []string, a slog.Attr) slog.Attr { if a.Key == "stack" { stackChan <- a.Value.String() return slog.Attr{} } else { if ra != nil { return ra(groups, a) } else { return a } } } return &MyJsonHandler{output: output, mu: sync.Mutex{}, jsonHandler: slog.NewJSONHandler(output, opts)} } func (s *MyJsonHandler) Enabled(ctx context.Context, level slog.Level) bool { return s.jsonHandler.Enabled(ctx, level) } func (s *MyJsonHandler) Handle(ctx context.Context, record slog.Record) error { err := s.jsonHandler.Handle(ctx, record) if err != nil { return err } select { case stack := <-stackChan: s.mu.Lock() defer s.mu.Unlock() _, err = s.output.Write([]byte(stack)) default: } return err } func (s *MyJsonHandler) WithAttrs(attrs []slog.Attr) slog.Handler { return s.jsonHandler.WithAttrs(attrs) } func (s *MyJsonHandler) WithGroup(name string) slog.Handler { return s.jsonHandler.WithGroup(name) }