The Gramps Logging System is based on Pythons logging facility.
- 1 Handler subclasses
- 2 Handler instances
- 3 Loggers
- 4 Enable Debugging
- 5 So how logging works in Gramps after all?
There are three Handler subclasses defined:
The RotateHandler just keeps a rotating buffer of the last N (defined at instantiation) log messages sent to it. It can be used e.g. with the GtkHandler to pass a history of log messages to the ErrorReportAssistant().
The GtkHandler will pop up a gtk dialog when a log message is sent to it. The dialog offers the user the chance to start ErrorReportAssistant() to send a bug report.
The WarnHandler is a subclass of RotateHandler thus buffers the last N logs (log level WARNING or above) it received. Additionally it has a button assigned, which will be shown for 180 sec. after a log is received. Activating this button the WarnHandler will pop up a dialog with the list of the buffered logs.
Currently there is one instance of each of the above Handler classes in Gramps. Additionally there's also a StreamHandler() defined with sys.stderr as output stream for debugging purposes. All of these Handlers are attached to the root logger, thus active for any later defined logger.
The RotateHandler, GtkHandler and StreamHandler are all instantiated in gramps.py (setup_logging), while Warnhandler is instantiated in DisplayState.py (DisplayState.__init__). Rotatehandler is attached also to GtkHandler for the purpose described in GtkHandler description. Each Handler instance has a custom formatter assigned.
|Handler||Log level||Formatter||Capacity (buffer size)|
|RotateHandler||-||"%(relativeCreated)d: %(levelname)s: %(filename)s: line %(lineno)d: %(message)s"||20|
|GtkHandler||ERROR||"%(relativeCreated)d: %(levelname)s: %(filename)s: line %(lineno)d: %(message)s"||-|
|WarnHandler||WARNING||"%(levelname)s %(name)s: %(message)s"||400|
|StreamHandler||DEBUG||"%(relativeCreated)d: %(levelname)s: %(filename)s: line %(lineno)d: %(message)s"||-|
The log level of the root logger is set to WARNING by default. In case debugging is activated it may be set to DEBUG (see Enable Debugging). In each module it is recommended to define an own Logger object to be able to understand, which module a certain log (error) is generated from. Setting own log level to a logger is not recommended.
Since the log level of the root logger is set to WARNING by default the StreamHandler will also receive only log at level WARNING and above. To enable debug logs the -d or --debug command line switch is defined. The debug log can be enabled globally by setting the log level of the root logger, or only for a specific module by setting the log level of the logger defined in that particular module.
The usage of the switch is quite simple:
python gramps.py -d "name_of_the_logger"
python gramps.py --debug="name_of_the_logger"
The name of the root logger is an empty string, thus e.g. --debug="" will enable all debug logs.
Note! The argument of the switch is not optional.
So how logging works in Gramps after all?
If debugging is not enabled
- all WARNING and above level logs will be buffered by WarnHandler and can be seen by pressing the warn_button within 3 minutes after the latest log is received.
- all ERROR and above level logs will raise a dialog showing the log. If user votes on reporting the error the ErrorReportAssistant() window will be called with the latest 20 logs included.
- all WARNING and above level logs are sent to the stderr stream.
If debugging is enabled
- all DEBUG and INFO level logs are additionally sent to stderr stream from the enabled logger.
Note! All unhandled exception will send an ERROR level log with the traceback included.
- A developer can add to a module eg:
import logging _LOG = logging.getLogger('.pageview')
- And then in some function
_LOG.debug('a debug message')
- To see this message in a terminal, one starts Gramps with the debug option followed by the debug logger one wants to see:
python src/gramps.py -d '.pageview'