mirror of
https://github.com/dtomlinson91/panaetius.git
synced 2025-12-22 04:55:44 +00:00
142 lines
4.2 KiB
Python
142 lines
4.2 KiB
Python
"""Module to define a convenient logger instance with json formatted output."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from abc import ABCMeta, abstractmethod
|
|
import logging
|
|
from logging.handlers import RotatingFileHandler
|
|
import pathlib
|
|
import sys
|
|
|
|
from panaetius import Config
|
|
from panaetius.library import set_config
|
|
from panaetius.exceptions import LoggingDirectoryDoesNotExistException
|
|
|
|
|
|
def set_logger(config_inst: Config, logging_format_inst: LoggingData) -> logging.Logger:
|
|
"""
|
|
Set and return a `logging.Logger` instance for quick logging.
|
|
|
|
`logging_format_inst` should be an instance of either SimpleLogger, AdvancedLogger,
|
|
or CustomLogger.
|
|
|
|
SimpleLogger and AdvancedLogger define a logging format and a logging level info.
|
|
|
|
CustomLogger defines a logging level info and should have a logging format passed
|
|
in.
|
|
|
|
Logging to a file is defined by a `logging.path` key set on `Config`. This path
|
|
should exist as it will not be created.
|
|
|
|
Args:
|
|
config_inst (Config): The instance of the `Config` class.
|
|
logging_format_inst (LoggingData): The instance of the `LoggingData` class.
|
|
|
|
Raises:
|
|
LoggingDirectoryDoesNotExistException: If the logging directory specified does
|
|
not exist.
|
|
|
|
Returns:
|
|
logging.Logger: An configured instance of `logging.Logger` ready to be used.
|
|
|
|
Example:
|
|
|
|
```
|
|
logger = set_logger(CONFIG, SimpleLogger())
|
|
|
|
logger.info("some logging message")
|
|
```
|
|
|
|
Would create a logging output of:
|
|
|
|
```
|
|
{
|
|
"time": "2021-10-18 02:26:24,037",
|
|
"logging_level":"INFO",
|
|
"message": "some logging message"
|
|
}
|
|
```
|
|
|
|
"""
|
|
logger = logging.getLogger(config_inst.header_variable)
|
|
log_handler_sys = logging.StreamHandler(sys.stdout)
|
|
|
|
# configure file handler
|
|
if config_inst.logging_path is not None:
|
|
logging_file = (
|
|
pathlib.Path(config_inst.logging_path)
|
|
/ config_inst.header_variable
|
|
/ f"{config_inst.header_variable}.log"
|
|
).expanduser()
|
|
|
|
if not logging_file.parents[0].exists():
|
|
raise LoggingDirectoryDoesNotExistException()
|
|
|
|
if config_inst.logging_rotate_bytes == 0:
|
|
set_config(config_inst, "logging.rotate_bytes", 512000)
|
|
if config_inst.logging_backup_count == 0:
|
|
set_config(config_inst, "logging.backup_count", 3)
|
|
|
|
log_handler_file = RotatingFileHandler(
|
|
str(logging_file),
|
|
"a",
|
|
config_inst.logging_rotate_bytes,
|
|
config_inst.logging_backup_count,
|
|
)
|
|
|
|
log_handler_file.setFormatter(logging.Formatter(logging_format_inst.format))
|
|
logger.addHandler(log_handler_file)
|
|
|
|
# configure stdout handler
|
|
log_handler_sys.setFormatter(logging.Formatter(logging_format_inst.format))
|
|
logger.addHandler(log_handler_sys)
|
|
logger.setLevel(logging_format_inst.logging_level)
|
|
return logger
|
|
|
|
|
|
class LoggingData(metaclass=ABCMeta):
|
|
@property
|
|
@abstractmethod
|
|
def format(self) -> str:
|
|
pass
|
|
|
|
@abstractmethod
|
|
def __init__(self, logging_level: str):
|
|
self.logging_level = logging_level
|
|
|
|
|
|
class SimpleLogger(LoggingData):
|
|
@property
|
|
def format(self) -> str:
|
|
return str(
|
|
'{\n\t"time": "%(asctime)s",\n\t"logging_level":'
|
|
'"%(levelname)s",\n\t"message": "%(message)s"\n}',
|
|
)
|
|
|
|
def __init__(self, logging_level: str = "INFO"):
|
|
self.logging_level = logging_level
|
|
|
|
|
|
class AdvancedLogger(LoggingData):
|
|
@property
|
|
def format(self) -> str:
|
|
return str(
|
|
'{\n\t"time": "%(asctime)s",\n\t"file_name": "%(filename)s",'
|
|
'\n\t"module": "%(module)s",\n\t"function":"%(funcName)s",\n\t'
|
|
'"line_number": "%(lineno)s",\n\t"logging_level":'
|
|
'"%(levelname)s",\n\t"message": "%(message)s"\n}',
|
|
)
|
|
|
|
def __init__(self, logging_level: str = "INFO"):
|
|
self.logging_level = logging_level
|
|
|
|
|
|
class CustomLogger(LoggingData):
|
|
@property
|
|
def format(self) -> str:
|
|
return str(self._format)
|
|
|
|
def __init__(self, logging_format: str, logging_level: str = "INFO"):
|
|
self.logging_level = logging_level
|
|
self._format = logging_format
|