Source code for ourobori.services.logger

"""
ourobori use loguru to log.
The logger to be used by the service is created using :func:`default_logger`
defined in this module.
The logger is called inside :func:`ourobori.apps.http._create_app`
automatically so you only have to define the logfile_path where to log
in your service-rules in ``rules.py`` or by passing the argument ``--logfile``
on service-start.
"""


import sys
from typing import Optional

from pathlib import Path
from loguru import logger
from loguru._logger import Logger
try:
    from logstash_async.formatter import LogstashFormatter
    from logstash_async.handler import AsynchronousLogstashHandler
    HAS_LOGSTASH = True
except ModuleNotFoundError:
    HAS_LOGSTASH = False


[docs]def default_logger(*, mode: str, servicename: str, logfile_path: Path, min_level: Optional[str] = 'INFO', rotation: Optional[str] = '1 day', retention: Optional[str] = '1 month', debug: Optional[bool] = False, logstash_connection: Optional[dict] = None) -> Logger: """ Creates the logger based on ``loguru`` to be used inside a service using the ourobori. This function is called inside :func:`ourobori.apps.http.create_app`. The ``logfile_path`` is extracted from Rules-class inside the rules of the service. Parameters: mode: The runtime mode of the service servicename: The name of the service logfile_path: The folder where to store the logfiles. min_level: The minimal log-level to log. rotation: How to rotate the logiles. retention: How long the logfiles will be kept. debug: Flag if debugmode is on or not. logstash_connection: The logstash-connection to use for communicate with logstash. Should be a dict containing the keys 'host" and 'port'. Returns: logger: The logger used for logging inside the service based on the ourobori. """ if not logfile_path.exists(): raise FileNotFoundError( f'logfolder {logfile_path} does not exist') log_fmt = ( '<green>{time:YYMMDD_HHmmss.SSS}</green> | ' '<level>{level[0]}</level> | ' '<blue>{extra[api_id]}</blue> | ' '<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - ' '<level>{message}</level>') # the minimal logger-arguments to use in each logger added by this # function. log_args = dict(format=log_fmt, enqueue=True, backtrace=True, level='DEBUG' if debug else min_level) # Remove the default loguru-logger-definition logger.remove() # add the customized loguru-logger-definition logger.add(sink=str((logfile_path / '{time:YYYY_MM_DD}.log').absolute()), rotation=rotation, retention=retention, **log_args) # define the logger to use for logstash-communication if logstash_connection and HAS_LOGSTASH: ls_handler = AsynchronousLogstashHandler(logstash_connection['host'], logstash_connection['port'], database_path='logstash.db') ls_formatter = LogstashFormatter(message_type='python-logstash', extra_prefix='service', extra=dict(servicename=servicename, mode=mode)) ls_handler.setFormatter(ls_formatter) logger.add(ls_handler, serialize=True, **log_args) # during in debug-mode use an additional logger to print the events to # terminal if debug: logger.add(sink=sys.stdout, **log_args) logger_ctx = logger.bind(api_id=' ') return logger_ctx
__all__ = ['default_logger']