Skip to content

Commit 9034b12

Browse files
authored
Set logger in Benchcab object (#281)
1 parent 52a557c commit 9034b12

File tree

2 files changed

+63
-45
lines changed

2 files changed

+63
-45
lines changed

src/benchcab/benchcab.py

+57-42
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""Contains the benchcab application class."""
55

66
import grp
7+
import logging
78
import os
89
import sys
910
from pathlib import Path
@@ -16,7 +17,6 @@
1617
from benchcab.environment_modules import EnvironmentModules, EnvironmentModulesInterface
1718
from benchcab.internal import get_met_forcing_file_names
1819
from benchcab.model import Model
19-
from benchcab.utils import get_logger
2020
from benchcab.utils.fs import mkdir, next_path
2121
from benchcab.utils.pbs import render_job_script
2222
from benchcab.utils.repo import create_repo
@@ -59,26 +59,37 @@ def __init__(
5959
self._spatial_tasks: list[spatial.SpatialTask] = []
6060

6161
# Get the logger object
62-
self.logger = get_logger()
62+
self._logger: Optional[logging.Logger] = None
6363
self._set_environment()
6464

65+
def set_logger(self, logger: logging.Logger):
66+
"""Set logger."""
67+
self._logger = logger
68+
69+
def _get_logger(self) -> logging.Logger:
70+
if self._logger is None:
71+
msg = "Logger uninitialised."
72+
raise RuntimeError(msg)
73+
return self._logger
74+
6575
def _set_environment(self):
6676
"""Sets environment variables on current user environment."""
6777
# Prioritize system binaries over externally set $PATHs (#220)
6878
os.environ["PATH"] = f"{':'.join(internal.SYSTEM_PATHS)}:{os.environ['PATH']}"
6979

7080
def _validate_environment(self, project: str, modules: list):
7181
"""Performs checks on current user environment."""
82+
logger = self._get_logger()
7283
if not self.validate_env:
7384
return
7485

7586
if "gadi.nci" not in internal.NODENAME:
76-
self.logger.error("benchcab is currently implemented only on Gadi")
87+
logger.error("benchcab is currently implemented only on Gadi")
7788
sys.exit(1)
7889

7990
namelist_dir = Path(internal.NAMELIST_DIR)
8091
if not namelist_dir.exists():
81-
self.logger.error(
92+
logger.error(
8293
"Cannot find 'namelists' directory in current working directory"
8394
)
8495
sys.exit(1)
@@ -101,7 +112,7 @@ def _validate_environment(self, project: str, modules: list):
101112

102113
for modname in modules:
103114
if not self.modules_handler.module_is_avail(modname):
104-
self.logger.error(f"Module ({modname}) is not available.")
115+
logger.error(f"Module ({modname}) is not available.")
105116
sys.exit(1)
106117

107118
system_paths = os.getenv("PATH").split(":")[: len(internal.SYSTEM_PATHS)]
@@ -119,14 +130,12 @@ def _validate_environment(self, project: str, modules: list):
119130
for site_id in all_site_ids:
120131
paths = list(internal.MET_DIR.glob(f"{site_id}*"))
121132
if not paths:
122-
self.logger.error(
123-
f"Failed to infer met file for site id '{site_id}' in "
124-
)
125-
self.logger.error(f"{internal.MET_DIR}.")
133+
logger.error(f"Failed to infer met file for site id '{site_id}' in ")
134+
logger.error(f"{internal.MET_DIR}.")
126135

127136
sys.exit(1)
128137
if len(paths) > 1:
129-
self.logger.error(
138+
logger.error(
130139
f"Multiple paths infered for site id: '{site_id}' in {internal.MET_DIR}."
131140
)
132141
sys.exit(1)
@@ -174,18 +183,17 @@ def validate_config(self, config_path: str):
174183

175184
def fluxsite_submit_job(self, config_path: str, skip: list[str]) -> None:
176185
"""Submits the PBS job script step in the fluxsite test workflow."""
186+
logger = self._get_logger()
177187
config = self._get_config(config_path)
178188
self._validate_environment(project=config["project"], modules=config["modules"])
179189
if self.benchcab_exe_path is None:
180190
msg = "Path to benchcab executable is undefined."
181191
raise RuntimeError(msg)
182192

183193
job_script_path = Path(internal.QSUB_FNAME)
184-
self.logger.info(
185-
"Creating PBS job script to run fluxsite tasks on compute nodes"
186-
)
194+
logger.info("Creating PBS job script to run fluxsite tasks on compute nodes")
187195

188-
self.logger.info(f"job_script_path = {job_script_path}")
196+
logger.info(f"job_script_path = {job_script_path}")
189197

190198
with job_script_path.open("w", encoding="utf-8") as file:
191199
contents = render_job_script(
@@ -204,92 +212,97 @@ def fluxsite_submit_job(self, config_path: str, skip: list[str]) -> None:
204212
capture_output=True,
205213
)
206214
except CalledProcessError as exc:
207-
self.logger.error("when submitting job to NCI queue, details to follow")
208-
self.logger.error(exc.output)
215+
logger.error("when submitting job to NCI queue, details to follow")
216+
logger.error(exc.output)
209217
raise
210218

211-
self.logger.info(f"PBS job submitted: {proc.stdout.strip()}")
212-
self.logger.info("CABLE log file for each task is written to:")
213-
self.logger.info(f"{internal.FLUXSITE_DIRS['LOG']}/<task_name>_log.txt")
214-
self.logger.info("The CABLE standard output for each task is written to:")
215-
self.logger.info(f"{internal.FLUXSITE_DIRS['TASKS']}/<task_name>/out.txt")
216-
self.logger.info("The NetCDF output for each task is written to:")
217-
self.logger.info(f"{internal.FLUXSITE_DIRS['OUTPUT']}/<task_name>_out.nc")
219+
logger.info(f"PBS job submitted: {proc.stdout.strip()}")
220+
logger.info("CABLE log file for each task is written to:")
221+
logger.info(f"{internal.FLUXSITE_DIRS['LOG']}/<task_name>_log.txt")
222+
logger.info("The CABLE standard output for each task is written to:")
223+
logger.info(f"{internal.FLUXSITE_DIRS['TASKS']}/<task_name>/out.txt")
224+
logger.info("The NetCDF output for each task is written to:")
225+
logger.info(f"{internal.FLUXSITE_DIRS['OUTPUT']}/<task_name>_out.nc")
218226

219227
def checkout(self, config_path: str):
220228
"""Endpoint for `benchcab checkout`."""
229+
logger = self._get_logger()
221230
config = self._get_config(config_path)
222231
self._validate_environment(project=config["project"], modules=config["modules"])
223232

224233
mkdir(internal.SRC_DIR, exist_ok=True)
225234

226-
self.logger.info("Checking out repositories...")
235+
logger.info("Checking out repositories...")
227236
rev_number_log = ""
228237

229238
for model in self._get_models(config):
230239
try:
231240
model.repo.checkout()
232241
except Exception:
233242
msg = "Try using `benchcab clean realisations` first"
234-
self.logger.error(
243+
logger.error(
235244
"Model checkout failed, probably due to existing realisation name"
236245
)
237246
raise FileExistsError(msg)
238247
rev_number_log += f"{model.name}: {model.repo.get_revision()}\n"
239248

240249
rev_number_log_path = next_path("rev_number-*.log")
241-
self.logger.info(f"Writing revision number info to {rev_number_log_path}")
250+
logger.info(f"Writing revision number info to {rev_number_log_path}")
242251
with rev_number_log_path.open("w", encoding="utf-8") as file:
243252
file.write(rev_number_log)
244253

245254
def build(self, config_path: str, mpi=False):
246255
"""Endpoint for `benchcab build`."""
256+
logger = self._get_logger()
247257
config = self._get_config(config_path)
248258
self._validate_environment(project=config["project"], modules=config["modules"])
249259

250260
for repo in self._get_models(config):
251261
if repo.build_script:
252262

253-
self.logger.info("Compiling CABLE using custom build script for")
254-
self.logger.info(f"realisation {repo.name}")
263+
logger.info("Compiling CABLE using custom build script for")
264+
logger.info(f"realisation {repo.name}")
255265
repo.custom_build(modules=config["modules"])
256266

257267
else:
258268
build_mode = "serial and MPI" if mpi else "serial"
259-
self.logger.info(
269+
logger.info(
260270
f"Compiling CABLE {build_mode} for realisation {repo.name}..."
261271
)
262272
repo.build(modules=config["modules"], mpi=mpi)
263-
self.logger.info(f"Successfully compiled CABLE for realisation {repo.name}")
273+
logger.info(f"Successfully compiled CABLE for realisation {repo.name}")
264274

265275
def fluxsite_setup_work_directory(self, config_path: str):
266276
"""Endpoint for `benchcab fluxsite-setup-work-dir`."""
277+
logger = self._get_logger()
267278
config = self._get_config(config_path)
268279
self._validate_environment(project=config["project"], modules=config["modules"])
269280

270-
self.logger.info("Setting up run directory tree for fluxsite tests...")
281+
logger.info("Setting up run directory tree for fluxsite tests...")
271282
setup_fluxsite_directory_tree()
272-
self.logger.info("Setting up tasks...")
283+
logger.info("Setting up tasks...")
273284
for task in self._get_fluxsite_tasks(config):
274285
task.setup_task()
275-
self.logger.info("Successfully setup fluxsite tasks")
286+
logger.info("Successfully setup fluxsite tasks")
276287

277288
def fluxsite_run_tasks(self, config_path: str):
278289
"""Endpoint for `benchcab fluxsite-run-tasks`."""
290+
logger = self._get_logger()
279291
config = self._get_config(config_path)
280292
self._validate_environment(project=config["project"], modules=config["modules"])
281293
tasks = self._get_fluxsite_tasks(config)
282294

283-
self.logger.info("Running fluxsite tasks...")
295+
logger.info("Running fluxsite tasks...")
284296
if config["fluxsite"]["multiprocess"]:
285297
ncpus = config["fluxsite"]["pbs"]["ncpus"]
286298
fluxsite.run_tasks_in_parallel(tasks, n_processes=ncpus)
287299
else:
288300
fluxsite.run_tasks(tasks)
289-
self.logger.info("Successfully ran fluxsite tasks")
301+
logger.info("Successfully ran fluxsite tasks")
290302

291303
def fluxsite_bitwise_cmp(self, config_path: str):
292304
"""Endpoint for `benchcab fluxsite-bitwise-cmp`."""
305+
logger = self._get_logger()
293306
config = self._get_config(config_path)
294307
self._validate_environment(project=config["project"], modules=config["modules"])
295308

@@ -302,13 +315,13 @@ def fluxsite_bitwise_cmp(self, config_path: str):
302315
self._get_fluxsite_tasks(config)
303316
)
304317

305-
self.logger.info("Running comparison tasks...")
318+
logger.info("Running comparison tasks...")
306319
if config["fluxsite"]["multiprocess"]:
307320
ncpus = config["fluxsite"]["pbs"]["ncpus"]
308321
run_comparisons_in_parallel(comparisons, n_processes=ncpus)
309322
else:
310323
run_comparisons(comparisons)
311-
self.logger.info("Successfully ran comparison tasks")
324+
logger.info("Successfully ran comparison tasks")
312325

313326
def fluxsite(self, config_path: str, no_submit: bool, skip: list[str]):
314327
"""Endpoint for `benchcab fluxsite`."""
@@ -331,28 +344,30 @@ def clean(self, config_path: str, clean_option: str):
331344

332345
def spatial_setup_work_directory(self, config_path: str):
333346
"""Endpoint for `benchcab spatial-setup-work-dir`."""
347+
logger = self._get_logger()
334348
config = self._get_config(config_path)
335349
self._validate_environment(project=config["project"], modules=config["modules"])
336350

337-
self.logger.info("Setting up run directory tree for spatial tests...")
351+
logger.info("Setting up run directory tree for spatial tests...")
338352
setup_spatial_directory_tree()
339-
self.logger.info("Setting up tasks...")
353+
logger.info("Setting up tasks...")
340354
try:
341355
payu_config = config["spatial"]["payu"]["config"]
342356
except KeyError:
343357
payu_config = None
344358
for task in self._get_spatial_tasks(config):
345359
task.setup_task(payu_config=payu_config)
346-
self.logger.info("Successfully setup spatial tasks")
360+
logger.info("Successfully setup spatial tasks")
347361

348362
def spatial_run_tasks(self, config_path: str):
349363
"""Endpoint for `benchcab spatial-run-tasks`."""
364+
logger = self._get_logger()
350365
config = self._get_config(config_path)
351366
self._validate_environment(project=config["project"], modules=config["modules"])
352367

353-
self.logger.info("Running spatial tasks...")
368+
logger.info("Running spatial tasks...")
354369
spatial.run_tasks(tasks=self._get_spatial_tasks(config))
355-
self.logger.info("Successfully dispatched payu jobs")
370+
logger.info("Successfully dispatched payu jobs")
356371

357372
def spatial(self, config_path: str, skip: list):
358373
"""Endpoint for `benchcab spatial`."""

src/benchcab/main.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
from benchcab.utils import get_logger
99

1010

11-
def parse_and_dispatch(parser):
11+
def parse_and_dispatch(parser, app):
1212
"""Parse arguments for the script and dispatch to the correct function.
1313
1414
Args:
1515
----
1616
parser : argparse.ArgumentParser
1717
Parser object.
18+
app : Benchcab
19+
Benchcab application instance.
1820
1921
"""
2022
args = vars(parser.parse_args(sys.argv[1:] if sys.argv[1:] else ["-h"]))
@@ -26,7 +28,8 @@ def parse_and_dispatch(parser):
2628
_ = args.pop("verbose")
2729

2830
# We just need to instantiate this with the desired level
29-
get_logger(level=log_level)
31+
logger = get_logger(level=log_level)
32+
app.set_logger(logger)
3033

3134
func = args.pop("func")
3235
func(**args)
@@ -39,7 +42,7 @@ def main():
3942
"""
4043
app = Benchcab(benchcab_exe_path=shutil.which(sys.argv[0]))
4144
parser = generate_parser(app)
42-
parse_and_dispatch(parser)
45+
parse_and_dispatch(parser, app)
4346

4447

4548
if __name__ == "__main__":

0 commit comments

Comments
 (0)