123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- """
- The ColorLog Extension provides logging based on the standard
- ``logging`` module and is a drop-in replacement for the default log
- handler :class:`cement.ext.ext_logging.LoggingLogHandler`.
- Requirements
- ------------
- * ColorLog (``pip install colorlog``)
- Configuration
- -------------
- This handler honors all of the same configuration settings as the
- ``LoggingLogHandler`` including:
- * level
- * file
- * to_console
- * rotate
- * max_bytes
- * max_files
- In addition, it also supports:
- * colorize_file_log
- * colorize_console_log
- A sample config section (in any config file) might look like:
- .. code-block:: text
- [log.colorlog]
- file = /path/to/config/file
- level = info
- to_console = true
- rotate = true
- max_bytes = 512000
- max_files = 4
- colorize_file_log = false
- colorize_console_log = true
- Usage
- -----
- .. code-block:: python
- from cement.core.foundation import CementApp
- class MyApp(CementApp):
- class Meta:
- label = 'myapp'
- extensions = ['colorlog']
- log_handler = 'colorlog'
- with MyApp() as app:
- app.run()
- app.log.debug('This is my debug message')
- app.log.info('This is my info message')
- app.log.warn('This is my warning message')
- app.log.error('This is my error message')
- app.log.fatal('This is my critical message')
- The colors can be customized by passing in a ``colors`` dictionary mapping
- overriding the ``ColorLogHandler.Meta.colors`` meta-data:
- .. code-block:: python
- from cement.core.foundation import CementApp
- from cement.ext.ext_colorlog import ColorLogHandler
- COLORS = {
- 'DEBUG': 'cyan',
- 'INFO': 'green',
- 'WARNING': 'yellow',
- 'ERROR': 'red',
- 'CRITICAL': 'red,bg_white',
- }
- class MyApp(CementApp):
- class Meta:
- label = 'myapp'
- log_handler = ColorLogHandler(colors=COLORS)
- Or by sub-classing and creating your own custom class:
- .. code-block:: python
- from cement.core.foundation import CementApp
- from cement.ext.ext_colorlog import ColorLogHandler
- class MyCustomLog(ColorLogHandler):
- class Meta:
- label = 'my_custom_log'
- colors = {
- 'DEBUG': 'cyan',
- 'INFO': 'green',
- 'WARNING': 'yellow',
- 'ERROR': 'red',
- 'CRITICAL': 'red,bg_white',
- }
- class MyApp(CementApp):
- class Meta:
- label = 'myapp'
- log_handler = MyCustomLog
- """
- import os
- import sys
- import logging
- from colorlog import ColoredFormatter
- from ..ext.ext_logging import LoggingLogHandler
- from ..utils.misc import is_true
- class ColorLogHandler(LoggingLogHandler):
- """
- This class implements the :class:`cement.core.log.ILog` interface. It is
- a sub-class of :class:`cement.ext.ext_logging.LoggingLogHandler` which is
- based on the standard :py:class:`logging` library, and adds colorized
- console output using the
- `ColorLog <https://pypi.python.org/pypi/colorlog>`_ library.
- **Note** This extension has an external dependency on ``colorlog``. You
- must include ``colorlog`` in your applications dependencies as Cement
- explicitly does **not** include external dependencies for optional
- extensions.
- """
- class Meta:
- """Handler meta-data."""
- #: The string identifier of the handler.
- label = "colorlog"
- #: Color mapping for each log level
- colors = {
- 'DEBUG': 'cyan',
- 'INFO': 'green',
- 'WARNING': 'yellow',
- 'ERROR': 'red',
- 'CRITICAL': 'red,bg_white',
- }
- #: Default configuration settings. Will be overridden by the same
- #: settings in any application configuration file under a
- #: ``[log.colorlog]`` block.
- config_defaults = dict(
- file=None,
- level='INFO',
- to_console=True,
- rotate=False,
- max_bytes=512000,
- max_files=4,
- colorize_file_log=False,
- colorize_console_log=True,
- )
- #: Formatter class to use for non-colorized logging (non-tty, file,
- #: etc)
- formatter_class_without_color = logging.Formatter
- #: Formatter class to use for colorized logging
- formatter_class = ColoredFormatter
- def _get_console_format(self):
- format = super(ColorLogHandler, self)._get_console_format()
- colorize = self.app.config.get('log.colorlog', 'colorize_console_log')
- if sys.stdout.isatty() or 'CEMENT_TEST' in os.environ:
- if is_true(colorize):
- format = "%(log_color)s" + format
- return format
- def _get_file_format(self):
- format = super(ColorLogHandler, self)._get_file_format()
- colorize = self.app.config.get('log.colorlog', 'colorize_file_log')
- if is_true(colorize):
- format = "%(log_color)s" + format
- return format
- def _get_console_formatter(self, format):
- colorize = self.app.config.get('log.colorlog', 'colorize_console_log')
- if sys.stdout.isatty() or 'CEMENT_TEST' in os.environ:
- if is_true(colorize):
- formatter = self._meta.formatter_class(
- format,
- log_colors=self._meta.colors
- )
- else:
- formatter = self._meta.formatter_class_without_color(
- format
- )
- else:
- klass = self._meta.formatter_class_without_color # pragma: nocover
- formatter = klass(format) # pragma: nocover
- return formatter
- def _get_file_formatter(self, format):
- colorize = self.app.config.get('log.colorlog', 'colorize_file_log')
- if is_true(colorize):
- formatter = self._meta.formatter_class(
- format,
- log_colors=self._meta.colors
- )
- else:
- formatter = self._meta.formatter_class_without_color(format)
- return formatter
- def load(app):
- app.handler.register(ColorLogHandler)
|