Configuration of logging is done through the logging.yml
. During the first start a default configuration will be created. It is recommended to extend the default configuration.
The complete description of the file format can be found here, but the format should be pretty straight forward.
Hint
| It is highly recommended to use an absolute path as a file name, at least for the HABApp.log
| That way even if the HABApp configuration is invalid HABApp can still log the errors that have occurred. | e.g.: /HABApp/logs/habapp.log
or c:\HABApp\logs\habapp.log
The logging library is the standard python library and an extensive description can be found in the official documentation.
../run/conf/rules/logging_rule.py
To make the logging output work properly an output file and an output format has to be configured for the logger. The logging library supports a logging hierarchy so the configuration for the logger MyRule
will also work logger MyRule.SubLogger
and MyRule.SubLogger.SubSubLogger
.
The output of our logger from the example shall be in a separate file so we add a new output file to the file configuration under handlers
in the logging.yml
.
handlers:
...
MyRuleHandler: # <-- This is the name of the handler
class: HABApp.core.lib.handler.MidnightRotatingFileHandler
filename: 'c:\HABApp\Logs\MyRule.log'
maxBytes: 10_000_000
backupCount: 3
formatter: HABApp_format # use this format
level: DEBUG
The output file is now available for logging but the configuration for the logger is still missing. It has to be added under loggers
and reference the handler we created
loggers:
...
MyRule: # <-- Name of the logger
level: DEBUG # <-- minimum Logging level, e.g. use INFO if you don't want the output of log.debug()
handlers:
- MyRuleHandler # This logger uses the MyRuleHandler
propagate: False
Now the logger works as expected and writes all output to the new file.
# -----------------------------------------------------------------------------------
# Configuration of the available output formats
# -----------------------------------------------------------------------------------
formatters:
HABApp_format:
format: '[%(asctime)s] [%(name)25s] %(levelname)8s | %(message)s'
# -----------------------------------------------------------------------------------
# Configuration of the available file handlers (output files)
# -----------------------------------------------------------------------------------
handlers:
HABApp_default:
class: HABApp.core.lib.handler.MidnightRotatingFileHandler
filename: 'HABApp.log'
maxBytes: 10_000_000
backupCount: 3
formatter: HABApp_format # use the specified formatter (see above)
level: DEBUG
MyRuleHandler:
class: HABApp.core.lib.handler.MidnightRotatingFileHandler
filename: 'c:\HABApp\Logs\MyRule.log' # absolute filename is recommended
maxBytes: 10_000_000
backupCount: 3
formatter: HABApp_format # use the specified formatter (see above)
level: DEBUG
# -----------------------------------------------------------------------------------
# Configuration of all available loggers and their configuration
# -----------------------------------------------------------------------------------
loggers:
HABApp:
level: DEBUG
handlers:
- HABApp_default # This logger does log with the default handler
propagate: False
MyRule: # <-- Name of the logger
level: DEBUG
handlers:
- MyRuleHandler # This logger uses the MyRuleHandler
propagate: False
It is possible to add custom log levels or rename existing levels. This is possible via the optional levels
entry in the logging configuration file.
levels:
WARNING: WARN # Changes WARNING to WARN
5: TRACE # Adds a new loglevel "TRACE" with value 5
formatters:
HABApp_format:
...
The following handler writes to stdout
handlers:
StdOutHandler:
class: logging.StreamHandler
stream: ext://sys.stdout
formatter: HABApp_format
level: DEBUG
It's possible to filter out certain parts of log files with a filter. The recommendation is to create the filter during startup<ref_run_code_on_startup>
.
This example ignores all messages for the HABApp.EventBus
logger that contain MyIgnoredString
.
Note
| Regular expressions for a filter should be compiled outside of the filter function with re.compile
for performance reasons. | A simple subtext search however will always have way better performance.