Logger

Class

The Logger class is the voice of colifrapy. Its aim is to display feedback from your program into the console and to write it to a file if necessary. It may also feed on externalized strings written in a YAML file.

N.B.: this custom logger is built around the python logging module and spawn a logging instance named “colifrapy”.

Model Usage

By default, and even if no settings were initialized before, every colifrapy model is loaded with the Logger so you may use it when convenient.

from colifrapy import Model

class MyModel(Model):

    # In every colifrapy model, the Logger is
    # accessible through the "log" property.

    def test(self):
        self.log.write('Hello World!')
        >>> '[DEBUG] :: Hello World!'

Standalone Usage

If you want to use the colifrapy Logger without messing with the whole framework, it is obviously possible. Note that as a lot of colifrapy classes, the Logger is actually a singleton. You may then instanciate it in different files, it will always be the same one for convenience.

from colifrapy import Logger

logger_instance = Logger()

# Run the configuration method at least one to initialize the logger
logger_instance.config(**options)

logger_instance.write('Hello World!')
>>> '[DEBUG] :: Hello World!'

# To change the logger's configuration, just rerun the config method
logger_instance.config(**options)

# Or for specific options
logger_instance.configConsole(options)
logger_instance.configFile(options)

Levels

The logger accepts five levels (ordered by importance):

  • VERBOSE (cyan output)
  • DEBUG (blue output)
  • INFO (green output)
  • WARNING (yellow ouput)
  • ERROR (red output)
  • CRITICAL (violet output) –> will throw an exception for you to catch or not

By default, if no level is specified for a message, DEBUG will always be taken.

Options

Colifrapy’s logger has three different configuration methods, each one dealing with a particular end. You can therefore configure the logger as a whole or rather one of both its handlers (console and file).

Note that if you want to change one of those options on the fly you can always run the config method one more time with the changed options.

Generic Options

The generic options you may pass to the logger’s config method (those options are automatically taken care of when the logger is loaded by the Settings class) are the following:

  • strings {string}
    Path leading to your externalized YAML strings.
    default: None (the logger won’t use externalized strings)
  • exceptions {boolean}
    Should the CRITICAL level trigger exceptions.
    default: True
  • flavor {string|lambda}
    The flavor to use to format %(flavored_levelname)s.
    default: ‘default’
  • console_kwargs {dict}
    A configuration dict to be run into the configConsole method.
    default: None (the configConsole method will be called with its defaults)
  • file_kwargs {dict}
    A configuration dict to be run into the configFile method.
    default: None (the configFile method will be called with its defaults)

For a list of flavors, see Styles. If none of the proposed flavors suit you and you need to create your own, please note that you can pass a lambda taking the levelname variable to the flavor option

Usage example

from colifrapy import Logger

logger_instance = Logger()
logger_instance.config(strings='example_string.yml', exceptions=False)

Console Options

The console options you may pass to the logger’s configConsole method (those options are automatically taken care of when the logger is loaded by the Settings class under logger:console) are the following:

  • activated {boolean}
    Whether the console handler should be activated or not.
    default: True
  • threshold {string}
    Threshold for the console handler.
    default: ‘VERBOSE’
  • formatter {string}
    Formatter for the console handler.
    default: ‘%(flavored_levelname)s :: %(msg)s’

Usage example

from colifrapy import Logger

logger_instance = Logger()
logger_instance.configConsole(threshold='WARNING', activated=True)

File Options

The console options you may pass to the logger’s configFile method (those options are automatically taken care of when the logger is loaded by the Settings class under logger:file) are the following:

  • activated {boolean}
    Whether the file handler should be activated or not.
    default: False
  • threshold {string}
    Threshold for the file handler.
    default: ‘VERBOSE’
  • formatter {string}
    Formatter for the console handler
    default: ‘%(asctime)s %(levelname)s :: %(msg)s’.
  • directory {string}
    Directory where the file handler is supposed to write its logs.
    default: ‘.’
  • filename {string}
    Name of the log files.
    default: ‘program.log’
  • mode {string}
    File logging mode. See Modes.
    default: ‘simple’
  • max_bytes {integer}
    When in rotation mode, maximum of bytes for a log file before rotating.
    default: 1048576
  • backup_count {integer}
    When in rotation mode, maximum number of archived log files.
    default: 5

Note that the file handler is not activated by default.

Usage example

from colifrapy import Logger

logger_instance = Logger()
logger_instance.configFile(threshold='ERROR', activated=True, mode='overwrite')

Strings

