mirror of https://gitee.com/anolis/sysom.git
164 lines
5.5 KiB
Python
164 lines
5.5 KiB
Python
# -*- coding: utf-8 -*- #
|
|
"""
|
|
Time 2023/4/4 18:08
|
|
Author: mingfeng (SunnyQjm)
|
|
Email mfeng@linux.alibaba.com
|
|
File clogger.py
|
|
Description:
|
|
"""
|
|
import logging
|
|
import sys
|
|
from typing import Optional
|
|
|
|
DEFAULT_FORMAT = "%(asctime)s | %(levelname)s | %(message)s"
|
|
|
|
CLOGGER_CONST_FILENAME = "clogger_filename"
|
|
CLOGGER_CONST_FUNC_NAME = "clogger_func_name"
|
|
CLOGGER_CONST_LINENO = "clogger_lineno"
|
|
|
|
|
|
class LessThanFilter(logging.Filter):
|
|
def __init__(self, exclusive_maximum, name=""):
|
|
super(LessThanFilter, self).__init__(name)
|
|
self.max_level = exclusive_maximum
|
|
|
|
def filter(self, record):
|
|
return 1 if record.levelno < self.max_level else 0
|
|
|
|
|
|
def find_caller_info(func):
|
|
def wrapper(*args, **kwargs):
|
|
filename = sys._getframe(1).f_code.co_filename
|
|
func_name = sys._getframe(1).f_code.co_name
|
|
lineno = sys._getframe(1).f_lineno
|
|
kwargs[CLOGGER_CONST_FILENAME] = filename
|
|
kwargs[CLOGGER_CONST_LINENO] = lineno
|
|
kwargs[CLOGGER_CONST_FUNC_NAME] = func_name
|
|
func(*args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
|
|
class Clogger:
|
|
def __init__(self, name: str = "root", level: str = "DEBUG",
|
|
file=None, log_format: str = DEFAULT_FORMAT):
|
|
# Init logger
|
|
self.logger = logging.getLogger(name)
|
|
|
|
self.file_logger_handler: Optional[logging.FileHandler] = None
|
|
self.stdout_logger_handler = logging.StreamHandler(stream=sys.stdout)
|
|
self.stderr_logger_handler = logging.StreamHandler(stream=sys.stderr)
|
|
|
|
if not self.logger.hasHandlers():
|
|
# FileLoggerHandler
|
|
if file:
|
|
self.file_logger_handler = logging.FileHandler(file)
|
|
self.logger.addHandler(self.file_logger_handler)
|
|
|
|
# stdout logger
|
|
self.stdout_logger_handler.addFilter(LessThanFilter(logging.WARNING))
|
|
self.logger.addHandler(self.stdout_logger_handler)
|
|
|
|
# stderr logger
|
|
self.logger.addHandler(self.stderr_logger_handler)
|
|
|
|
self.set_format(log_format)
|
|
self.set_level(level)
|
|
|
|
def set_format(self, log_format: str, date_fmt: str = "%Y-%m-%d %H:%M:%S"):
|
|
fmt = logging.Formatter(log_format, datefmt=date_fmt)
|
|
if self.file_logger_handler:
|
|
self.file_logger_handler.setFormatter(fmt)
|
|
if self.stdout_logger_handler:
|
|
self.stdout_logger_handler.setFormatter(fmt)
|
|
if self.stderr_logger_handler:
|
|
self.stderr_logger_handler.setFormatter(fmt)
|
|
|
|
def set_level(self, level: str):
|
|
self.logger.setLevel(level)
|
|
if self.file_logger_handler:
|
|
self.file_logger_handler.setLevel(level)
|
|
if self.stdout_logger_handler is not None and logging.getLevelName(
|
|
level) < logging.WARNING:
|
|
self.stdout_logger_handler.setLevel(level)
|
|
if self.stderr_logger_handler is not None:
|
|
if logging.getLevelName(level) > logging.WARNING:
|
|
self.stderr_logger_handler.setLevel(level)
|
|
else:
|
|
self.stderr_logger_handler.setLevel(logging.WARNING)
|
|
|
|
def _wrapper_msg(self, msg, kwargs):
|
|
filename = kwargs.pop(CLOGGER_CONST_FILENAME, "")
|
|
_ = kwargs.pop(CLOGGER_CONST_FUNC_NAME, "")
|
|
lineno = kwargs.pop(CLOGGER_CONST_LINENO, "")
|
|
return f"{filename}:{lineno} | {msg}"
|
|
|
|
@find_caller_info
|
|
def debug(self, msg, *args, **kwargs):
|
|
"""
|
|
Log 'msg % args' with severity 'DEBUG'.
|
|
|
|
To pass exception information, use the keyword argument exc_info with
|
|
a true value, e.g.
|
|
|
|
logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
|
|
"""
|
|
self.logger.debug(self._wrapper_msg(msg, kwargs), *args, **kwargs)
|
|
|
|
@find_caller_info
|
|
def info(self, msg, *args, **kwargs):
|
|
"""
|
|
Log 'msg % args' with severity 'INFO'.
|
|
|
|
To pass exception information, use the keyword argument exc_info with
|
|
a true value, e.g.
|
|
|
|
logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
|
|
"""
|
|
self.logger.info(self._wrapper_msg(msg, kwargs), *args, **kwargs)
|
|
|
|
@find_caller_info
|
|
def warning(self, msg, *args, **kwargs):
|
|
"""
|
|
Log 'msg % args' with severity 'WARNING'.
|
|
|
|
To pass exception information, use the keyword argument exc_info with
|
|
a true value, e.g.
|
|
|
|
logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
|
|
"""
|
|
self.logger.warning(self._wrapper_msg(msg, kwargs), *args, **kwargs)
|
|
|
|
@find_caller_info
|
|
def error(self, msg, *args, **kwargs):
|
|
"""
|
|
Log 'msg % args' with severity 'ERROR'.
|
|
|
|
To pass exception information, use the keyword argument exc_info with
|
|
a true value, e.g.
|
|
|
|
logger.error("Houston, we have a %s", "major problem", exc_info=1)
|
|
"""
|
|
self.logger.error(self._wrapper_msg(msg, kwargs), *args, **kwargs)
|
|
|
|
def exception(self, msg, *args, exc_info=True, **kwargs):
|
|
"""
|
|
Convenience method for logging an ERROR with exception information.
|
|
"""
|
|
self.logger.exception(msg, *args, exc_info=exc_info, **kwargs)
|
|
|
|
@find_caller_info
|
|
def critical(self, msg, *args, **kwargs):
|
|
"""
|
|
Log 'msg % args' with severity 'CRITICAL'.
|
|
|
|
To pass exception information, use the keyword argument exc_info with
|
|
a true value, e.g.
|
|
|
|
logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
|
|
"""
|
|
self.logger.critical(self._wrapper_msg(msg, kwargs), *args, **kwargs)
|
|
|
|
|
|
logger = Clogger()
|