@@ -10,6 +10,7 @@ import (
1010 "io"
1111 "os"
1212 "strconv"
13+ "strings"
1314 "time"
1415
1516 "github.com/joho/godotenv"
@@ -54,9 +55,30 @@ func configureLogger() *logrus.Logger {
5455func configureLoggerWithOutput (output io.Writer ) * logrus.Logger {
5556 logger := logrus .New ()
5657
57- // Set output if provided (for testing)
58+ // Set output - file logging if LOG_FILE is set, otherwise stdout
5859 if output != nil {
60+ // Testing mode - use provided output
5961 logger .SetOutput (output )
62+ } else if logFile := os .Getenv ("LOG_FILE" ); logFile != "" {
63+ // File logging enabled - write to both stdout and file
64+ if err := os .MkdirAll (utils .GetDir (logFile ), 0755 ); err != nil {
65+ logger .Warnf ("Failed to create log directory: %v, falling back to stdout only" , err )
66+ logger .SetOutput (os .Stdout )
67+ } else {
68+ file , err := os .OpenFile (logFile , os .O_CREATE | os .O_WRONLY | os .O_APPEND , 0644 )
69+ if err != nil {
70+ logger .Warnf ("Failed to open log file %s: %v, falling back to stdout only" , logFile , err )
71+ logger .SetOutput (os .Stdout )
72+ } else {
73+ // Write to both stdout and file
74+ multiWriter := io .MultiWriter (os .Stdout , file )
75+ logger .SetOutput (multiWriter )
76+ logger .Infof ("Logging to file: %s" , logFile )
77+ }
78+ }
79+ } else {
80+ // Default to stdout only
81+ logger .SetOutput (os .Stdout )
6082 }
6183
6284 // Set log level - flag takes precedence over environment variable
@@ -100,6 +122,69 @@ type LoadEnvConfig struct {
100122 Error error
101123}
102124
125+ /**************************************************************************************************
126+ ** logStartupSummary logs a concise summary of the current configuration at startup.
127+ ** Shows the resolved configuration values for all major settings.
128+ **
129+ ** @param logger - Logger instance to output the summary
130+ **************************************************************************************************/
131+ func logStartupSummary (logger * logrus.Logger ) {
132+ // Build summary based on format
133+ if format := os .Getenv ("LOG_FORMAT" ); format == "json" {
134+ logger .WithFields (logrus.Fields {
135+ "runMode" : runMode ,
136+ "cronInterval" : cronInterval ,
137+ "logLevel" : logger .GetLevel ().String (),
138+ "logFormat" : "json" ,
139+ "logFile" : os .Getenv ("LOG_FILE" ),
140+ "dryRun" : dryRun ,
141+ "replaceStacks" : replaceStacks ,
142+ "resetStacks" : resetStacks ,
143+ "withArchived" : withArchived ,
144+ "withDeleted" : withDeleted ,
145+ "removeSingleAssetStacks" : removeSingleAssetStacks ,
146+ "criteria" : criteria ,
147+ "parentFilenamePromote" : parentFilenamePromote ,
148+ "parentExtPromote" : parentExtPromote ,
149+ }).Info ("Configuration loaded" )
150+ } else {
151+ // Build human-readable summary
152+ var summary []string
153+ summary = append (summary , fmt .Sprintf ("mode=%s" , runMode ))
154+ if runMode == "cron" {
155+ summary = append (summary , fmt .Sprintf ("interval=%ds" , cronInterval ))
156+ }
157+ summary = append (summary , fmt .Sprintf ("level=%s" , logger .GetLevel ().String ()))
158+ summary = append (summary , fmt .Sprintf ("format=%s" , "text" ))
159+ if logFile := os .Getenv ("LOG_FILE" ); logFile != "" {
160+ summary = append (summary , fmt .Sprintf ("file=%s" , logFile ))
161+ }
162+ if dryRun {
163+ summary = append (summary , "dry-run=true" )
164+ }
165+ if replaceStacks {
166+ summary = append (summary , "replace=true" )
167+ }
168+ if resetStacks {
169+ summary = append (summary , "reset=true" )
170+ }
171+ if withArchived {
172+ summary = append (summary , "archived=true" )
173+ }
174+ if withDeleted {
175+ summary = append (summary , "deleted=true" )
176+ }
177+ if removeSingleAssetStacks {
178+ summary = append (summary , "remove-single=true" )
179+ }
180+ if criteria != "" {
181+ summary = append (summary , fmt .Sprintf ("criteria=%s" , criteria ))
182+ }
183+
184+ logger .Infof ("Starting with config: %s" , strings .Join (summary , ", " ))
185+ }
186+ }
187+
103188/**************************************************************************************************
104189** LoadEnvForTesting loads environment variables and validates configuration without calling Fatal().
105190** Returns errors instead of terminating, allowing tests to verify error conditions.
@@ -183,6 +268,10 @@ func LoadEnvForTesting() LoadEnvConfig {
183268 parentExtPromote = envVal
184269 }
185270 }
271+
272+ // Log startup configuration summary
273+ logStartupSummary (logger )
274+
186275 return LoadEnvConfig {Logger : logger , Error : nil }
187276}
188277
0 commit comments