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