From 4a7ebacdb1082dde669d8dc1ecb4a4788a1d1bcc Mon Sep 17 00:00:00 2001 From: Victor Holanda Rusu Date: Wed, 20 Jun 2018 15:37:40 +0200 Subject: [PATCH 1/4] Adding username and group to perf logging This PR attempts to add the username and group to perf logging. This is especially good for grafana logging. This should capture the name and primary group of the user that has executed reframe. REMARKS: * capturing the username and group is not portable across OSes * The fields were updated inside the `_update_check_extras`, but they could be set during the initialization of the `LoggerAdapter`. --- reframe/core/logging.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/reframe/core/logging.py b/reframe/core/logging.py index cc165d0924..acb5b431b0 100644 --- a/reframe/core/logging.py +++ b/reframe/core/logging.py @@ -343,6 +343,9 @@ def __init__(self, logger=None, check=None): 'check_perf_ref': None, 'check_perf_lower_thres': None, 'check_perf_upper_thres': None, + 'check_perf_upper_thres': None, + 'username': None, + 'group': None, 'check_tags': None, 'version': reframe.VERSION, } @@ -378,6 +381,24 @@ def _update_check_extras(self): if self.check.job: self.extra['check_jobid'] = self.check.job.jobid + try: + import pwd + self.extra['username'] = pwd.getpwuid(os.geteuid()).pw_name + except: + try: + import getpass + self.extra['username'] = getpass.getuser() + except: + pass + + try: + import grp + import pwd + gid = pwd.getpwnam(self.extra['username']).pw_gid + self.extra['group'] = grp.getgrgid(gid).gr_name + except: + pass + def log_performance(self, level, tag, value, ref, low_thres, upper_thres, msg=None): From d99d6fe1d921d5ee495cf87c5fa5b2c06591d30c Mon Sep 17 00:00:00 2001 From: Victor Holanda Rusu Date: Wed, 20 Jun 2018 16:03:08 +0200 Subject: [PATCH 2/4] Fix PR remark --- reframe/core/logging.py | 1 - 1 file changed, 1 deletion(-) diff --git a/reframe/core/logging.py b/reframe/core/logging.py index acb5b431b0..c4a71e2026 100644 --- a/reframe/core/logging.py +++ b/reframe/core/logging.py @@ -343,7 +343,6 @@ def __init__(self, logger=None, check=None): 'check_perf_ref': None, 'check_perf_lower_thres': None, 'check_perf_upper_thres': None, - 'check_perf_upper_thres': None, 'username': None, 'group': None, 'check_tags': None, From e4b3ac212fb1d812d2dae56055dc527d9bba8a8a Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Thu, 21 Jun 2018 17:08:35 +0200 Subject: [PATCH 3/4] Address PR comments --- reframe/core/logging.py | 25 ++++--------------------- reframe/frontend/cli.py | 2 +- reframe/frontend/printer.py | 2 +- reframe/utility/os_ext.py | 28 +++++++++++++++++++++++++++- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/reframe/core/logging.py b/reframe/core/logging.py index c4a71e2026..7ed149c0fe 100644 --- a/reframe/core/logging.py +++ b/reframe/core/logging.py @@ -12,6 +12,7 @@ import reframe import reframe.core.debug as debug +import reframe.utility.os_ext as os_ext from reframe.core.exceptions import ConfigError, LoggingError @@ -343,8 +344,8 @@ def __init__(self, logger=None, check=None): 'check_perf_ref': None, 'check_perf_lower_thres': None, 'check_perf_upper_thres': None, - 'username': None, - 'group': None, + 'osuser': os_ext.osuser() or '', + 'osgroup': os_ext.osgroup() or '', 'check_tags': None, 'version': reframe.VERSION, } @@ -380,24 +381,6 @@ def _update_check_extras(self): if self.check.job: self.extra['check_jobid'] = self.check.job.jobid - try: - import pwd - self.extra['username'] = pwd.getpwuid(os.geteuid()).pw_name - except: - try: - import getpass - self.extra['username'] = getpass.getuser() - except: - pass - - try: - import grp - import pwd - gid = pwd.getpwnam(self.extra['username']).pw_gid - self.extra['group'] = grp.getgrgid(gid).gr_name - except: - pass - def log_performance(self, level, tag, value, ref, low_thres, upper_thres, msg=None): @@ -408,7 +391,7 @@ def log_performance(self, level, tag, value, ref, self.extra['check_perf_lower_thres'] = low_thres self.extra['check_perf_upper_thres'] = upper_thres if msg is None: - msg = 'sent by ' + os.environ['USER'] + msg = 'sent by ' + self.extra['osuser'] self.log(level, msg) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index b70659f4e7..816702d4cf 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -336,7 +336,7 @@ def main(): # Print command line printer.info('Command line: %s' % ' '.join(sys.argv)) printer.info('Reframe version: ' + reframe.VERSION) - printer.info('Launched by user: ' + os.environ['USER']) + printer.info('Launched by user: ' + (os_ext.osuser() or '')) printer.info('Launched on host: ' + socket.gethostname()) # Print important paths diff --git a/reframe/frontend/printer.py b/reframe/frontend/printer.py index 442644fa45..407d240616 100644 --- a/reframe/frontend/printer.py +++ b/reframe/frontend/printer.py @@ -118,7 +118,7 @@ def warning(self, msg): def error(self, msg): msg = AnsiColorizer.colorize('%s: %s' % (sys.argv[0], msg), AnsiColorizer.red) - self._logger.error('%s: %s' % (sys.argv[0], msg)) + self._logger.error(msg) def log_config(self, options): opt_list = [' %s=%s' % (attr, val) diff --git a/reframe/utility/os_ext.py b/reframe/utility/os_ext.py index 1330b4aaa8..befb2ec5ae 100644 --- a/reframe/utility/os_ext.py +++ b/reframe/utility/os_ext.py @@ -2,6 +2,8 @@ # OS and shell utility functions # +import getpass +import grp import os import re import shlex @@ -13,7 +15,6 @@ from reframe.core.exceptions import (ReframeError, SpawnedProcessError, SpawnedProcessTimeout) -from reframe.core.logging import getlogger def run_command(cmd, check=False, timeout=None, shell=False): @@ -63,6 +64,9 @@ def run_command_async(cmd, stderr=subprocess.PIPE, shell=False, **popen_args): + # Import logger here to avoid unnecessary circular dependencies + from reframe.core.logging import getlogger + getlogger().debug('executing OS command: ' + cmd) if not shell: cmd = shlex.split(cmd) @@ -75,6 +79,28 @@ def run_command_async(cmd, **popen_args) +def osuser(): + """Return the name of the current OS user. + + If the name cannot be retrieved, :class:`None` will be returned. + """ + try: + return getpass.getuser() + except BaseException: + return None + + +def osgroup(): + """Return the group name of the current OS user. + + If the name cannot be retrieved, :class:`None` will be returned. + """ + try: + return grp.getgrgid(os.getgid()).gr_name + except KeyError: + return None + + def copytree(src, dst, symlinks=False, ignore=None, copy_function=shutil.copy2, ignore_dangling_symlinks=False): """Same as shutil.copytree() but valid also if 'dst' exists. From 10e3694de0976fdd38f5126a3f3758a304749aea Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Thu, 21 Jun 2018 17:37:57 +0200 Subject: [PATCH 4/4] Document osuser and osgroup logging attributes --- docs/running.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/running.rst b/docs/running.rst index 58508477bd..911ada88ea 100644 --- a/docs/running.rst +++ b/docs/running.rst @@ -567,6 +567,8 @@ All handlers accept the following set of attributes (keys) in their configuratio - ``check_stagedir``: The stage directory associated with the currently executing test. - ``check_system``: The host system where this test is currently executing. - ``check_tags``: The tags associated with this test. + - ``osuser``: The name of the OS user running ReFrame. + - ``osgroup``: The group name of the OS user running ReFrame. - ``version``: The ReFrame version. * ``datefmt`` (default: ``'%FT%T'``) The format that will be used for outputting timestamps (i.e., the ``%(asctime)s`` field).