/usr/lib/python3/dist-packages/provisioningserver/logger/__init__.py is in python3-maas-provisioningserver 2.4.0~beta2-6865-gec43e47e6-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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | # Copyright 2014-2016 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Logging in MAAS: region, rack, and at the command-line.
Logging is complex:
- The standard library has a `logging` module that needs to be configured. It
can be complex and needs an significant time investment to fully understand.
The `logging.basicConfig` helper can be used to get going, but third-party
libraries often have very different ideas of what an informational message
is (they often overestimate their own importance and emit as informational
what someone else would at best consider a debug message) so levels must be
adjusted; it's not enough to just `basicConfig()` and go.
- Twisted has a "legacy" logging system in `twisted.python.log`. This is still
widely used in Twisted (16.0) and is the primary logging mechanism used by
`twistd`. It has no concept of logging beyond "message" and "error".
- Twisted has a new logging system in `twisted.logger`. This is richer than
the legacy logging system, less complex than `logging`, and emphasises that
logs are not merely lines of text, but are structured events.
- Parts of the legacy Twisted logging system has been reimplemented to use the
modern system. It works but the wiring can be confusing.
- The standard library has a `warnings` module. It invites users to replace
its `showwarning` function in order to change where warnings are reported,
and the standard library's `logging` module can be asked to do just that,
something that Django does. But Twisted also replaces `showwarning` when
logging is initialised. The winner is the one that goes last, meaning it's
important to initialise parts of the application in a stable order.
- `warnings` tests each warning against a list of filters. This is populated
by two functions — `filterwarnings` and `simplefilter` — as well as by `-W`
options given at the command-line. The winner is the last to add a filter,
so the order of initialisation of the application is again a concern.
- Django configures both `logging` and `warnings` during initialisation. In
MAAS, Django often gets initialised late in the start-up process. It can end
up winning the configuration race — by coming last — unless steps are taken
to prevent it.
- Log levels and log level names between Twisted and `logging` are not
consistent, and need normalising in order to produce a consistent log when
both systems are in use.
This module attempts to address *all* of these issues!
"""
__all__ = [
"configure",
"EventLogger",
"get_maas_logger",
"LegacyLogger",
"LoggingMode",
"set_verbosity",
"VerbosityOptions",
]
from provisioningserver.logger._common import (
DEFAULT_LOG_VERBOSITY,
LoggingMode,
make_logging_level_names_consistent,
)
from provisioningserver.logger._django import configure_django_logging
from provisioningserver.logger._logging import (
configure_standard_logging,
set_standard_verbosity,
)
from provisioningserver.logger._maaslog import get_maas_logger
from provisioningserver.logger._tftp import configure_tftp_logging
from provisioningserver.logger._twisted import (
configure_twisted_logging,
EventLogger,
LegacyLogger,
set_twisted_verbosity,
VerbosityOptions,
)
from provisioningserver.utils import typed
# Current verbosity level. Configured initial in `configure()` call.
# Can be set afterward at runtime with `set_verbosity()`.
# Default verbosity is kind of noisy, so we may want to revisit this.
current_verbosity = DEFAULT_LOG_VERBOSITY
@typed
def configure(verbosity: int=None, mode: LoggingMode=None):
"""Configure logging for both Twisted and Python.
This is safe to call from within `twistd`, in a plain Python environment,
and before setting-up Django or after. It will try to do the right thing
in each instance, and also takes into consideration whether it it being
called by a program running at an interactive terminal.
Note that nothing is done to address time-zones. Both Twisted and Python's
``logging`` use local time by default.
If the verbosity is not specified, it will be set to the default verbosity
level.
It is not necessary to call `set_verbosity()` after calling this function,
unless the specified verbosity needs to be changed.
:param verbosity: See `get_logging_level`.
:param mode: The mode in which to configure logging. If not provided this
will be guessed at. See `LoggingMode`.
"""
global current_verbosity
if verbosity is None:
verbosity = DEFAULT_LOG_VERBOSITY
current_verbosity = verbosity
# Automatically detect if we're at a stdio if not explicitly told.
if mode is None:
mode = LoggingMode.guess()
# Fix-up the logging level names in the standard library. This is done
# first to ensure they're consistent in most/all situations.
make_logging_level_names_consistent()
# Now call each configurator in order.
for configurator in configurators:
configurator(verbosity, mode)
configurators = [
configure_twisted_logging,
configure_django_logging,
configure_standard_logging,
configure_tftp_logging,
]
@typed
def set_verbosity(verbosity: int=None):
"""Resets the logging verbosity to the specified level.
This function is intended to be be called after `configure()` is called.
If the verbosity is not specified, it will be set to the default verbosity
level.
:param verbosity: See `get_logging_level`.
"""
global current_verbosity
if verbosity is None:
verbosity = DEFAULT_LOG_VERBOSITY
current_verbosity = verbosity
for verbosity_setter in verbosity_setters:
verbosity_setter(verbosity)
verbosity_setters = [
set_standard_verbosity,
set_twisted_verbosity,
]
|