From 6c2d8898ab2783abbd17c0cb26aec36a6de9be3e Mon Sep 17 00:00:00 2001 From: Daniel Vedder <daniel.vedder@idiv.de> Date: Wed, 5 Jun 2024 15:34:13 +0200 Subject: [PATCH] Log output can now be routed to screen, to file, or to both --- src/core/output.jl | 19 +++++++++++++------ src/core/simulation.jl | 7 +++++-- src/parameters.toml | 7 ++++--- test/io_tests.jl | 9 ++++++++- test/test_parameters.toml | 1 + 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/core/output.jl b/src/core/output.jl index 6d1fc2d..9a3eefe 100644 --- a/src/core/output.jl +++ b/src/core/output.jl @@ -30,23 +30,30 @@ function createdatadir(outdir::String, overwrite::Union{Bool,String}) end """ - modellogger(loglevel, outdir) + modellogger(loglevel, outdir, output="both") Create a logger object that writes output both to screen and to a logfile. This object is stored as `model.logger` and can then be used with `with_logger()`. Note: requires [`createdatadir`](@ref) to be run first. """ -function modellogger(loglevel::String, outdir::String) +function modellogger(loglevel::String, outdir::String, output::String="both") !isdir(outdir) && #TODO replace with exception Base.error("$(outdir) does not exist. Call `createdatadir()` before `modellogger()`.") loglevel == "debug" ? loglevel = Logging.Debug : loglevel == "warn" ? loglevel = Logging.Warn : loglevel == "info" ? loglevel = Logging.Info : Base.error("Invalid loglevel $loglevel, should be debug/info/warn.") #TODO make exception - #XXX If this is a parallel run, should we turn off logging to screen? - logfile = open(joinpath(outdir, LOGFILE), "w+") - TeeLogger(ConsoleLogger(logfile, loglevel), - ConsoleLogger(stdout, loglevel)) + (output in ["file", "both"]) && (logfile = open(joinpath(outdir, LOGFILE), "w+")) + if output == "both" + return TeeLogger(ConsoleLogger(logfile, loglevel), + ConsoleLogger(stdout, loglevel)) + elseif output == "file" + return ConsoleLogger(logfile, loglevel) + elseif output == "screen" + return ConsoleLogger(stdout, loglevel) + else + Base.error("Invalid log output target $output, should be file/screen/both.") + end end """ diff --git a/src/core/simulation.jl b/src/core/simulation.jl index dd454c7..646f47a 100644 --- a/src/core/simulation.jl +++ b/src/core/simulation.jl @@ -104,8 +104,11 @@ a helper function for `initialise()`. function initmodel(settings::Dict{String, Any}) #TODO catch exceptions and print them to the log file @debug "Initialising model object." - createdatadir(settings["core.outdir"], settings["core.overwrite"]) - logger = modellogger(settings["core.loglevel"], settings["core.outdir"]) + createdatadir(settings["core.outdir"], + settings["core.overwrite"]) + logger = modellogger(settings["core.loglevel"], + settings["core.outdir"], + settings["core.logoutput"]) with_logger(logger) do landscape = initlandscape(settings["world.landcovermap"], settings["world.farmfieldsmap"]) diff --git a/src/parameters.toml b/src/parameters.toml index 3a068c7..272bb25 100644 --- a/src/parameters.toml +++ b/src/parameters.toml @@ -10,6 +10,7 @@ configfile = "src/parameters.toml" # location of the configuration file outdir = "results" # location and name of the output folder overwrite = "ask" # overwrite the output directory? (true/false/"ask") +logoutput = "both" # log output to screen/file/both csvoutput = true # save collected data in CSV files visualise = true # generate result graphs storedata = true # keep collected data in memory @@ -17,9 +18,9 @@ figureformat = "pdf" # file format to use for graphical output loglevel = "debug" # verbosity level: "debug", "info", "warn" processors = 2 # number of processors to use on parallel runs seed = 2 # seed value for the RNG (0 -> random value) -# dates to start and end the simulation -startdate = 2022-01-01 -enddate = 2022-12-31 +startdate = 2022-01-01 # first day of the simulation +#enddate = 2022-12-31 # last day of the simulation +enddate = 2022-03-31 # last day of the simulation (test value) [world] landcovermap = "data/regions/jena-small/landcover.tif" # location of the landcover map diff --git a/test/io_tests.jl b/test/io_tests.jl index 214e549..71c8f0c 100644 --- a/test/io_tests.jl +++ b/test/io_tests.jl @@ -19,13 +19,20 @@ end outdir = @param(core.outdir) Ps.createdatadir(outdir, @param(core.overwrite)) @test isdir(outdir) - logger = Ps.modellogger(@param(core.loglevel), outdir) @test_logs((:debug, "Setting up output directory results_testsuite."), min_level=Logging.Debug, match_mode=:any, Ps.saveinputfiles(model)) @test isfile(joinpath(outdir, @param(world.landcovermap))) @test isfile(joinpath(outdir, @param(world.farmfieldsmap))) @test isfile(joinpath(outdir, @param(core.configfile))) + # test log output to screen/file/both + #XXX cannot test logger output due to https://github.com/JuliaLang/julia/issues/48456 + logger1 = Ps.modellogger(@param(core.loglevel), outdir, "screen") + @test !isfile(joinpath(outdir, Ps.LOGFILE)) + logger2 = Ps.modellogger(@param(core.loglevel), outdir, "file") + @test isfile(joinpath(outdir, Ps.LOGFILE)) + rm(joinpath(outdir, Ps.LOGFILE)) + logger3 = Ps.modellogger(@param(core.loglevel), outdir, "both") @test isfile(joinpath(outdir, Ps.LOGFILE)) # check whether the overwrite warning/protection works @test_logs((:warn, "Overwriting existing output directory $(outdir)."), diff --git a/test/test_parameters.toml b/test/test_parameters.toml index f34a20d..3a24704 100644 --- a/test/test_parameters.toml +++ b/test/test_parameters.toml @@ -8,6 +8,7 @@ [core] configfile = "test_parameters.toml" # location of the configuration file outdir = "results_testsuite" # location and name of the output folder +logoutput = "both" overwrite = true # overwrite the output directory? (true/false/"ask") csvoutput = true # save collected data in CSV files visualise = true # generate result graphs -- GitLab