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