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
This commit is contained in:
yusing
2025-10-10 22:20:12 +08:00
parent 357ce38b18
commit 38c0419483
4 changed files with 34 additions and 9 deletions

View File

@@ -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)
}