mirror of
https://github.com/gabehf/Koito.git
synced 2026-03-10 07:50:37 -07:00
chore: expand debug logging + embeddable version
This commit is contained in:
parent
edbd7d506e
commit
e92733823d
25 changed files with 563 additions and 303 deletions
|
|
@ -29,26 +29,28 @@ import (
|
|||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const Version = "dev"
|
||||
|
||||
func Run(
|
||||
getenv func(string) string,
|
||||
w io.Writer,
|
||||
version string,
|
||||
) error {
|
||||
err := cfg.Load(getenv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load configuration: %v", err)
|
||||
panic("Engine: Failed to load configuration")
|
||||
}
|
||||
|
||||
l := logger.Get()
|
||||
|
||||
l.Debug().Msg("Engine: Starting application initialization")
|
||||
|
||||
if cfg.StructuredLogging() {
|
||||
l.Debug().Msg("Engine: Enabling structured logging")
|
||||
*l = l.Output(w)
|
||||
} else {
|
||||
l.Debug().Msg("Engine: Enabling console logging")
|
||||
*l = l.Output(zerolog.ConsoleWriter{
|
||||
Out: w,
|
||||
TimeFormat: time.RFC3339,
|
||||
// FormatLevel: func(i interface{}) string {
|
||||
// return strings.ToUpper(fmt.Sprintf("[%s]", i))
|
||||
// },
|
||||
FormatMessage: func(i interface{}) string {
|
||||
return fmt.Sprintf("\u001b[30;1m>\u001b[0m %s |", i)
|
||||
},
|
||||
|
|
@ -57,64 +59,75 @@ func Run(
|
|||
|
||||
ctx := logger.NewContext(l)
|
||||
|
||||
l.Info().Msgf("Koito %s", Version)
|
||||
l.Info().Msgf("Koito %s", version)
|
||||
|
||||
l.Debug().Msgf("Engine: Checking config directory: %s", cfg.ConfigDir())
|
||||
_, err = os.Stat(cfg.ConfigDir())
|
||||
if err != nil {
|
||||
l.Info().Msgf("Creating config dir: %s", cfg.ConfigDir())
|
||||
l.Info().Msgf("Engine: Creating config directory: %s", cfg.ConfigDir())
|
||||
err = os.MkdirAll(cfg.ConfigDir(), 0744)
|
||||
if err != nil {
|
||||
l.Error().Err(err).Msg("Failed to create config directory")
|
||||
l.Fatal().Err(err).Msg("Engine: Failed to create config directory")
|
||||
return err
|
||||
}
|
||||
}
|
||||
l.Info().Msgf("Using config dir: %s", cfg.ConfigDir())
|
||||
l.Info().Msgf("Engine: Using config directory: %s", cfg.ConfigDir())
|
||||
|
||||
l.Debug().Msgf("Engine: Checking import directory: %s", path.Join(cfg.ConfigDir(), "import"))
|
||||
_, err = os.Stat(path.Join(cfg.ConfigDir(), "import"))
|
||||
if err != nil {
|
||||
l.Debug().Msgf("Creating import dir: %s", path.Join(cfg.ConfigDir(), "import"))
|
||||
l.Info().Msgf("Engine: Creating import directory: %s", path.Join(cfg.ConfigDir(), "import"))
|
||||
err = os.Mkdir(path.Join(cfg.ConfigDir(), "import"), 0744)
|
||||
if err != nil {
|
||||
l.Error().Err(err).Msg("Failed to create import directory")
|
||||
l.Fatal().Err(err).Msg("Engine: Failed to create import directory")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
l.Debug().Msg("Engine: Initializing database connection")
|
||||
var store *psql.Psql
|
||||
store, err = psql.New()
|
||||
for err != nil {
|
||||
l.Error().Err(err).Msg("Failed to connect to database; retrying in 5 seconds")
|
||||
l.Error().Err(err).Msg("Engine: Failed to connect to database; retrying in 5 seconds")
|
||||
time.Sleep(5 * time.Second)
|
||||
store, err = psql.New()
|
||||
}
|
||||
defer store.Close(ctx)
|
||||
l.Info().Msg("Engine: Database connection established")
|
||||
|
||||
l.Debug().Msg("Engine: Initializing MusicBrainz client")
|
||||
var mbzC mbz.MusicBrainzCaller
|
||||
if !cfg.MusicBrainzDisabled() {
|
||||
mbzC = mbz.NewMusicBrainzClient()
|
||||
l.Info().Msg("Engine: MusicBrainz client initialized")
|
||||
} else {
|
||||
mbzC = &mbz.MbzErrorCaller{}
|
||||
l.Warn().Msg("Engine: MusicBrainz client disabled")
|
||||
}
|
||||
|
||||
l.Debug().Msg("Engine: Initializing image sources")
|
||||
images.Initialize(images.ImageSourceOpts{
|
||||
UserAgent: cfg.UserAgent(),
|
||||
EnableCAA: !cfg.CoverArtArchiveDisabled(),
|
||||
EnableDeezer: !cfg.DeezerDisabled(),
|
||||
})
|
||||
l.Info().Msg("Engine: Image sources initialized")
|
||||
|
||||
l.Debug().Msg("Engine: Checking for default user")
|
||||
userCount, _ := store.CountUsers(ctx)
|
||||
if userCount < 1 {
|
||||
l.Debug().Msg("Creating default user...")
|
||||
l.Info().Msg("Engine: Creating default user")
|
||||
user, err := store.SaveUser(ctx, db.SaveUserOpts{
|
||||
Username: cfg.DefaultUsername(),
|
||||
Password: cfg.DefaultPassword(),
|
||||
Role: models.UserRoleAdmin,
|
||||
})
|
||||
if err != nil {
|
||||
l.Fatal().AnErr("error", err).Msg("Failed to save default user in database")
|
||||
l.Fatal().Err(err).Msg("Engine: Failed to save default user in database")
|
||||
}
|
||||
apikey, err := utils.GenerateRandomString(48)
|
||||
if err != nil {
|
||||
l.Fatal().AnErr("error", err).Msg("Failed to generate default api key")
|
||||
l.Fatal().Err(err).Msg("Engine: Failed to generate default API key")
|
||||
}
|
||||
label := "Default"
|
||||
_, err = store.SaveApiKey(ctx, db.SaveApiKeyOpts{
|
||||
|
|
@ -123,28 +136,27 @@ func Run(
|
|||
Label: label,
|
||||
})
|
||||
if err != nil {
|
||||
l.Fatal().AnErr("error", err).Msg("Failed to save default api key in database")
|
||||
l.Fatal().Err(err).Msg("Engine: Failed to save default API key in database")
|
||||
}
|
||||
l.Info().Msgf("Default user has been created. Login: %s : %s", cfg.DefaultUsername(), cfg.DefaultPassword())
|
||||
l.Info().Msgf("Engine: Default user created. Login: %s : %s", cfg.DefaultUsername(), cfg.DefaultPassword())
|
||||
}
|
||||
|
||||
l.Debug().Msg("Engine: Checking allowed hosts configuration")
|
||||
if cfg.AllowAllHosts() {
|
||||
l.Warn().Msg("Your configuration allows requests from all hosts. This is a potential security risk!")
|
||||
l.Warn().Msg("Engine: Configuration allows requests from all hosts. This is a potential security risk!")
|
||||
} else if len(cfg.AllowedHosts()) == 0 || cfg.AllowedHosts()[0] == "" {
|
||||
l.Warn().Msgf("You are currently not allowing any hosts! Did you forget to set the %s variable?", cfg.ALLOWED_HOSTS_ENV)
|
||||
l.Warn().Msgf("Engine: No hosts allowed! Did you forget to set the %s variable?", cfg.ALLOWED_HOSTS_ENV)
|
||||
} else {
|
||||
l.Debug().Msgf("Allowing hosts: %v", cfg.AllowedHosts())
|
||||
l.Info().Msgf("Engine: Allowing hosts: %v", cfg.AllowedHosts())
|
||||
}
|
||||
|
||||
l.Debug().Msg("Engine: Setting up HTTP server")
|
||||
var ready atomic.Bool
|
||||
|
||||
mux := chi.NewRouter()
|
||||
// bind general middleware to mux
|
||||
mux.Use(middleware.WithRequestID)
|
||||
mux.Use(middleware.Logger(l))
|
||||
mux.Use(chimiddleware.Recoverer)
|
||||
mux.Use(chimiddleware.RealIP)
|
||||
// call router binds on mux
|
||||
bindRoutes(mux, &ready, store, mbzC)
|
||||
|
||||
httpServer := &http.Server{
|
||||
|
|
@ -153,36 +165,38 @@ func Run(
|
|||
}
|
||||
|
||||
go func() {
|
||||
ready.Store(true) // signal readiness
|
||||
l.Info().Msg("listening on " + cfg.ListenAddr())
|
||||
ready.Store(true)
|
||||
l.Info().Msgf("Engine: Listening on %s", cfg.ListenAddr())
|
||||
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
l.Fatal().AnErr("error", err).Msg("Error when running ListenAndServe")
|
||||
l.Fatal().Err(err).Msg("Engine: Error when running ListenAndServe")
|
||||
}
|
||||
}()
|
||||
|
||||
// Import
|
||||
l.Debug().Msg("Engine: Checking import configuration")
|
||||
if !cfg.SkipImport() {
|
||||
go func() {
|
||||
RunImporter(l, store, mbzC)
|
||||
}()
|
||||
}
|
||||
|
||||
l.Info().Msg("Pruning orphaned images...")
|
||||
l.Info().Msg("Engine: Pruning orphaned images")
|
||||
go catalog.PruneOrphanedImages(logger.NewContext(l), store)
|
||||
// Wait for interrupt signal to gracefully shutdown the server with a timeout of 10 seconds.
|
||||
// Use a buffered channel to avoid missing signals as recommended for signal.Notify
|
||||
|
||||
l.Info().Msg("Engine: Initialization finished")
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
l.Info().Msg("Received server shutdown notice")
|
||||
l.Info().Msg("Engine: Received server shutdown notice")
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
l.Info().Msg("waiting for all processes to finish...")
|
||||
l.Info().Msg("Engine: Waiting for all processes to finish")
|
||||
mbzC.Shutdown()
|
||||
if err := httpServer.Shutdown(ctx); err != nil {
|
||||
l.Fatal().Err(err).Msg("Engine: Error during server shutdown")
|
||||
return err
|
||||
}
|
||||
l.Info().Msg("shutdown successful")
|
||||
l.Info().Msg("Engine: Shutdown successful")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue