~launchpad-pqm/launchpad/devel

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
# Copyright 2009 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

# This file is imported by parts/scripts/sitecustomize.py, as set up in our
# buildout.cfg (see the "initialization" key in the "[scripts]" section).

import itertools
import os
import warnings
import logging

from twisted.internet.defer import (
    Deferred,
    DeferredList,
    )

from bzrlib.branch import Branch
from lp.services.log import loglevels
from lp.services.log.mappingfilter import MappingFilter
from lp.services.log.nullhandler import NullHandler
from lp.services.mime import customizeMimetypes
from zope.security import checker


def add_custom_loglevels():
    """Add out custom log levels to the Python logging package."""

    # This import installs custom ZODB loglevels, which we can then
    # override. BLATHER is between INFO and DEBUG, so we can leave it.
    # TRACE conflicts with DEBUG6, and since we are not using ZEO, we
    # just overwrite the level string by calling addLevelName.
    from ZODB.loglevels import BLATHER, TRACE

    # Confirm our above assumptions, and silence lint at the same time.
    assert BLATHER == 15
    assert TRACE == loglevels.DEBUG6

    logging.addLevelName(loglevels.DEBUG2, 'DEBUG2')
    logging.addLevelName(loglevels.DEBUG3, 'DEBUG3')
    logging.addLevelName(loglevels.DEBUG4, 'DEBUG4')
    logging.addLevelName(loglevels.DEBUG5, 'DEBUG5')
    logging.addLevelName(loglevels.DEBUG6, 'DEBUG6')
    logging.addLevelName(loglevels.DEBUG7, 'DEBUG7')
    logging.addLevelName(loglevels.DEBUG8, 'DEBUG8')
    logging.addLevelName(loglevels.DEBUG9, 'DEBUG9')

    # Install our customized Logger that provides easy access to our
    # custom loglevels.
    logging.setLoggerClass(loglevels.LaunchpadLogger)


def silence_bzr_logger():
    """Install the NullHandler on the bzr logger to silence logs."""
    logging.getLogger('bzr').addHandler(NullHandler())


def silence_zcml_logger():
    """Lower level of ZCML parsing DEBUG messages."""
    config_filter = MappingFilter(
        {logging.DEBUG: (7, 'DEBUG4')}, 'config')
    logging.getLogger('config').addFilter(config_filter)


def silence_transaction_logger():
    """Lower level of DEBUG messages from the transaction module."""
    # Transaction logging is too noisy. Lower its DEBUG messages
    # to DEBUG3. Transactions log to loggers named txn.<thread_id>,
    # so we need to register a null handler with a filter to ensure
    # the logging records get mutated before being propagated up
    # to higher level loggers.
    txn_handler = NullHandler()
    txn_filter = MappingFilter(
        {logging.DEBUG: (8, 'DEBUG3')}, 'txn')
    txn_handler.addFilter(txn_filter)
    logging.getLogger('txn').addHandler(txn_handler)


def dont_wrap_class_and_subclasses(cls):
    checker.BasicTypes.update({cls: checker.NoProxy})
    for subcls in cls.__subclasses__():
        dont_wrap_class_and_subclasses(subcls)


def silence_warnings():
    """Silence warnings across the entire Launchpad project."""
    # pycrypto-2.0.1 on Python2.6:
    #   DeprecationWarning: the sha module is deprecated; use the hashlib
    #   module instead
    warnings.filterwarnings(
        "ignore",
        category=DeprecationWarning,
        module="Crypto")


def main(instance_name):
    # This is called by our custom buildout-generated sitecustomize.py
    # in parts/scripts/sitecustomize.py. The instance name is sent to
    # buildout from the Makefile, and then inserted into
    # sitecustomize.py.  See buildout.cfg in the "initialization" value
    # of the [scripts] section for the code that goes into this custom
    # sitecustomize.py.  We do all actual initialization here, in a more
    # visible place.
    if instance_name and instance_name != 'development':
        # See bug 656213 for why we do this carefully.
        os.environ.setdefault('LPCONFIG', instance_name)
    os.environ['STORM_CEXTENSIONS'] = '1'
    add_custom_loglevels()
    customizeMimetypes()
    dont_wrap_class_and_subclasses(Branch)
    checker.BasicTypes.update({Deferred: checker.NoProxy})
    checker.BasicTypes.update({DeferredList: checker.NoProxy})
    checker.BasicTypes[itertools.groupby] = checker._iteratorChecker
    # The itertools._grouper type is not exposed by name, so we must get it
    # through actually using itertools.groupby.
    grouper = type(list(itertools.groupby([0]))[0][1])
    checker.BasicTypes[grouper] = checker._iteratorChecker
    silence_warnings()
    silence_bzr_logger()
    silence_zcml_logger()
    silence_transaction_logger()