Logging¶
Early debug messages¶
Default logging level is set to INFO
. While debugging actions happening early in pipeline workflow, like module discovery and loading, it may be useful to enable more verbose logging. Unfortunatelly, this feature is controlled by a debug
option, and this option will be taken into account too late to shed light on your problem. For that case, it is possible to tell gluetool
to enable debug logging right from its beginning, by setting an environment variable GLUETOOL_DEBUG
to any value:
export GLUETOOL_DEBUG=does-not-matter
gluetool -l
As you can see, gluetool
dumps much more verbose logging messages - about processing of options, config files and other stuff - on terminal with the variable set.
Note
You can set the variable in any way supported by your shell, session or environment in general. The only important thing is that such variable must exist when gluetool
starts.
Logging of structured data¶
To format structured data, like lists, tuples and dictionaries, for output, use gluetool.log.format_dict()
Example:
import gluetool
print gluetool.log.format_dict([1, 2, (3, 4)])
Output:
[
1,
2,
[
3,
4,
]
]
To actually log structured data, the gluetool.log.log_dict()
helper is a nice shortcut.
Example:
import gluetool
logger = gluetool.log.Logging.create_logger()
gluetool.log.log_dict(logger.info, 'logging structured data', [1, 2, (3, 4)])
Output:
[14:43:03] [+] logging structured data:
[
1,
2,
[
3,
4
]
]
The first parameter of log_dict
expects a callback which is given the formatted data to actually log them. It is therefore easy to use log_dict
on every level of your code, e.g. in methods of your module, just give it proper callback, like self.info
.
Todo
seealso
:- logging helpers
- connecting loggers
See also
- Logging of unstructured blobs of text
- to find out how to log text blobs.
gluetool.log.format_dict()
,gluetool.log.log_dict()
- for developer documentation.
Logging of unstructured blobs of text¶
To format a “blob” of text, without any apparent structure other than new-lines and similar markings, use gluetool.log.format_blob()
:
It will preserve text formatting over multiple lines, and it will add borders to allow easy separation of the blob from neighbouring text.
To actually log a blob of text, gluetool.log.log_blob()
is a shortcut:
The first parameter of log_blob
expects a callback which is given the formatted data to actually log them. It is therefore easy to use log_blob
on every level of your code, e.g. in methods of your module, just give it proper callback, like self.info
.
Todo
seealso
:- logging helpers
- connecting loggers
See also
- Logging of structured data
- to find out how to log structured data.
gluetool.log.format_blob()
,gluetool.log.log_blob()
- for developer documentation.
Logging of XML elements¶
To format an XML element, use gluetool.log.format_xml()
:
It will indent nested elements, presenting the tree in a more readable form.
To actually log an XML element, gluetool.log.log_xml()
is a shortcut:
The first parameter of log_xml
expects a callback which is given the formatted data to actually log them. It is therefore easy to use log_xml
on every level of your code, e.g. in methods of your module, just give it proper callback, like self.info
.
Todo
seealso
:- logging helpers
- connecting loggers
See also
- Logging of structured data
- to find out how to log structured data.
gluetool.log.format_blob()
,gluetool.log.log_blob()
- for developer documentation.
Object logging helpers¶
Note
When we talk about logger, we mean it as a description - an object that has logging methods we can use. It’s not necessarilly the instance of logging.Logger
- in fact, given how logging part of gluetool
works, it is most likely it’s an instance of gluetool.logging.ContextAdapter
. But that is not important, the API - logging methods like info
or error
are available in such “logger” object, no matter what its class is.
Python’s logging system provides a log function for each major log level, usually named by its corresponding level in lowercase, e.g. debug
or info
. These are reachable as methods of a logger (or logging context adapter) instance. If you have a class which is given a logger, to ease access to these methods, it is possible to “connect” the logger and your class, making logger’s debug
& co. direct members of your objects, allowing you to call self.debug
, for example.
Example:
from gluetool.log import Logging, ContextAdapter
logger = ContextAdapter(Logging.create_logger())
class Foo(object):
def __init__(self, logger):
logger.connect(self)
Foo(logger).info('a message')
Output:
[10:01:15] [+] a message
All standard logging method debug
, info
, warn
, error
and exception
are made available after connecting a logger.
Todo
seealso
:- context adapter
See also
logging.Logger.debug()
- for logging methods.
Todo
Features yet to describe:
- clear separation of logging records, making it visible where each of them starts and what is a log message and what a logged blob of command output
- default log level controlled by env var
- warn(sentry=True)
- verbose, readable, formatted traceback logging
- using context adapters to add “structure” to loged messages
- colorized messages based on their level
- optional “log everything” dump in a file
- correct and readable logging of exception chains