/usr/lib/python3/dist-packages/systemimage/logging.py is in system-image-common 2.2-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 111 112 113 114 115 116 117 118 119 120 121 122 | # Copyright (C) 2013-2014 Canonical Ltd.
# Author: Barry Warsaw <barry@ubuntu.com>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Set up logging, both for main script execution and the test suite."""
__all__ = [
'debug_logging',
'initialize',
]
import os
import sys
import stat
import logging
from contextlib import contextmanager
from systemimage.config import config
from systemimage.helpers import makedirs
DATE_FMT = '%b %d %H:%M:%S %Y'
MSG_FMT = '[{name}] {asctime} ({process:d}) {message}'
LOGFILE_PERMISSIONS = stat.S_IRUSR | stat.S_IWUSR
# We want to support {}-style logging for all systemimage child loggers. One
# way to do this is with a LogRecord factory, but to play nice with third
# party loggers which might be using %-style, we have to make sure that we use
# the default factory for everything else.
#
# This actually isn't the best way to do this because it still makes a global
# change and we don't know how this will interact with other third party
# loggers. A marginally better way to do this is to pass class instances to
# the logging calls. Those instances would have a __str__() method that does
# the .format() conversion. The problem with that is that it's a bit less
# convenient to make the logging calls because you can't pass strings
# directly. One such suggestion at <http://tinyurl.com/pjjwjxq> is to import
# the class as __ (i.e. double underscore) so your logging calls would look
# like: log.error(__('Message with {} {}'), foo, bar)
class FormattingLogRecord(logging.LogRecord):
def __init__(self, name, *args, **kws):
logger_path = name.split('.')
self._use_format = (logger_path[0] == 'systemimage')
super().__init__(name, *args, **kws)
def getMessage(self):
if self._use_format:
msg = str(self.msg)
if self.args:
msg = msg.format(*self.args)
return msg
else:
return super().getMessage()
def initialize(*, verbosity=0):
"""Initialize the loggers."""
level = {
0: logging.ERROR,
1: logging.INFO,
2: logging.DEBUG,
3: logging.CRITICAL,
}.get(verbosity, logging.ERROR)
level = min(level, config.system.loglevel)
# Make sure our library's logging uses {}-style messages.
logging.setLogRecordFactory(FormattingLogRecord)
# Now configure the application level logger based on the ini file.
log = logging.getLogger('systemimage')
# Make sure the log directory exists.
makedirs(os.path.dirname(config.system.logfile))
# touch(1) - but preserve in case file already exists.
with open(config.system.logfile, 'a', encoding='utf-8'):
pass
os.chmod(config.system.logfile, LOGFILE_PERMISSIONS)
# Our handler will output in UTF-8 using {} style logging.
handler = logging.FileHandler(config.system.logfile, encoding='utf-8')
handler.setLevel(level)
formatter = logging.Formatter(style='{', fmt=MSG_FMT, datefmt=DATE_FMT)
handler.setFormatter(formatter)
log.addHandler(handler)
log.propagate = False
# If we want more verbosity, add a stream handler.
if verbosity == 0:
# Set the log level.
log.setLevel(level)
return
handler = logging.StreamHandler(stream=sys.stderr)
handler.setLevel(level)
handler.setFormatter(formatter)
log.addHandler(handler)
# Set the overall level on the log object to the minimum level.
log.setLevel(level)
# Please be quiet gnupg.
gnupg_log = logging.getLogger('gnupg')
gnupg_log.propagate = False
@contextmanager
def debug_logging():
# getEffectiveLevel() is the best we can do, but it's good enough because
# we always set the level of the logger.
log = logging.getLogger('systemimage')
old_level = log.getEffectiveLevel()
try:
log.setLevel(logging.DEBUG)
yield
finally:
log.setLevel(old_level)
|