Source code for pywrapid.log.application_log

#!/usr/bin/python3
"""
Log manager for easy and fast log compliancy

This library is for educational purposes only.
Do no evil, do not break local or internation laws!
By using this code, you take full responisbillity for your actions.
The author have granted code access for educational purposes and is
not liable for any missuse.
"""
__author__ = "Jonas Werme"
__copyright__ = "Copyright (c) 2021 Jonas Werme"
__credits__ = ["Marcus Wallgren", "nsahq"]
__license__ = "MIT"
__version__ = "1.0.0"
__maintainer__ = "Jonas Werme"
__email__ = "jonas[dot]werme[at]nsahq[dot]se"
__status__ = "Prototype"

import logging
from logging.handlers import SysLogHandler
from typing import Type, Union

from pywrapid.config import WrapidConfig
from pywrapid.config.exceptions import ConfigurationError
from pywrapid.utils import dict_merge


def _generate_default(cfg: dict) -> dict:
    """Generate default config dict for logging

    Args:
        cfg (dict): Logging configuration

    Raises:
        ConfigurationError

    Returns:
        dict: Default logging configuration
    """
    if not isinstance(cfg, dict):
        raise ConfigurationError("Invalid application logging configuration type")

    default = {
        "console": {
            "format": "[%(levelname)s] (%(name)s) %(message)s",
            "level": logging.INFO,
        },
        "file": {
            "format": "%(asctime)-15s [%(levelname)s] (%(name)s) %(message)s",
            "level": logging.INFO,
            "location": "",
        },
        "syslog": {
            "format": "%(asctime)-15s [%(levelname)s] (%(name)s) %(message)s",
            "level": 0,
            "location": "/dev/log",
            "ident": "pywrapid-default-ident",
        },
    }

    if not cfg:
        return default

    if "default" in cfg and cfg["default"]:
        if not isinstance(cfg["default"], dict):
            raise ConfigurationError("Invalid object in configuration section: default")
        default = dict_merge(default, cfg["default"])

    return default


# flake8: noqa: C901
[docs] def application_logging( # pylint: disable=too-many-branches config: Union[Type[WrapidConfig], dict], ) -> None: """Sets up loggers for application Configuration used for setting up all specified loggers as well as the root logger. Args: config (WrapidConfig|dict): Wrapid config object or dict of modules and options """ if isinstance(config, WrapidConfig): cfg = config.cfg elif isinstance(config, dict): cfg = config else: raise ConfigurationError("Invalid application logging configuration type") logging.root.setLevel(logging.NOTSET) default = _generate_default(cfg=cfg) cfg["root"] = default for module in cfg: if module == "default": continue log = logging.getLogger(module) if module != "root" else logging.getLogger() log.propagate = False # if log.hasHandlers(): # continue cfg[module] = dict_merge(default, cfg[module]) if cfg[module] is not None else default for log_type in ["console", "file", "syslog"]: formatter = logging.Formatter(cfg[module].get("format", default[log_type]["format"])) level = cfg[module][log_type].get("level", default[log_type]["level"]) if level == 0: continue if log_type == "console": handler: logging.Handler = logging.StreamHandler() elif log_type == "file": if not cfg[module][log_type]["location"]: continue handler = logging.FileHandler( cfg[module].get("location", default[log_type]["location"]) ) elif log_type == "syslog": handler = SysLogHandler( facility=SysLogHandler.LOG_DAEMON, address=cfg[module].get("location", default[log_type]["location"]), ) ident = cfg[module].get("ident", default[log_type]["ident"]) if ident: handler.ident = ident handler.setLevel(level) handler.setFormatter(formatter) log.addHandler(handler) if log.getEffectiveLevel() > level: log.setLevel(level) if log.getEffectiveLevel() == 0: log.setLevel(10)
# if log.root.getEffectiveLevel() > level: # log.root.setLevel(level)