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