aboutsummaryrefslogtreecommitdiffstats
path: root/fg21sim/utils/logging.py
blob: c0746e81872a39f1acd12c2da1d6f9562884cbb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# Copyright (c) 2016-2017 Weitian LI <weitian@aaronly.me>
# MIT license

"""
Logging utilities.
"""

import os
import sys
import logging
from logging import FileHandler, StreamHandler


logger = logging.getLogger(__name__)


def setup_logging(dict_config=None, level=None, stream=None, logfile=None):
    """Setup the logging.

    This will override the logging configurations in the config file
    if specified (e.g., by command line arguments).

    Parameters
    ----------
    dict_config : dict
        Dict of logging configurations specified in the config file.
        If this parameter specified, the logging will be reconfigured.
    level : str;
        Override the existing log level
    stream : string; "stderr", "stdout", or ""
        This controls where the log messages go to.
        If not None, then override the old ``StreamHandler`` settings;
        if ``stream=""``, then disable the ``StreamHandler``.
    logfile : str
        Specify the file where the log messages go to.
        If ``logfile=""``, then disable the ``FileHandler``.

    NOTE
    ----
    If the logging already has ``StreamHandler`` or ``FileHandler``
    configured, then the old handler will be **replaced** (i.e., remove
    the old one, then add the new one).
    """
    # Default file open mode for logging to file
    filemode = "a"
    root_logger = logging.getLogger()
    #
    if dict_config:
        # XXX/NOTE:
        # ``basicConfig()`` does NOT accept parameter ``filemode`` if the
        # corresponding parameter ``filename`` NOT specified.
        filemode = dict_config.pop("filemode", filemode)
        # Clear existing handlers, otherwise further "basicConfig" calls
        # will be ignored
        for handler in root_logger.handlers:
            handler.close()
            root_logger.removeHandler(handler)
        # Initialize/reconfigure the logging, which will automatically
        # create a ``Formatter`` for handlers if necessary, and adding
        # the handlers to the "root" logger.
        logging.basicConfig(**dict_config)
    #
    if os.environ.get("DEBUG_FG21SIM"):
        print("DEBUG: Force 'DEBUG' logging level", file=sys.stderr)
        level = "DEBUG"
    if level is not None:
        level_int = getattr(logging, level.upper(), None)
        if not isinstance(level_int, int):
            raise ValueError("invalid log level: %s" % level)
        root_logger.setLevel(level_int)
    #
    # Configured logging has at least one handler with configured formatter.
    # Store the existing formatter to preserve the configured format styles.
    formatter = root_logger.handlers[0].formatter
    #
    if stream is None:
        pass
    elif stream in ["", "stderr", "stdout"]:
        for handler in root_logger.handlers:
            if isinstance(handler, StreamHandler):
                # remove old ``StreamHandler``
                handler.close()
                root_logger.removeHandler(handler)
        if stream == "":
            # ``StreamHandler`` already disabled
            pass
        else:
            # Add new ``StreamHandler``
            handler = StreamHandler(getattr(sys, stream))
            handler.setFormatter(formatter)
            root_logger.addHandler(handler)
    else:
        raise ValueError("invalid stream: %s" % stream)
    #
    if logfile is not None:
        for handler in root_logger.handlers:
            if isinstance(handler, FileHandler):
                filemode = handler.mode
                # remove old ``FileHandler``
                handler.close()
                root_logger.removeHandler(handler)
        if logfile == "":
            # ``FileHandler`` already disabled
            pass
        else:
            # Add new ``FileHandler``
            handler = FileHandler(logfile, mode=filemode)
            handler.setFormatter(formatter)
            root_logger.addHandler(handler)
    logger.info("Set up logging.")