Skip to content
Snippets Groups Projects
Commit 6c2d8898 authored by xo30xoqa's avatar xo30xoqa
Browse files

Log output can now be routed to screen, to file, or to both

parent 2673d3ba
No related branches found
No related tags found
No related merge requests found
...@@ -30,23 +30,30 @@ function createdatadir(outdir::String, overwrite::Union{Bool,String}) ...@@ -30,23 +30,30 @@ function createdatadir(outdir::String, overwrite::Union{Bool,String})
end end
""" """
modellogger(loglevel, outdir) modellogger(loglevel, outdir, output="both")
Create a logger object that writes output both to screen and to a logfile. 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()`. This object is stored as `model.logger` and can then be used with `with_logger()`.
Note: requires [`createdatadir`](@ref) to be run first. 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 !isdir(outdir) && #TODO replace with exception
Base.error("$(outdir) does not exist. Call `createdatadir()` before `modellogger()`.") Base.error("$(outdir) does not exist. Call `createdatadir()` before `modellogger()`.")
loglevel == "debug" ? loglevel = Logging.Debug : loglevel == "debug" ? loglevel = Logging.Debug :
loglevel == "warn" ? loglevel = Logging.Warn : loglevel == "warn" ? loglevel = Logging.Warn :
loglevel == "info" ? loglevel = Logging.Info : loglevel == "info" ? loglevel = Logging.Info :
Base.error("Invalid loglevel $loglevel, should be debug/info/warn.") #TODO make exception 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? (output in ["file", "both"]) && (logfile = open(joinpath(outdir, LOGFILE), "w+"))
logfile = open(joinpath(outdir, LOGFILE), "w+") if output == "both"
TeeLogger(ConsoleLogger(logfile, loglevel), return TeeLogger(ConsoleLogger(logfile, loglevel),
ConsoleLogger(stdout, 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 end
""" """
......
...@@ -104,8 +104,11 @@ a helper function for `initialise()`. ...@@ -104,8 +104,11 @@ a helper function for `initialise()`.
function initmodel(settings::Dict{String, Any}) function initmodel(settings::Dict{String, Any})
#TODO catch exceptions and print them to the log file #TODO catch exceptions and print them to the log file
@debug "Initialising model object." @debug "Initialising model object."
createdatadir(settings["core.outdir"], settings["core.overwrite"]) createdatadir(settings["core.outdir"],
logger = modellogger(settings["core.loglevel"], settings["core.outdir"]) settings["core.overwrite"])
logger = modellogger(settings["core.loglevel"],
settings["core.outdir"],
settings["core.logoutput"])
with_logger(logger) do with_logger(logger) do
landscape = initlandscape(settings["world.landcovermap"], landscape = initlandscape(settings["world.landcovermap"],
settings["world.farmfieldsmap"]) settings["world.farmfieldsmap"])
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
configfile = "src/parameters.toml" # location of the configuration file configfile = "src/parameters.toml" # location of the configuration file
outdir = "results" # location and name of the output folder outdir = "results" # location and name of the output folder
overwrite = "ask" # overwrite the output directory? (true/false/"ask") 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 csvoutput = true # save collected data in CSV files
visualise = true # generate result graphs visualise = true # generate result graphs
storedata = true # keep collected data in memory storedata = true # keep collected data in memory
...@@ -17,9 +18,9 @@ figureformat = "pdf" # file format to use for graphical output ...@@ -17,9 +18,9 @@ figureformat = "pdf" # file format to use for graphical output
loglevel = "debug" # verbosity level: "debug", "info", "warn" loglevel = "debug" # verbosity level: "debug", "info", "warn"
processors = 2 # number of processors to use on parallel runs processors = 2 # number of processors to use on parallel runs
seed = 2 # seed value for the RNG (0 -> random value) seed = 2 # seed value for the RNG (0 -> random value)
# dates to start and end the simulation startdate = 2022-01-01 # first day of the simulation
startdate = 2022-01-01 #enddate = 2022-12-31 # last day of the simulation
enddate = 2022-12-31 enddate = 2022-03-31 # last day of the simulation (test value)
[world] [world]
landcovermap = "data/regions/jena-small/landcover.tif" # location of the landcover map landcovermap = "data/regions/jena-small/landcover.tif" # location of the landcover map
......
...@@ -19,13 +19,20 @@ end ...@@ -19,13 +19,20 @@ end
outdir = @param(core.outdir) outdir = @param(core.outdir)
Ps.createdatadir(outdir, @param(core.overwrite)) Ps.createdatadir(outdir, @param(core.overwrite))
@test isdir(outdir) @test isdir(outdir)
logger = Ps.modellogger(@param(core.loglevel), outdir)
@test_logs((:debug, "Setting up output directory results_testsuite."), @test_logs((:debug, "Setting up output directory results_testsuite."),
min_level=Logging.Debug, match_mode=:any, min_level=Logging.Debug, match_mode=:any,
Ps.saveinputfiles(model)) Ps.saveinputfiles(model))
@test isfile(joinpath(outdir, @param(world.landcovermap))) @test isfile(joinpath(outdir, @param(world.landcovermap)))
@test isfile(joinpath(outdir, @param(world.farmfieldsmap))) @test isfile(joinpath(outdir, @param(world.farmfieldsmap)))
@test isfile(joinpath(outdir, @param(core.configfile))) @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)) @test isfile(joinpath(outdir, Ps.LOGFILE))
# check whether the overwrite warning/protection works # check whether the overwrite warning/protection works
@test_logs((:warn, "Overwriting existing output directory $(outdir)."), @test_logs((:warn, "Overwriting existing output directory $(outdir)."),
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
[core] [core]
configfile = "test_parameters.toml" # location of the configuration file configfile = "test_parameters.toml" # location of the configuration file
outdir = "results_testsuite" # location and name of the output folder outdir = "results_testsuite" # location and name of the output folder
logoutput = "both"
overwrite = true # overwrite the output directory? (true/false/"ask") overwrite = true # overwrite the output directory? (true/false/"ask")
csvoutput = true # save collected data in CSV files csvoutput = true # save collected data in CSV files
visualise = true # generate result graphs visualise = true # generate result graphs
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment