1    	import logging
2    	import logging.handlers
3    	
4    	LOGGER_NAMES = [
5    	    "pcs.daemon",
6    	    "pcs.daemon.scheduler",
7    	    "tornado.application",
8    	    "tornado.access",
9    	    "tornado.general",
10   	]
11   	
12   	# pylint:disable=invalid-name
13   	pcsd = logging.getLogger("pcs.daemon")
14   	
15   	
16   	def from_external_source(level, created: float, usecs: int, message, group_id):
17   	    record = pcsd.makeRecord(
18   	        name=pcsd.name,
19   	        level=level,
20   	        # Information about stack frame is not needed here. Values are
21   	        # inspired by the code of the logging module.
22   	        fn="(external)",
23   	        lno=0,
24   	        # Message from ruby does not need args.
25   	        msg=message,
26   	        args=tuple(),
27   	        # The exception information makes not sense here.
28   	        exc_info=None,
29   	    )
30   	
31   	    # A value of attribute relativelyCreated is in logging module calculated by
32   	    # this way:
33   	    # self.relativeCreated = (self.created - _startTime) * 1000
34   	    # To update it, we need to reduce it by difference between current value
35   	    # of attribute created (which is newer, so higher) and the correct one
36   	    # (which comes from an external source)
37   	    record.relativeCreated -= (record.created - created) * 1000
38   	    record.created = created
39   	    record.msec = usecs // 1000
40   	    record.pcsd_group_id = str(group_id).zfill(5)
41   	    pcsd.handle(record)
42   	
43   	
44   	class Formatter(logging.Formatter):
45   	    default_time_format = "%Y-%m-%dT%H:%M:%S"
46   	    # It produces `datetime.milliseconds`
47   	    default_msec_format = "%s.%03d"
48   	
49   	    def __init__(self):
50   	        super().__init__(
51   	            fmt="{levelname[0]}, [{asctime} #{pcsd_group_id}]"
52   	            " {levelname:>8s} -- : {message}",
53   	            datefmt=None,
54   	            style="{",
55   	        )
56   	
57   	    def format(self, record):
58   	        # Non-external records, which are currently the minority, needs to be
59   	        # extended by group_id (see init arugument fmt and function
60   	        # from_external_source).
61   	        if not hasattr(record, "pcsd_group_id"):
62   	            record.pcsd_group_id = "00000"
63   	        return super().format(record)
64   	
65   	
66   	def setup(log_file):
67   	    handler = logging.handlers.WatchedFileHandler(log_file, encoding="utf8")
68   	    handler.setFormatter(Formatter())
69   	    handler.setLevel(logging.INFO)
70   	
71   	    for logger_name in LOGGER_NAMES:
72   	        pcsd_log = logging.getLogger(logger_name)
73   	        pcsd_log.addHandler(handler)
74   	        pcsd_log.setLevel(logging.INFO)
75   	
76   	
77   	def enable_debug():
78   	    # Debug messages won't be written if we call setLevel(logging.DEBUG) on the
79   	    # handler when loggers itself have an higher level. So the level is set to
80   	    # the loggers. Our handler has the implicit NOTSET level and there is no
81   	    # reason to make it more complicated currently.
82   	    for logger_name in LOGGER_NAMES:
83   	        logger = logging.getLogger(logger_name)
CID (unavailable; MK=2848ef3bf4172603bf3396946935c06f) (#1 of 1): Excessive log level (SIGMA.debug_logging_enabled):
(1) Event Sigma main event: The Python application has been configured to create excessive logs using a `DEBUG` log level. Excessive logging can expose sensitive information in log files.
(2) Event remediation: The log level of a production Python application should be set to `ERROR`, `WARN`, or `INFO`, instead of `DEBUG`.
84   	        logger.setLevel(logging.DEBUG)
85   	        for handler in logger.handlers:
86   	            handler.setLevel(logging.DEBUG)
87