Skip to content

Commit

Permalink
Create COTFormatter logging class
Browse files Browse the repository at this point in the history
  • Loading branch information
glennmatthews committed Feb 24, 2017
1 parent 5080706 commit 9f841b2
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 47 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This project adheres to `Semantic Versioning`_.
``COT.ui_shared``.
- Function ``COT.deploy_esxi.get_object_from_connection`` is now method
``PyVmomiVMReconfigSpec.lookup_object``.
- Function ``COT.cli.formatter`` is now class ``COT.logging_.COTFormatter``.

- COT.disks module:

Expand Down
4 changes: 3 additions & 1 deletion COT/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
COT.data_validation
COT.file_reference
COT.platforms
COT.logging_
User interface modules
----------------------
Expand All @@ -64,8 +64,10 @@
.. autosummary::
:toctree:
COT.disks
COT.helpers
COT.ovf
COT.platforms
"""

from ._version import get_versions
Expand Down
50 changes: 4 additions & 46 deletions COT/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# cli.py - CLI handling for the Common OVF Tool suite
#
# August 2013, Glenn F. Matthews
# Copyright (c) 2013-2016 the COT project developers.
# Copyright (c) 2013-2017 the COT project developers.
# See the COPYRIGHT.txt file at the top-level directory of this distribution
# and at https://github.com/glennmatthews/cot/blob/master/COPYRIGHT.txt.
#
Expand All @@ -18,13 +18,6 @@

"""CLI entry point for the Common OVF Tool (COT) suite.
**Functions**
.. autosummary::
:nosignatures:
formatter
**Classes**
.. autosummary::
Expand Down Expand Up @@ -58,45 +51,11 @@
from COT import __version_long__
from COT.data_validation import InvalidInputError, ValueMismatchError
from COT.ui_shared import UI
from COT.logging_ import COTFormatter

logger = logging.getLogger(__name__)


def formatter(verbosity=logging.INFO):
"""Create formatter for log output.
We offer different (more verbose) formatting when debugging is enabled,
hence this need.
Args:
verbosity (int): Logging level as defined by :mod:`logging`.
Returns:
colorlog.ColoredFormatter: Formatter object to use with :mod:`logging`.
"""
from colorlog import ColoredFormatter
log_colors = {
'DEBUG': 'blue',
'VERBOSE': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
}
format_string = "%(log_color)s"
datefmt = None
if verbosity <= logging.DEBUG:
format_string += "%(asctime)s.%(msecs)d "
datefmt = "%H:%M:%S"
format_string += "%(levelname)8s: "
if verbosity <= logging.VERBOSE:
format_string += "%(name)-22s "
format_string += "%(message)s"
return ColoredFormatter(format_string,
datefmt=datefmt,
log_colors=log_colors)


class CLI(UI):
"""Command-line user interface for COT.
Expand Down Expand Up @@ -312,16 +271,15 @@ def fill_examples(self, example_list):
def set_verbosity(self, level):
"""Enable logging and/or change the logging verbosity level.
Will call :func:`formatter` and associate the resulting formatter
with logging.
Will create a :class:`COTFormatter` and use it for log formatting.
Args:
level (int): Logging level as defined by :mod:`logging`
"""
if not self.handler:
self.handler = logging.StreamHandler()
self.handler.setLevel(level)
self.handler.setFormatter(formatter(level))
self.handler.setFormatter(COTFormatter(level))
if not self.master_logger:
self.master_logger = logging.getLogger('COT')
self.master_logger.addHandler(self.handler)
Expand Down
93 changes: 93 additions & 0 deletions COT/logging_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/env python
#
# logging.py - Common OVF Tool infrastructure for logging
#
# February 2017, Glenn F. Matthews
# Copyright (c) 2013-2017 the COT project developers.
# See the COPYRIGHT.txt file at the top-level directory of this distribution
# and at https://github.com/glennmatthews/cot/blob/master/COPYRIGHT.txt.
#
# This file is part of the Common OVF Tool (COT) project.
# It is subject to the license terms in the LICENSE.txt file found in the
# top-level directory of this distribution and at
# https://github.com/glennmatthews/cot/blob/master/LICENSE.txt. No part
# of COT, including this file, may be copied, modified, propagated, or
# distributed except according to the terms contained in the LICENSE.txt file.

"""Logging module for the Common OVF Tool (COT).
**Classes**
.. autosummary::
:nosignatures:
COTFormatter
"""

from __future__ import absolute_import

import logging
from verboselogs import VerboseLogger
from colorlog import ColoredFormatter

# VerboseLogger adds a log level 'verbose' between 'info' and 'debug'.
# This lets us be a bit more fine-grained in our logging verbosity.
logging.setLoggerClass(VerboseLogger)

logger = logging.getLogger(__name__)


class COTFormatter(ColoredFormatter):
r"""Logging formatter with colorization and variable verbosity.
COT logs are formatted differently (more or less verbosely) depending
on the logging level.
.. seealso:: :class:`logging.Formatter`
Args:
verbosity (int): Logging level as defined by :mod:`logging`.
Examples::
>>> record = logging.LogRecord("test_func", logging.INFO,
... "/fake.py", 22, "Hello world!",
... None, None)
>>> record.created = 0
>>> record.msecs = 0
>>> COTFormatter(logging.DEBUG).format(record)
'\x1b[32m19:00:00.0 INFO: test_func Hello world!\x1b[0m'
>>> COTFormatter(logging.VERBOSE).format(record)
'\x1b[32m INFO: test_func Hello world!\x1b[0m'
>>> COTFormatter(logging.INFO).format(record)
'\x1b[32m INFO: Hello world!\x1b[0m'
"""

LOG_COLORS = {
'DEBUG': 'blue',
'VERBOSE': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
}

def __init__(self, verbosity=logging.INFO):
"""Create formatter for COT log output with the given verbosity."""
format_string = "%(log_color)s"
datefmt = None
if verbosity <= logging.DEBUG:
format_string += "%(asctime)s.%(msecs)d "
datefmt = "%H:%M:%S"
format_string += "%(levelname)8s: "
if verbosity <= logging.VERBOSE:
format_string += "%(name)-22s "
format_string += "%(message)s"
super(COTFormatter, self).__init__(format_string,
datefmt=datefmt,
log_colors=self.LOG_COLORS)


if __name__ == "__main__":
import doctest
doctest.testmod()
1 change: 1 addition & 0 deletions COT/tests/test_doctests.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def load_tests(*_):
suite.addTests(DocTestSuite('COT.edit_hardware'))
suite.addTests(DocTestSuite('COT.edit_properties'))
suite.addTests(DocTestSuite('COT.file_reference'))
suite.addTests(DocTestSuite('COT.logging_'))
suite.addTests(DocTestSuite('COT.platforms'))
suite.addTests(DocTestSuite('COT.ui_shared'))
return suite
4 changes: 4 additions & 0 deletions docs/COT.logging_.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
``COT.logging_`` module
=======================

.. automodule:: COT.logging_

0 comments on commit 9f841b2

Please sign in to comment.