1# Copyright (c) 2022 Nordic Semiconductor ASA
2# SPDX-License-Identifier: Apache-2.0
3
4'''
5Common code used when logging that is needed by multiple modules.
6'''
7
8import logging
9import os
10import platform
11import shlex
12
13_WINDOWS = platform.system() == 'Windows'
14
15
16def log_command(logger, msg, args):
17    '''Platform-independent helper for logging subprocess invocations.
18    Will log a command string that can be copy/pasted into a POSIX
19    shell on POSIX platforms. This is not available on Windows, so
20    the entire args array is logged instead.
21
22    :param logger: logging.Logger to use
23    :param msg: message to associate with the command
24    :param args: argument list as passed to subprocess module
25    '''
26    logger = logging.getLogger("twister")
27    logger.setLevel(logging.DEBUG)
28
29    msg = f'{msg}: %s'
30    if _WINDOWS:
31        logger.debug(msg, str(args))
32    else:
33        logger.debug(msg, shlex.join(args))
34
35def setup_logging(outdir, log_file, log_level, timestamps):
36    logger = logging.getLogger("twister")
37    logger.setLevel(logging.DEBUG)
38
39    # create file handler which logs even debug messages
40    if log_file:
41        file_handler = logging.FileHandler(log_file)
42    else:
43        file_handler = logging.FileHandler(os.path.join(outdir, "twister.log"))
44
45    file_handler.setLevel(logging.DEBUG)
46
47    # create console handler with a higher log level
48    console_handler = logging.StreamHandler()
49    console_handler.setLevel(getattr(logging, log_level))
50
51    # create formatter and add it to the handlers
52    if timestamps:
53        formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
54    else:
55        formatter = logging.Formatter("%(levelname)-7s - %(message)s")
56
57    formatter_file = logging.Formatter(
58        "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
59    )
60    console_handler.setFormatter(formatter)
61    file_handler.setFormatter(formatter_file)
62
63    # add the handlers to logger
64    logger.addHandler(console_handler)
65    logger.addHandler(file_handler)
66
67
68def close_logging():
69    logger = logging.getLogger("twister")
70    handlers = logger.handlers[:]
71
72    for handler in handlers:
73        logger.removeHandler(handler)
74        handler.close()
75
76    loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict]
77    for logg in loggers:
78        handls = logg.handlers[:]
79        for handl in handls:
80            logg.removeHandler(handl)
81            handl.close()
82