Colifrapy offers to externalize your strings in order to enable you to quickly modify them if needed, or even translate them easily. I you do not provide the logger with some strings, it will simply take normal python strings.

The string format used is a mustache-like one, so variables come likewise : {{some_variable}}

Strings given must follow this yaml layout

main:
    process:

        # String with a variable contained within the mustaches
        start: 'Starting corpus analysis (path : {{path}})//INFO'

        # Simply write two slashes at the end to specify the level of the message
        end: 'Exiting//WARNING'
        test_line_break: '\nBonjour'

    title: 'Colifrapy'

other_string_category:
    test: 'Hello everyone//INFO'
    you:
        can:
            make: 'any levels that you want'
            so: 'you can organize your strings however you need.'

Modes

The Logger comes with three different outputting modes:

  • simple: it will write everything to a single specified file.
  • overwrite: the log will be completely overwritten each time you launch the program.
  • rotation: each time your log file overcomes a specified number of lines, it will create a new file and archive the old one. E.g. it functions like the apache log.

For more information about file rotation, you can read the python logging module’s RotatingFileHandler documentation.

Methods

Writing

from colifrapy import Model

class MyModel(Model):
    def test(self):

        # Main method
        #------------

        # Outputting a message
        self.log.write('main:process:end')
        >>> '[WARNING] :: Exiting'

        # Overriding the message level
        self.log.write('main:process:end', level='INFO')
        >>> '[INFO] :: Exiting'

        # Passing variables
        self.log.write('main:protocol:start', {'path' : 'test'})
        >>> '[INFO] :: Starting corpus analysis (path : test)'

        # Variables can be passed to the logger as:
        # a hash, a list, a tuple, a single string or integer or float

        # Examples
        self.log.write('{{variable}}', 'test')
        >>> '[DEBUG] :: test'

        self.log.write('{{var1}} is {{var2}}', ['python', 'cool'])
        >>> '[DEBUG] :: python is cool'

        # When yml string file is not specified or if message does not exist in the yaml file
        self.log.write('Test string')
        >>> '[DEBUG] :: Test string'

        # Named arguments of write
        # variables --> mixed
        # level --> log level



        # Helper methods
        #---------------

        # Printing a header
        self.log.header('main:title', [optional]flavor='default')
        >>> Colifrapy
        >>> ---------

        # You can also pass a function as the title flavor rather
        # than a predetermined one.
        self.log.header('main:title', flavor=lambda msg: msg.upper())
        >>> COLIFRAPY

        # Write methods shorteners
        self.log.critical(message, vars)
        self.log.error(...)
        self.log.warning(...)
        self.log.info(...)
        self.log.debug(...)
        self.log.verbose(...)

Confirmation

from colifrapy import Model

class MyModel(Model):
    def test(self):

        # Confirmation
        #---------------

        # 'y' will be taken by default in arg 2
        # will return True for y and False for n
        response = self.log.confirm('Are you sure you want to continue?')
        >>> 'Are you sure you want to continue? (Y/n)'
        >>> y --> True

        response = self.log.confirm('Are you sure you want to continue?', 'n')
        >>> 'Are you sure you want to continue? (y/N)'
        >>> n --> False

User Input

from colifrapy import Model

class MyModel(Model):
    def test(self):

        # User Input
        #---------------

        response = self.log.input('What up ?')
        >>> 'What up ?'
        >>> 'feeling fine
        >>> 'feeling fine'

        # You can also provide a lambda to the function as second argument
        # This lambda will affect the input given
        response = self.log.input('What up ?', lambda x: x.upper())
        >>> 'What up ?'
        >>> 'feeling fine'
        >>> 'FEELING FINE'

Styles

Colifrapy’s logger comes with several visual alternatives that you may choose from. Those are called flavors and are available for title and standard messages.

Formatters

Colifrapy’s logger accepts a format string the same way as the python logging module, so you can customize your logging output. It also add a custom variable named flavored_levelname which is in fact the level name colored and stylized.

# Default formatter for console
'%(flavored_levelname)s :: %(msg)s'
>>> [DEBUG] :: message to log

# Default formatter for file
'%(asctime)s %(levelname)s :: %(msg)s'
>>> 2014-01-15 13:56:09,798 DEBUG :: message to log

For the full documentation about the variables usable by the formatter, see this page.

Title Flavors

default

Title
-----

heavy

#########
# Title #
#########

elegant

# Title
#-------

bold

# Title
#=======

Flavors

default

[DEBUG]

flat

debug

reverse

# With reverse colors
DEBUG

elegant

Debug

underline

DEBUG
-----