From 1b55498b0048739978de4cbada46bd9a0cfd16a1 Mon Sep 17 00:00:00 2001 From: Nikolai Papin Date: Mon, 23 Jun 2025 14:18:25 +0300 Subject: [PATCH] refactor: a better DI-friendy logger implementation that doesn't suck --- backend/cmd/main.go | 15 ++++++++++-- backend/internal/logger/logger.go | 40 ++++++++++++++----------------- backend/internal/services/auth.go | 9 ++++--- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index b69e2e8..1fb5fb1 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -20,6 +20,7 @@ import ( "github.com/gin-gonic/gin" "go.uber.org/fx" + "go.uber.org/zap" "easywish/config" docs "easywish/docs" @@ -42,6 +43,7 @@ func main() { fx.New( fx.Provide( logger.NewLogger, + logger.NewSyncLogger, gin.Default, ), database.Module, @@ -49,7 +51,7 @@ func main() { controllers.Module, routes.Module, - fx.Invoke(func(lc fx.Lifecycle, router *gin.Engine) { + fx.Invoke(func(lc fx.Lifecycle, router *gin.Engine, syncLogger *logger.SyncLogger) { // Swagger docs.SwaggerInfo.Schemes = []string{"http"} @@ -65,6 +67,7 @@ func main() { OnStart: func(ctx context.Context) error { go func() { if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + syncLogger.Fatal("Server failed", zap.Error(err)) } }() return nil @@ -72,7 +75,15 @@ func main() { OnStop: func(ctx context.Context) error { shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - return server.Shutdown(shutdownCtx) + + if err := server.Shutdown(shutdownCtx); err != nil { + syncLogger.Error("Server shutdown error", zap.Error(err)) + } + + if err := syncLogger.Close(); err != nil { + syncLogger.Error("Logger sync error", zap.Error(err)) + } + return nil }, }) }), diff --git a/backend/internal/logger/logger.go b/backend/internal/logger/logger.go index d2586bd..5bac938 100644 --- a/backend/internal/logger/logger.go +++ b/backend/internal/logger/logger.go @@ -8,40 +8,36 @@ import ( "go.uber.org/zap" ) -type Logger interface { - Get() *zap.Logger - Sync() error -} - -type loggerImpl struct { -} - -func NewLogger() Logger { - return &loggerImpl{} -} - var ( - logger *zap.Logger - once sync.Once + instance *zap.Logger + once sync.Once ) -func (l *loggerImpl) Get() *zap.Logger { +func NewLogger() *zap.Logger { once.Do(func() { - var err error cfg := config.GetConfig() + var err error if cfg.Environment == "production" { - logger, err = zap.NewProduction() + instance, err = zap.NewProduction() } else { - logger, err = zap.NewDevelopment() + instance, err = zap.NewDevelopment() } if err != nil { - panic(err) + panic("failed to initialize logger: " + err.Error()) } }) - return logger + return instance } -func (l *loggerImpl) Sync() error { - return logger.Sync() +type SyncLogger struct { + *zap.Logger +} + +func NewSyncLogger(logger *zap.Logger) *SyncLogger { + return &SyncLogger{logger} +} + +func (s *SyncLogger) Close() error { + return s.Sync() } diff --git a/backend/internal/services/auth.go b/backend/internal/services/auth.go index b752d01..a91db04 100644 --- a/backend/internal/services/auth.go +++ b/backend/internal/services/auth.go @@ -3,7 +3,6 @@ package services import ( "easywish/internal/database" errs "easywish/internal/errors" - "easywish/internal/logger" "easywish/internal/models" "easywish/internal/utils" @@ -18,11 +17,11 @@ type AuthService interface { } type authServiceImpl struct { - log logger.Logger + log *zap.Logger dbctx database.DbContext } -func NewAuthService(_log logger.Logger, _dbctx database.DbContext) AuthService { +func NewAuthService(_log *zap.Logger, _dbctx database.DbContext) AuthService { return &authServiceImpl{log: _log, dbctx: _dbctx} } @@ -33,10 +32,10 @@ func (a *authServiceImpl) RegistrationBegin(request models.RegistrationBeginRequ user, err := db.TXQueries.CreateUser(db.CTX, request.Username) // TODO: validation if err != nil { - a.log.Get().Error("Failed to add user to database", zap.Error(err)) + a.log.Error("Failed to add user to database", zap.Error(err)) return false, errs.ErrServerError } - a.log.Get().Info("Registered a new user", zap.String("username", user.Username)) + a.log.Info("Registered a new user", zap.String("username", user.Username)) helper.Commit()