utils.logger - Logger Components¶
Convenience stuff for logging.
Main component of waeup.kofa.utils.logging
is a mix-in class
waeup.kofa.utils.logging.Logger
. Classes derived (also) from
that mix-in provide a logger attribute that returns a regular Python
logger logging to a rotating log file stored in the datacenter storage
path.
Deriving components (classes) should set their own logger_name and logger_filename attribute.
The logger_name tells under which name the logger should be
registered Python-wise. This is usually a dotted name string like
waeup.kofa.${sitename}.mycomponent
which should be unique. If you
pick a name already used by another component, trouble is ahead. The
${sitename}
chunk of the name can be set literally like this. The
logger machinery will turn it into some real site name at time of
logging.
The logger_filename attribute tells how the logfile should be
named. This should be some base filename like
mycomponent.log
. Please note, that some logfile names are already
used: main.log
, applications.log
, and datacenter.log
.
The Logger mix-in also cares for updating the logging handlers when a datacenter location moves. That means you do not have to write your own event handlers for the purpose. Just derive from Logger, set your logger_name and logger_filename attribute and off you go:
from waeup.kofa.utils.logger import Logger
class MyComponent(object, Logger):
# Yes that's a complete working class
logger_name = 'waeup.kofa.${sitename}.mycomponent
logger_filename = 'mycomponent.log'
def do_something(self):
# demomstrate how to use logging from methods
self.logger.info('About to do something')
try:
# Do something here
except IOError:
self.logger.warn('Something went wrong')
return
self.logger.info('I did it')
As you can see from that example, methods of the class can log messages simply by calling self.logger.
The datacenter and its storage are created automatically when you
create a waeup.kofa.app.University
. This also means that
logging with the Logger mix-in will work only inside so-called sites
(University instances put into ZODB are such sites).
Other components in this module help to make everything work.
-
class
waeup.kofa.utils.logger.
ContextFilter
(name='')[source]¶ Bases:
logging.Filter
This is a filter which injects contextual information into the log.
-
__doc__
= '\n This is a filter which injects contextual information into the log.\n\n '¶
-
__module__
= 'waeup.kofa.utils.logger'¶
-
-
interface
waeup.kofa.utils.logger.
ILogger
[source]¶ -
logger_filename
¶ A filename for the log file to use (basename)
-
logger_setup
(logger)¶ Setup a logger.
logger is an instance of
logging.Logger
.
-
logger_get_logfile_path
()¶ Get path to logfile used.
Return None if the file path cannot be computed.
-
logger_get_logdir
()¶ Get the directory of the logfile.
Return None if the directory path cannot be computed.
-
logger_name
¶ A Python logger name
-
logger
¶ Get a Python logger instance already set up
-
-
waeup.kofa.utils.logger.
LEVEL
= 20¶ Default logging level (logging.INFO)
-
class
waeup.kofa.utils.logger.
Logger
[source]¶ Bases:
object
Mixin-class that for logging support.
Classes that (also) inherit from this class provide support for logging with waeup sites.
By default a logger attribute is provided which returns a regular Python logger. This logger has already registered a file rotating log handler that writes log messages to a file main.log in datacenters
log/
directory. This is the main log file also used by other components. Therefore you can pick another filename by setting the logger_filename attribute.All methods and attributes of this mix-in start with
logger_
in order not to interfere with already existing names of a class.Method names do not follow the usual Zope habit (CamelCase) but PEP8 convention (lower_case_with_underscores).
-
__dict__
= dict_proxy({'__providedBy__': <_interface_coptimizations.ObjectSpecificationDescriptor object at 0x7f402dea22c0>, '__module__': 'waeup.kofa.utils.logger', 'logger_filename': 'main.log', '__provides__': <zope.interface.declarations.ClassProvides object at 0x7f402803bc50>, 'logger_setup': <function logger_setup at 0x7f4028042e60>, 'logger_get_logfile_path': <function logger_get_logfile_path at 0x7f4028042ed8>, 'logger_get_logdir': <function logger_get_logdir at 0x7f4028042f50>, 'logger_format_str': '%(asctime)s - %(levelname)s - %(user)s - %(message)s', 'logger_shutdown': <function logger_shutdown at 0x7f40280430c8>, 'logger_name': 'waeup.kofa.${sitename}', '__dict__': <attribute '__dict__' of 'Logger' objects>, 'logger': <property object at 0x7f40282b5fc8>, '__implemented__': <implementedBy waeup.kofa.utils.logger.Logger>, '__weakref__': <attribute '__weakref__' of 'Logger' objects>, '__doc__': 'Mixin-class that for logging support.\n\n Classes that (also) inherit from this class provide support for\n logging with waeup sites.\n\n By default a `logger` attribute is provided which returns a\n regular Python logger. This logger has already registered a file\n rotating log handler that writes log messages to a file `main.log`\n in datacenters ``log/`` directory. This is the main log file also\n used by other components. Therefore you can pick another filename\n by setting the `logger_filename` attribute.\n\n All methods and attributes of this mix-in start with ``logger_``\n in order not to interfere with already existing names of a class.\n\n Method names do not follow the usual Zope habit (CamelCase) but\n PEP8 convention (lower_case_with_underscores).\n ', 'logger_logfile_changed': <function logger_logfile_changed at 0x7f4028043050>})¶
-
__doc__
= 'Mixin-class that for logging support.\n\n Classes that (also) inherit from this class provide support for\n logging with waeup sites.\n\n By default a `logger` attribute is provided which returns a\n regular Python logger. This logger has already registered a file\n rotating log handler that writes log messages to a file `main.log`\n in datacenters ``log/`` directory. This is the main log file also\n used by other components. Therefore you can pick another filename\n by setting the `logger_filename` attribute.\n\n All methods and attributes of this mix-in start with ``logger_``\n in order not to interfere with already existing names of a class.\n\n Method names do not follow the usual Zope habit (CamelCase) but\n PEP8 convention (lower_case_with_underscores).\n '¶
-
__implemented__
= <implementedBy waeup.kofa.utils.logger.Logger>¶
-
__module__
= 'waeup.kofa.utils.logger'¶
-
__providedBy__
¶ Special descriptor for class __provides__
The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.
For example:
>>> from zope.interface import Interface >>> class IFooFactory(Interface): ... pass >>> class IFoo(Interface): ... pass >>> class C(object): ... implements(IFoo) ... classProvides(IFooFactory) >>> [i.getName() for i in C.__provides__] ['IFooFactory']
>>> [i.getName() for i in C().__provides__] ['IFoo']
-
__provides__
¶ Special descriptor for class __provides__
The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.
For example:
>>> from zope.interface import Interface >>> class IFooFactory(Interface): ... pass >>> class IFoo(Interface): ... pass >>> class C(object): ... implements(IFoo) ... classProvides(IFooFactory) >>> [i.getName() for i in C.__provides__] ['IFooFactory']
>>> [i.getName() for i in C().__provides__] ['IFoo']
-
__weakref__
¶ list of weak references to the object (if defined)
-
logger
¶ Get a logger instance.
Returns a standard logger object as provided by
logging
module from the standard library.Other components can use this logger to perform log entries into the logfile of this component.
The logger is initialized the first time it is called.
The logger is only available when used inside a site.
Note
The logger default level is
logging.WARN
. Uselogging.Logger.setLevel()
to set a different level.
-
logger_filename
= 'main.log'¶ The filename to use when logging.
-
logger_format_str
= '%(asctime)s - %(levelname)s - %(user)s - %(message)s'¶ The format to use when logging.
-
logger_get_logdir
()[source]¶ Get log dir where logfile should be put.
Returns the path to the logfile directory. If no site is set,
None
is returned. The same applies, if the site has no datacenter.If the dir dies not exist already it will be created. Only the last part of the directory path will be created.
-
logger_get_logfile_path
()[source]¶ Get the path to the logfile used.
Returns the path to a file in local sites datacenter
log/
directory (dependent onlogger_get_logdir()
) and withlogger_filename
as basename.Override this method if you want a complete different computation of the logfile path. If you only want a different logfile name, set
logger_filename
. If you only want a different path to the logfile overridelogger_get_logdir()
instead.Returns
None
if no logdir can be fetched.Note
creates the logfile dir if it does not exist.
-
logger_logfile_changed
()[source]¶ React on logfile location change.
If the logfile changed, we can set a different logfile. While changing the logfile is a rather critical operation you might not do often in production use, we have to cope with that especially in tests.
What this method does by default (unless you override it):
- It fetches the current logger and
- Removes flushes, closes, and removes all handlers
- Sets up new handler(s).
All this, of course, requires to be ‘in a site’.
Use this method to handle moves of datacenters, for instance by writing an appropriate event handler.
- It fetches the current logger and
-
logger_name
= 'waeup.kofa.${sitename}'¶ The Python logger name used when logging.
'waeup.kofa.${sitename}'
by default. You can use the${sitename}
placeholder in that string, which will be replaced by the actual used site name.
-
-
class
waeup.kofa.utils.logger.
LoggerCollector
[source]¶ Bases:
dict
,grokcore.component.components.GlobalUtility
A global utility providing ILoggerCollector.
A logging collector collects logging components. This helps to inform them when a logfile location changes.
Logging components are registered per site they belong to.
-
__dict__
= dict_proxy({'getLoggers': <function getLoggers at 0x7f4028043230>, '__module__': 'waeup.kofa.utils.logger', '__provides__': <zope.interface.declarations.ClassProvides object at 0x7f402803bd50>, 'registerLogger': <function registerLogger at 0x7f40280432a8>, '__dict__': <attribute '__dict__' of 'LoggerCollector' objects>, '__implemented__': <implementedBy waeup.kofa.utils.logger.LoggerCollector>, '__weakref__': <attribute '__weakref__' of 'LoggerCollector' objects>, '__doc__': 'A global utility providing `ILoggerCollector`.\n\n A logging collector collects logging components. This helps to\n inform them when a logfile location changes.\n\n Logging components are registered per site they belong to.\n ', 'unregisterLogger': <function unregisterLogger at 0x7f4028043320>})¶
-
__doc__
= 'A global utility providing `ILoggerCollector`.\n\n A logging collector collects logging components. This helps to\n inform them when a logfile location changes.\n\n Logging components are registered per site they belong to.\n '¶
-
__implemented__
= <implementedBy waeup.kofa.utils.logger.LoggerCollector>¶
-
__module__
= 'waeup.kofa.utils.logger'¶
-
__provides__
¶ Special descriptor for class __provides__
The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.
For example:
>>> from zope.interface import Interface >>> class IFooFactory(Interface): ... pass >>> class IFoo(Interface): ... pass >>> class C(object): ... implements(IFoo) ... classProvides(IFooFactory) >>> [i.getName() for i in C.__provides__] ['IFooFactory']
>>> [i.getName() for i in C().__provides__] ['IFoo']
-
__weakref__
¶ list of weak references to the object (if defined)
-
-
waeup.kofa.utils.logger.
handle_datacenter_storage_moved
(obj, event)[source]¶ Event handler, in case datacenter storage moves.
By default all our logfiles (yes, we produce a whole bunch of it) are located in a
log/
dir of a local datacenter, the datacenter ‘storage’. If this path changes because the datacenter is moved an appropriate event is triggered and we can react.Via the global ILoggerCollector utility, a small piece that allows self-registering of logging components, we can lookup components whose logfile path has to be set up anew.
Each component we call has to provide ILogger or, more specific, the
logger_logfile_changed()
method of this interface.