@@ -12,7 +12,6 @@ import (
1212 "time"
1313
1414 "github.com/go-logr/logr"
15- abtrlog "github.com/maansaake/arbiter/internal/log"
1615 "github.com/maansaake/arbiter/pkg/module"
1716 "github.com/maansaake/arbiter/pkg/report"
1817 "github.com/maansaake/arbiter/pkg/report/collection"
@@ -25,6 +24,7 @@ import (
2524 "github.com/spf13/cobra"
2625 "github.com/spf13/pflag"
2726 "github.com/trebent/envparser"
27+ "github.com/trebent/zerologr"
2828)
2929
3030type (
3838 reportPath string
3939 // interactive is set when an interactive TUI reporting is used.
4040 interactive bool
41+ // logger is used for info-level logging.
42+ logger logr.Logger
4143 // errorLogger is the logger used for error logs by the reporter.
4244 errorLogger logr.Logger
4345 }
@@ -51,27 +53,26 @@ type (
5153 }
5254)
5355
56+ const (
57+ defaultInfoLogPath = "info.log"
58+ defaultErrorLogPath = "error.log"
59+ defaultDuration = time .Minute * 5
60+ defaultReportPath = "report.yaml"
61+ defaultInteractive = false
62+ )
63+
5464// defaultOpts sets zero-value fields to their defaults.
5565func (o * Opts ) defaultOpts () {
5666 if o .ErrorLogPath == "" {
57- o .InfoLogPath = abtrlog . DefaultErrorLogPath
67+ o .ErrorLogPath = defaultErrorLogPath
5868 }
5969
60- if o .ErrorLogPath == "" {
61- o .InfoLogPath = abtrlog . DefaultInfoLogPath
70+ if o .InfoLogPath == "" {
71+ o .InfoLogPath = defaultInfoLogPath
6272 }
6373}
6474
65- const (
66- defaultDuration = time .Minute * 5
67- defaultReportPath = "report.yaml"
68- defaultInteractive = false
69- )
70-
7175var (
72- // logger is the package logger for the arbiter package.
73- logger logr.Logger //nolint:gochecknoglobals // package-level state for arbiter
74-
7576 // rootCmd holds the cobra root command for Usage access.
7677 //nolint:gochecknoglobals // package-level command for Usage access
7778 rootCmd * cobra.Command
@@ -123,21 +124,17 @@ func Run(modules module.Modules, opts *Opts) error {
123124 SilenceUsage : true ,
124125 }
125126
126- errorLogger , err := abtrlog .Setup (& abtrlog.Opts {
127- Verbosity : logVerbosity .Value (),
128- ErrorLogPath : opts .ErrorLogPath ,
129- InfoLogPath : opts .InfoLogPath ,
130- })
127+ infoLogger , errorLogger , err := setupLoggers (opts , logVerbosity .Value ())
131128 if err != nil {
132129 return fmt .Errorf ("failed to build loggers: %w" , err )
133130 }
134- logger = abtrlog .GetLogger ()
135131
136132 abtr := & abtr {
137133 opts : opts ,
138134 duration : defaultDuration ,
139135 reportPath : defaultReportPath ,
140136 interactive : defaultInteractive ,
137+ logger : infoLogger ,
141138 errorLogger : errorLogger ,
142139 }
143140
@@ -240,18 +237,14 @@ func (a *abtr) buildRunnerFlagSet() *pflag.FlagSet {
240237 return runnerFlagSet
241238}
242239
243- // run runs the input modules and starts generating traffic. Creates a traffic
244- // model based on the modules opertation settings. Aborts on SIGINT, SIGTERM
245- // or when the test duration runs out. Will immediately exit if any module
246- // returns an error from its call to Run().
247240func (a * abtr ) run (metadata module.Metadata ) error {
248- logger .Info ("Starting modules" )
241+ a . logger .Info ("Starting modules" )
249242
250- if err := startModules (metadata ); err != nil {
251- logger .Error (err , "Start failure" )
243+ if err := a . startModules (metadata ); err != nil {
244+ a . logger .Error (err , "Start failure" )
252245 return err
253246 }
254- logger .Info ("All modules started" )
247+ a . logger .Info ("All modules started" )
255248
256249 // Start signal interceptor for SIGINT and SIGTERM
257250 signalCtx , signalCancel := signal .NotifyContext (context .Background (), syscall .SIGINT , syscall .SIGTERM )
@@ -265,7 +258,7 @@ func (a *abtr) run(metadata module.Metadata) error {
265258 // Traffic context with a timeout of the test's >>> duration <<<
266259 timeoutCtx , timeoutCancel := context .WithTimeout (signalCtx , a .duration )
267260 defer timeoutCancel ()
268- logger .Info ("Traffic will run for: " + a .duration .String ())
261+ a . logger .Info ("Traffic will run for: " + a .duration .String ())
269262
270263 // The reporter runs in its own context to allow reporting to finalize separately from traffic and module
271264 // shutdown.
@@ -274,26 +267,26 @@ func (a *abtr) run(metadata module.Metadata) error {
274267 reporter .Start (reporterCtx )
275268
276269 sched := traffic .New (& traffic.Opts {
277- Logger : logger ,
270+ Logger : a . logger ,
278271 WorkerLimit : workerLimit .Value (),
279272 })
280273
281274 // Run traffic.
282275 if err := sched .Run (timeoutCtx , metadata , reporter ); err != nil {
283276 reporter .ReportError (err ) // Report is done in case of early traffic failure, to highlight issues in the TUI.
284- logger .Error (err , "Failed to start traffic" )
277+ a . logger .Error (err , "Failed to start traffic" )
285278 return err
286279 }
287280
288- logger .Info ("Awaiting completion (SIGINT/SIGTERM or duration timeout)" )
281+ a . logger .Info ("Awaiting completion (SIGINT/SIGTERM or duration timeout)" )
289282 select {
290283 case <- signalCtx .Done ():
291- logger .Info ("Got stop signal" )
284+ a . logger .Info ("Got stop signal" )
292285 // no need to call timeoutCancel() here since the traffic context is a child of the signal context,
293286 // so will be cancelled automatically.
294287 // timeoutCancel()
295288 case <- timeoutCtx .Done ():
296- logger .Info ("Deadline exceeded" )
289+ a . logger .Info ("Deadline exceeded" )
297290 // Needed to terminate the parent context, in case other's are reliant on it.
298291 signalCancel ()
299292 }
@@ -302,35 +295,35 @@ func (a *abtr) run(metadata module.Metadata) error {
302295 // to be returned at the end of the function.
303296 var stopErr error
304297 if stopErr = sched .Stop (); stopErr != nil {
305- logger .Error (stopErr , "Error when stopping traffic" )
298+ a . logger .Error (stopErr , "Error when stopping traffic" )
306299 stopErr = fmt .Errorf ("%w: traffic stop: %w" , ErrStopping , stopErr )
307300 }
308301
309302 // Now that traffic has been stopped, we can stop the reporter to allow it to finalise the report.
310303 reporterCancel ()
311304
312- logger .Info ("Stopping modules" )
305+ a . logger .Info ("Stopping modules" )
313306 for _ , m := range metadata {
314307 if moduleStopErr := m .Stop (); moduleStopErr != nil {
315- logger .Error (moduleStopErr , "Module stop reported an error" , "module" , m .Name ())
308+ a . logger .Error (moduleStopErr , "Module stop reported an error" , "module" , m .Name ())
316309 stopErr = errors .Join (stopErr , fmt .Errorf ("module %s stop: %w" , m .Name (), moduleStopErr ))
317310 }
318311 }
319312
320- logger .Info ("Finalising report" )
313+ a . logger .Info ("Finalising report" )
321314 reporterStopErr := reporter .Finalise ()
322315 if reporterStopErr != nil {
323- logger .Error (reporterStopErr , "Error when finalising report" )
316+ a . logger .Error (reporterStopErr , "Error when finalising report" )
324317 stopErr = errors .Join (stopErr , fmt .Errorf ("reporter stop: %w" , reporterStopErr ))
325318 }
326319
327320 return stopErr
328321}
329322
330- // Starts the input modules and logs any errors.
331- func startModules (meta []* module.Meta ) error {
323+ // startModules starts the input modules and logs any errors.
324+ func ( a * abtr ) startModules (meta []* module.Meta ) error {
332325 for _ , m := range meta {
333- logger .Info ("Starting" , "module" , m .Name ())
326+ a . logger .Info ("Starting" , "module" , m .Name ())
334327 if err := m .Run (); err != nil {
335328 return fmt .Errorf ("failed to start module %s: %w" , m .Name (), err )
336329 }
@@ -339,7 +332,7 @@ func startModules(meta []*module.Meta) error {
339332 return nil
340333}
341334
342- // Creates the reporter(s). In interactive mode a collection reporter is
335+ // setupReporter creates the reporter(s). In interactive mode a collection reporter is
343336// returned that fans out to both a YAML reporter and the live TUI reporter.
344337// trafficCancel is called by the interactive reporter when the user requests an early
345338// stop (e.g. Ctrl-C inside the TUI), triggering the same shutdown path as
@@ -352,6 +345,7 @@ func (a *abtr) setupReporter(
352345) report.Reporter {
353346 yamlR := yamlreport .New (& yamlreport.Opts {
354347 Path : a .reportPath ,
348+ Logger : a .logger ,
355349 ErrorLogger : a .errorLogger ,
356350 })
357351
@@ -369,3 +363,38 @@ func (a *abtr) setupReporter(
369363
370364 return yamlR
371365}
366+
367+ // setupLoggers initialises the info and error loggers from the provided options.
368+ // It returns the info logger, the error logger, and any error encountered.
369+ func setupLoggers (opts * Opts , verbosity int ) (logr.Logger , logr.Logger , error ) {
370+ errorFile , err := os .Create (opts .ErrorLogPath )
371+ if err != nil {
372+ return logr.Logger {}, logr.Logger {}, err
373+ }
374+
375+ var infoLogger logr.Logger
376+ if opts .InfoLogPath == "" {
377+ infoLogger = logr .Discard ()
378+ } else {
379+ infoFile , err := os .Create (opts .InfoLogPath ) //nolint:govet // shad
380+ if err != nil {
381+ return logr.Logger {}, logr.Logger {}, err
382+ }
383+
384+ infoLogger = zerologr .New (& zerologr.Opts {
385+ Output : infoFile ,
386+ Console : true ,
387+ Caller : true ,
388+ V : verbosity ,
389+ }).WithName ("abtr" )
390+ }
391+
392+ errorLogger := zerologr .New (& zerologr.Opts {
393+ Output : errorFile ,
394+ Console : true ,
395+ Caller : false ,
396+ V : verbosity ,
397+ })
398+
399+ return infoLogger , errorLogger , nil
400+ }
0 commit comments