Files
trove/trove/tests/root_logger.py
Amrith Kumar 67adc87e92 Change reporting of unhandled logging
Unhandled logging messages generated from sources other than Trove's
tests were flooding the log with numerous messages that included
complete backtraces. These backtraces are over 150mb when you run tox
-e py27. Unfortunately, while they are an indication of a problem,
they are most often not things that can be fixed in the Trove project.

To fix this, at least in the short term, this change only reports
anything if the logged message is coming from the context of a test.

Also, this change disables back traces in the messages being reported
unless an optional enables_backtrace is set. By default it set to
False and can only be enabled with a code change (i.e. no
configuration setting).

Change-Id: I9452f03bdd5365991e3c4831aa4936de3713612e
Closes-Bug: 1521373
2015-11-30 19:44:13 -05:00

78 lines
2.5 KiB
Python

# Copyright 2015 Tesora Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import traceback
class DefaultRootHandler(logging.StreamHandler):
"""A singleton StreamHandler"""
__handler = logging.StreamHandler()
__singleton = None
__info = None
__enable_backtrace = False
@classmethod
def activate(cls, enable_backtrace=False):
# leverage the singleton __handler which has an
# acquire() method to create a critical section.
cls.__handler.acquire()
if cls.__singleton is None:
cls.__singleton = DefaultRootHandler()
cls.__enable_backtrace = enable_backtrace
cls.__handler.release()
return cls.__singleton
@classmethod
def set_info(cls, info=None):
cls.__info = info
def __init__(self):
if DefaultRootHandler.__singleton is not None:
raise Exception(
"Do not directly instantiate DefaultRootHandler(). "
"Only use the activate() class method.")
super(DefaultRootHandler, self).__init__()
def emit(self, record):
if DefaultRootHandler.__info:
msg = ("*************************\n" +
"Unhandled message logged from " +
DefaultRootHandler.__info + ", " +
record.name + "\n")
if DefaultRootHandler.__enable_backtrace:
msg += ''.join(traceback.format_stack()) + "\n"
msg += "*************************\n"
self.stream.write(msg)
self.flush()
class DefaultRootLogger(object):
"""A root logger that uses the singleton handler"""
def __init__(self, enable_backtrace=False):
super(DefaultRootLogger, self).__init__()
handler = DefaultRootHandler.activate(enable_backtrace=False)
handler.acquire()
if handler not in logging.getLogger('').handlers:
logging.getLogger('').addHandler(handler)
handler.release()