Made error logging entries red in the terminal

This commit is contained in:
Brad Warren 2015-09-25 13:26:45 -07:00
parent 5cc9061413
commit fe810020c4
5 changed files with 95 additions and 4 deletions

View file

@ -24,6 +24,7 @@ from acme import jose
import letsencrypt
from letsencrypt import account
from letsencrypt import colored_logging
from letsencrypt import configuration
from letsencrypt import constants
from letsencrypt import client
@ -786,7 +787,7 @@ def _setup_logging(args):
level = -args.verbose_count * 10
fmt = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
if args.text_mode:
handler = logging.StreamHandler()
handler = colored_logging.StreamHandler()
handler.setFormatter(logging.Formatter(fmt))
else:
handler = log.DialogHandler()

View file

@ -0,0 +1,47 @@
"""A formatter and StreamHandler for colorizing logging output."""
import logging
import sys
from letsencrypt import le_util
class StreamHandler(logging.StreamHandler):
"""Sends colored logging output to a stream.
If the specified stream is not a tty, the class works like the
standard logging.StreamHandler. Default red_level is logging.WARNING.
:ivar bool colored: True if output should be colored
:ivar bool red_level: The level at which to output
"""
_RED = '\033[31m'
def __init__(self, stream=None):
super(StreamHandler, self).__init__(stream)
self.colored = (sys.stderr.isatty() if stream is None else
stream.isatty())
self.set_red_level(logging.WARNING)
def format(self, record):
"""Formats the string representation of record.
:param logging.LogRecord record: Record to be formatted
:returns: Formatted, string representation of record
:rtype: str
"""
output = super(StreamHandler, self).format(record)
if self.colored and record.levelno >= self.red_level:
return ''.join((self._RED, output, le_util.ANSI_SGR_RESET))
else:
return output
def set_red_level(self, red_level):
"""Sets the level necessary to display output in red.
:param int red_level: Minimum log level for displaying red text
"""
self.red_level = red_level

View file

@ -18,6 +18,10 @@ Key = collections.namedtuple("Key", "file pem")
CSR = collections.namedtuple("CSR", "file data form")
# ANSI escape code for resetting output format
ANSI_SGR_RESET = "\033[0m"
def run_script(params):
"""Run the script with the given params.

View file

@ -9,6 +9,7 @@ import textwrap
import zope.interface
from letsencrypt import interfaces
from letsencrypt import le_util
logger = logging.getLogger(__name__)
@ -30,7 +31,6 @@ class Reporter(object):
LOW_PRIORITY = 2
"""Low priority constant. See `add_message`."""
_RESET = '\033[0m'
_BOLD = '\033[1m'
_msg_type = collections.namedtuple('ReporterMsg', 'priority text on_crash')
@ -87,7 +87,7 @@ class Reporter(object):
msg = self.messages.get()
if no_exception or msg.on_crash:
if bold_on and msg.priority > self.HIGH_PRIORITY:
sys.stdout.write(self._RESET)
sys.stdout.write(le_util.ANSI_SGR_RESET)
bold_on = False
lines = msg.text.splitlines()
print first_wrapper.fill(lines[0])
@ -95,4 +95,4 @@ class Reporter(object):
print "\n".join(
next_wrapper.fill(line) for line in lines[1:])
if bold_on:
sys.stdout.write(self._RESET)
sys.stdout.write(le_util.ANSI_SGR_RESET)

View file

@ -0,0 +1,39 @@
"""Tests for letsencrypt.colored_logging."""
import logging
import StringIO
import unittest
from letsencrypt import le_util
class StreamHandlerTest(unittest.TestCase):
def setUp(self):
from letsencrypt import colored_logging
self.stream = StringIO.StringIO()
self.stream.isatty = lambda: True
self.handler = colored_logging.StreamHandler(self.stream)
self.logger = logging.getLogger()
self.logger.setLevel(logging.DEBUG)
self.logger.addHandler(self.handler)
def test_format(self):
msg = 'I did a thing'
self.logger.debug(msg)
self.assertEqual(self.stream.getvalue(), '{0}\n'.format(msg))
def test_format_and_red_level(self):
msg = 'I did another thing'
self.handler.set_red_level(logging.DEBUG)
self.logger.debug(msg)
# pylint: disable=protected-access
expected = '{0}{1}{2}\n'.format(self.handler._RED, msg,
le_util.ANSI_SGR_RESET)
self.assertEqual(self.stream.getvalue(), expected)
if __name__ == "__main__":
unittest.main() # pragma: no cover