fix: improve logging and error visibility, move Story 1.7 to Epic 2
Fixes: - Added database connection logging with masked DSN - Added migration progress logging - Added HTTP server startup logging with address - Fixed database provider to accept logger parameter - Improved error visibility throughout initialization Documentation: - Moved Story 1.7 (Service Client Interfaces) to Epic 2 as Story 2.7 - Updated Epic 1 and Epic 2 READMEs - Updated COMPLETE_TASK_LIST.md - Updated story metadata (ID, Epic, Dependencies) These changes will help diagnose startup issues and provide better visibility into what the application is doing.
This commit is contained in:
@@ -67,7 +67,7 @@ func ProvideLogger() fx.Option {
|
||||
|
||||
// ProvideDatabase creates an FX option that provides the database client.
|
||||
func ProvideDatabase() fx.Option {
|
||||
return fx.Provide(func(cfg config.ConfigProvider, lc fx.Lifecycle) (*database.Client, error) {
|
||||
return fx.Provide(func(cfg config.ConfigProvider, log logger.Logger, lc fx.Lifecycle) (*database.Client, error) {
|
||||
dsn := cfg.GetString("database.dsn")
|
||||
if dsn == "" {
|
||||
return nil, fmt.Errorf("database DSN is not configured")
|
||||
@@ -108,9 +108,11 @@ func ProvideDatabase() fx.Option {
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(ctx context.Context) error {
|
||||
// Run migrations on startup
|
||||
log.Info("Running database migrations...")
|
||||
if err := dbClient.Migrate(ctx); err != nil {
|
||||
return fmt.Errorf("failed to run database migrations: %w", err)
|
||||
}
|
||||
log.Info("Database migrations completed successfully")
|
||||
return nil
|
||||
},
|
||||
OnStop: func(ctx context.Context) error {
|
||||
@@ -225,8 +227,22 @@ func ProvideHTTPServer() fx.Option {
|
||||
// Register lifecycle hooks
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(ctx context.Context) error {
|
||||
// Get server address from config
|
||||
port := cfg.GetInt("server.port")
|
||||
if port == 0 {
|
||||
port = 8080
|
||||
}
|
||||
host := cfg.GetString("server.host")
|
||||
if host == "" {
|
||||
host = "0.0.0.0"
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%d", host, port)
|
||||
|
||||
// Start server in a goroutine
|
||||
go func() {
|
||||
log.Info("HTTP server starting",
|
||||
logger.String("addr", addr),
|
||||
)
|
||||
if err := srv.Start(); err != nil && err != http.ErrServerClosed {
|
||||
log.Error("HTTP server error",
|
||||
logger.String("error", err.Error()),
|
||||
@@ -259,6 +275,32 @@ func CoreModule() fx.Option {
|
||||
)
|
||||
}
|
||||
|
||||
// maskDSN masks sensitive information in DSN for logging.
|
||||
func maskDSN(dsn string) string {
|
||||
// Simple masking: replace password with ***
|
||||
// Format: postgres://user:password@host:port/db
|
||||
if len(dsn) < 20 {
|
||||
return "***"
|
||||
}
|
||||
// Find @ symbol and replace password part
|
||||
if idx := indexOf(dsn, '@'); idx > 0 {
|
||||
if colonIdx := indexOf(dsn[:idx], ':'); colonIdx > 0 {
|
||||
return dsn[:colonIdx+1] + "***" + dsn[idx:]
|
||||
}
|
||||
}
|
||||
return "***"
|
||||
}
|
||||
|
||||
// indexOf finds the index of a character in a string.
|
||||
func indexOf(s string, c byte) int {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == c {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// RegisterLifecycleHooks registers lifecycle hooks for logging.
|
||||
func RegisterLifecycleHooks(lc fx.Lifecycle, l logger.Logger) {
|
||||
lc.Append(fx.Hook{
|
||||
|
||||
Reference in New Issue
Block a user