From 38c04194832a9281919eeb38291014b2e45eba84 Mon Sep 17 00:00:00 2001 From: yusing Date: Fri, 10 Oct 2025 22:20:12 +0800 Subject: [PATCH] feat(config): add temporary logging for failed reloads - Add tmpLogBuf and tmpLog fields to capture config loading logs - Flush temporary logs only when reload succeeds - Extract NewLogger function for creating custom loggers - Update State interface to include FlushTmpLog method --- internal/config/events.go | 6 ++++++ internal/config/state.go | 25 +++++++++++++++++++------ internal/config/types/state.go | 2 ++ internal/logging/logging.go | 10 +++++++--- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/internal/config/events.go b/internal/config/events.go index aa03d2a6..07c3703a 100644 --- a/internal/config/events.go +++ b/internal/config/events.go @@ -45,6 +45,9 @@ func Load() error { notifyError("init", err) } SetState(state) + + // flush temporary log + state.FlushTmpLog() return nil } @@ -69,6 +72,9 @@ func Reload() gperr.Error { return gperr.New(ansi.Warning("using last config")).With(err) } + // flush temporary log + newState.FlushTmpLog() + // cancel all current subtasks -> wait // -> replace config -> start new subtasks GetState().Task().FinishAndWait(config.ErrConfigChanged) diff --git a/internal/config/state.go b/internal/config/state.go index 4509ee79..d16cc3f6 100644 --- a/internal/config/state.go +++ b/internal/config/state.go @@ -1,6 +1,7 @@ package config import ( + "bytes" "context" "fmt" "iter" @@ -21,6 +22,7 @@ import ( config "github.com/yusing/godoxy/internal/config/types" "github.com/yusing/godoxy/internal/entrypoint" homepage "github.com/yusing/godoxy/internal/homepage/types" + "github.com/yusing/godoxy/internal/logging" "github.com/yusing/godoxy/internal/maxmind" "github.com/yusing/godoxy/internal/notif" route "github.com/yusing/godoxy/internal/route/provider" @@ -40,13 +42,21 @@ type state struct { entrypoint entrypoint.Entrypoint task *task.Task + + // used for temporary logging + // discarded on failed reload + tmpLogBuf *bytes.Buffer + tmpLog zerolog.Logger } func NewState() config.State { + tmpLogBuf := bytes.NewBuffer(make([]byte, 0, 4096)) return &state{ providers: xsync.NewMap[string, types.RouteProvider](), entrypoint: entrypoint.NewEntrypoint(), task: task.RootTask("config", false), + tmpLogBuf: tmpLogBuf, + tmpLog: logging.NewLogger(tmpLogBuf), } } @@ -167,6 +177,11 @@ func (state *state) NumProviders() int { return state.providers.Size() } +func (state *state) FlushTmpLog() { + state.tmpLogBuf.WriteTo(os.Stdout) + state.tmpLogBuf.Reset() +} + // this one is connection level access logger, different from entrypoint access logger func (state *state) initAccessLogger() error { if !state.ACL.Valid() { @@ -336,8 +351,7 @@ func (state *state) loadRouteProviders() error { } providersLoader.Wait() - log.Info().Msg(results.String()) - + state.tmpLog.Info().Msg(results.String()) state.printRoutesByProvider(lenLongestName) state.printState() return errs.Error() @@ -389,12 +403,11 @@ func (state *state) printRoutesByProvider(lenLongestName int) { // Always print the routes since we want to show even empty providers routeStr := routeResults.String() if routeStr != "" { - log.Info().Msg(routeStr) + state.tmpLog.Info().Msg(routeStr) } } func (state *state) printState() { - log.Info().Msg("active config") - l := log.Level(zerolog.InfoLevel) - yaml.NewEncoder(l).Encode(state.Config) + state.tmpLog.Info().Msg("active config:") + yaml.NewEncoder(state.tmpLog).Encode(state.Config) } diff --git a/internal/config/types/state.go b/internal/config/types/state.go index 54251a0a..88b67f7f 100644 --- a/internal/config/types/state.go +++ b/internal/config/types/state.go @@ -30,6 +30,8 @@ type State interface { IterProviders() iter.Seq2[string, types.RouteProvider] NumProviders() int StartProviders() error + + FlushTmpLog() } // could be nil diff --git a/internal/logging/logging.go b/internal/logging/logging.go index af860d25..284c4c4d 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -48,7 +48,7 @@ func fmtMessage(msg string) string { return strutils.JoinRune(lines, '\n') } -func InitLogger(out ...io.Writer) { +func NewLogger(out ...io.Writer) zerolog.Logger { writer := zerolog.ConsoleWriter{ Out: zerolog.MultiLevelWriter(out...), TimeFormat: timeFmt, @@ -56,10 +56,14 @@ func InitLogger(out ...io.Writer) { return fmtMessage(msgI.(string)) }, } - logger = zerolog.New( + return zerolog.New( writer, ).Level(level).With().Timestamp().Logger() - log.SetOutput(writer) +} + +func InitLogger(out ...io.Writer) { + logger = NewLogger(out...) + log.SetOutput(logger) log.SetPrefix("") log.SetFlags(0) zerolog.TimeFieldFormat = timeFmt