626e1bb5ac
Store file handle per module, swap lifecycle logger before closing file, return teardown errors, remove duplicate Module() func. Co-authored-by: Cursor <cursoragent@cursor.com>
92 lines
2.0 KiB
Go
92 lines
2.0 KiB
Go
package applog
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"time"
|
|
|
|
"gitea.auvem.com/go-toolkit/app"
|
|
"github.com/lmittmann/tint"
|
|
slogmulti "github.com/samber/slog-multi"
|
|
)
|
|
|
|
type moduleState struct {
|
|
opts AppLogOpts
|
|
logfile *os.File
|
|
consoleHandler slog.Handler
|
|
}
|
|
|
|
func (s *moduleState) setup(m *app.Module) error {
|
|
if s.opts.FileOutput == "" && s.opts.ConsoleOutput == nil {
|
|
return fmt.Errorf("no logging output configured")
|
|
}
|
|
|
|
handlers := make([]slog.Handler, 0, 2)
|
|
|
|
if s.opts.FileOutput != "" {
|
|
f, err := os.OpenFile(s.opts.FileOutput, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.logfile = f
|
|
|
|
fileLevel := s.opts.FileLevel
|
|
if fileLevel == 0 && s.opts.ConsoleOutput == nil {
|
|
fileLevel = slog.LevelInfo
|
|
}
|
|
handlers = append(handlers, slog.NewJSONHandler(f, &slog.HandlerOptions{Level: fileLevel}))
|
|
}
|
|
|
|
if s.opts.ConsoleOutput != nil {
|
|
consoleLevel := s.opts.ConsoleLevel
|
|
if consoleLevel == 0 {
|
|
consoleLevel = slog.LevelInfo
|
|
}
|
|
s.consoleHandler = tint.NewHandler(s.opts.ConsoleOutput, &tint.Options{
|
|
Level: consoleLevel,
|
|
TimeFormat: time.Kitchen,
|
|
})
|
|
handlers = append(handlers, s.consoleHandler)
|
|
}
|
|
|
|
logger := slog.New(slogmulti.Fanout(handlers...))
|
|
m.Lifecycle().WithLogger(logger)
|
|
|
|
if s.opts.SetDefault {
|
|
slog.SetDefault(logger)
|
|
}
|
|
|
|
if !s.opts.DisableAnnouncement {
|
|
logger.Info("Logger initialized", "module", ModuleName)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *moduleState) teardown(lifecycle *app.Lifecycle) error {
|
|
if lifecycle != nil {
|
|
switch {
|
|
case s.consoleHandler != nil:
|
|
lifecycle.WithLogger(slog.New(s.consoleHandler))
|
|
default:
|
|
lifecycle.WithLogger(slog.New(slog.DiscardHandler))
|
|
}
|
|
}
|
|
|
|
if s.logfile == nil {
|
|
return nil
|
|
}
|
|
|
|
var err error
|
|
if syncErr := s.logfile.Sync(); syncErr != nil {
|
|
err = fmt.Errorf("flush log file: %w", syncErr)
|
|
}
|
|
if closeErr := s.logfile.Close(); closeErr != nil {
|
|
err = errors.Join(err, fmt.Errorf("close log file: %w", closeErr))
|
|
}
|
|
s.logfile = nil
|
|
return err
|
|
}
|