mirror of
https://github.com/certbot/certbot.git
synced 2026-06-08 08:12:15 -04:00
Made error logging entries red in the terminal
This commit is contained in:
parent
5cc9061413
commit
fe810020c4
5 changed files with 95 additions and 4 deletions
|
|
@ -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()
|
||||
|
|
|
|||
47
letsencrypt/colored_logging.py
Normal file
47
letsencrypt/colored_logging.py
Normal 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
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
39
letsencrypt/tests/colored_logging_test.py
Normal file
39
letsencrypt/tests/colored_logging_test.py
Normal 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
|
||||
Loading…
Reference in a new issue