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