This file is indexed.

/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,
]