From 7119d9ed52c44baf28936569b6d026ebe7dc196b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Andr=C3=A9=20Reuter?= Date: Wed, 13 Nov 2024 21:28:31 +0100 Subject: [PATCH] EasyBlock: Allow to disable logging to file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case an EasyBlock creates another instance of an EasyBlock (for example when dealing with Bundles), each instance will create new log file, which may stay open and cause issues down the line. To prevent this, add an option to the EasyBlock constructor to disable logging to files. Signed-off-by: Jan André Reuter --- easybuild/framework/easyblock.py | 17 +++++++++++---- test/framework/easyblock.py | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index df1866b6db..95cae7608b 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -40,6 +40,7 @@ * Maxime Boissonneault (Compute Canada) * Davide Vanzo (Vanderbilt University) * Caspar van Leeuwen (SURF) +* Jan Andre Reuter (Juelich Supercomputing Centre) """ import copy @@ -141,10 +142,11 @@ def extra_options(extra=None): # # INIT # - def __init__(self, ec): + def __init__(self, ec, create_log_file=True): """ Initialize the EasyBlock instance. :param ec: a parsed easyconfig file (EasyConfig instance) + :param log: a logger instance from another EasyBlock instance (optional) """ # keep track of original working directory, so we can go back there @@ -213,9 +215,13 @@ def __init__(self, ec): self.rpath_include_dirs = [] # logging + # each easyblock instance creates its own logger. + # however, this is not necessary if a logger is passed to the easyblock + # in that case, reuse the logger self.log = None self.logfile = None self.logdebug = build_option('debug') + self.create_log_file = create_log_file self.postmsg = '' # allow a post message to be set, which can be shown as last output self.current_step = None @@ -303,11 +309,11 @@ def _init_log(self): if self.log is not None: return - self.logfile = get_log_filename(self.name, self.version, add_salt=True) - fancylogger.logToFile(self.logfile, max_bytes=0) + if self.create_log_file: + self.logfile = get_log_filename(self.name, self.version, add_salt=True) + fancylogger.logToFile(self.logfile, max_bytes=0) self.log = fancylogger.getLogger(name=self.__class__.__name__, fname=False) - self.log.info(this_is_easybuild()) this_module = inspect.getmodule(self) @@ -323,6 +329,9 @@ def close_log(self): """ Shutdown the logger. """ + # only close log if we created a logfile + if not self.logfile: + return self.log.info("Closing log for application name %s version %s" % (self.name, self.version)) fancylogger.logToFile(self.logfile, enable=False) diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index 19218eca6a..fa4072a80c 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -28,6 +28,7 @@ @author: Jens Timmerman (Ghent University) @author: Kenneth Hoste (Ghent University) @author: Maxime Boissonneault (Compute Canada) +@author: Jan Andre Reuter (Juelich Supercomputing Centre) """ import os import re @@ -2895,6 +2896,41 @@ def run_sanity_check_step(sanity_check_paths, enhance_sanity_check): run_sanity_check_step({}, False) run_sanity_check_step({}, True) + def test_create_easyblock_without_logfile(self): + """ + Test creating an EasyBlock without a logfile. + This represents scenarios found in Bundle and QuantumESPRESSO, where an EasyBlock is + created within another EasyBlock. + """ + self.contents = '\n'.join([ + 'easyblock = "ConfigureMake"', + 'name = "pi"', + 'version = "3.14"', + 'homepage = "http://example.com"', + 'description = "test easyconfig"', + 'toolchain = SYSTEM', + ]) + self.writeEC() + # Ensure that the default case works as expected + eb = EasyBlock(EasyConfig(self.eb_file)) + self.assertNotEqual(eb.log, None) + self.assertNotEqual(eb.logfile, None) + # Get reference to the actual log instance and ensure that it works + # This is NOT eb.log, which represents a separate logger with a separate name. + file_log = fancylogger.getLogger(name=None) + self.assertNotEqual(getattr(file_log, 'logtofile_%s' % eb.logfile), False) + eb.close_log() + self.assertEqual(getattr(file_log, 'logtofile_%s' % eb.logfile), False) + + # Now, create another EasyBlock without a log file + eb_non_logfile = EasyBlock(EasyConfig(self.eb_file), create_log_file=False) + self.assertNotEqual(eb_non_logfile.log, None) + self.assertEqual(eb_non_logfile.logfile, None) + # Try to log something in it + eb_non_logfile.log.info("Test message") + + os.remove(eb.logfile) + def suite(): """ return all the tests in this file """