Levels and WorkflowΒΆ
The most basic component of logging is the log entry verbosity (or priority) and how that informs the overall workflow. There are 5 levels of verbosity that are used in this library:
- debug
- info
- warning
- error
- exception
Each of these has a graduating level of priority in the system: debug
being the lowest and most
verbose; exception
being the highest and most restrictive.
Handler
s are configured to have a minimum level of verbosity. That is, if a handler is configured
to only produce log entries with a minimum level of info
, all messages passed to it with a level
of debug
will not be recorded; anything else greater than or equal to the set minimum level
will be recorded. For example:
>>> from logging2.handlers import StdOutHandler
>>> from logging2.levels import LogLevel
>>> handler = StdOutHandler(level=LogLevel.debug) # sets handler to log everything
>>> handler.write('Hello\n', level=LogLevel.debug)
Hello
>>> handler.write('Hello\n', level=LogLevel.info)
Hello
>>> handler = StdOutHandler(level=LogLevel.error) # sets handler to log only errors and exceptions
>>> handler.write('Hello\n', level=LogLevel.debug) # skipped
>>> handler.write('Hello\n', level=LogLevel.info) # skipped
>>> handler.write('Hello\n', level=LogLevel.error)
Hello
This workflow is helpful in that Logger
s can have multiple handlers attached to them, each with
a distinct level of verbosity:
# test.py
from logging2 import Logger, LogLevel, StdOutHandler, StdErrHandler
stdout = StdOutHandler()
stderr = StdErrHandler(level=LogLevel.error)
logger = Logger('test', handlers=[stdout, stderr])
logger.debug('this is a debug message')
logger.info('this is an info message')
logger.warning('this is a warning message')
logger.error('this is an error message')
try:
1 / 0
except ZeroDivisionError:
logger.exception("world's best breakpoint")
Which if you ran directly in the terminal would look like:
2017-04-29T17:36:31.560942+00:00 INFO test: this is an info message
2017-04-29T17:36:31.561007+00:00 WARNING test: this is a warning message
2017-04-29T17:36:31.561041+00:00 ERROR test: this is an error message
2017-04-29T17:36:31.561041+00:00 ERROR test: this is an error message
2017-04-29T17:36:31.561070+00:00 EXCEPTION test: world's best breakpoint
Traceback (most recent call last):
File "test.py", line 13, in <module>
1 / 0
ZeroDivisionError: division by zero
2017-04-29T17:36:31.561070+00:00 EXCEPTION test: world's best breakpoint
Traceback (most recent call last):
File "test.py", line 13, in <module>
1 / 0
ZeroDivisionError: division by zero
A better approach would be a general log and an error log:
$ python test.py > test.log 2>error.log
# test.log
2017-04-29T17:37:51.764118+00:00 INFO test: this is an info message
2017-04-29T17:37:51.764141+00:00 WARNING test: this is a warning message
2017-04-29T17:37:51.764157+00:00 ERROR test: this is an error message
2017-04-29T17:37:51.764176+00:00 EXCEPTION test: world's best breakpoint
Traceback (most recent call last):
File "test.py", line 13, in <module>
1 / 0
ZeroDivisionError: division by zero
# error.log
2017-04-29T17:37:51.764157+00:00 ERROR test: this is an error message
2017-04-29T17:37:51.764176+00:00 EXCEPTION test: world's best breakpoint
Traceback (most recent call last):
File "test.py", line 13, in <module>
1 / 0
ZeroDivisionError: division by zero
The last thing to note here, obviously, is that each LogLevel
value has a corresponding method
in Logger
that sets the priority of the message passed to the handlers.