====== Логирование ====== ===== Общее ===== [[https://habr.com/ru/company/otus/blog/590067/|Статья]]\\
:!: Вырезки {{:develop:pyton:2022-12-03_11-21.png?direct&600|}} {{:develop:pyton:2022-12-03_11-31.png?direct&600|}}
===== Применение ===== [[https://docs.python.org/3/library/logging.html#logger-objects|Дока]]\\ [[https://docs.python.org/3/library/logging.config.html|Дока]]\\ Классы логгера наследуются, в блоке "root" можно определить базовые параметры для всех создаваемых потом подклассов\\ Собсна структура конфига ниже, перечисляются форматтеры, логгеры, хендлеры, можно создавать несколько разных комбинаций, каждая со своими параметрами и для каждой применяются указанные правила логирования (место, формат, устр-во и т.д.)\\ Конфиг можно хранить в отдельном файле, но тогда нет возможности использовать переменные, можно обернуть в python объект, тогда чики-пики. [[https://habr.com/ru/company/otus/blog/590067/|тут есть пример]]\\ Настройка целевого уровня задается и в loggers и в handlers, сначала фильтруется в первом, затем во втором\\ { "version": 1, "disable_existing_loggers": False, "formatters": { }, "handlers": { }, "loggers": { }, "root": { }, } Для использования JSON нужен модуль [[https://pypi.org/project/python-json-logger/|"python-json-logger"]]\\
:!: Боевой пример. Три типа логов Три типа логов: * Общий * Только ошибки * Логирование спец событий, в данном случае д-я пользователей Использование #!/usr/bin/python3.8 import loggers logger = loggers.get_logger('main') usr_logger = loggers.get_logger('usrlog', template = "usr_actions") logger.info("Simple logger, level == info") logger.error("Simple logger, level == error") usr_logger.info("User log, level == info", extra={"username": "myname"}) Создание объекта логгера #!/usr/bin/python3.8 import os import json import logging import logging.config FOLDER_LOG = "log" LOGGING_CONFIG_FILE = 'logger_config.json' def create_log_folder(folder=FOLDER_LOG): if not os.path.exists(folder): os.mkdir(folder) def get_logger(name, template='simple'): create_log_folder() with open(LOGGING_CONFIG_FILE, "r") as f: dict_config = json.load(f) dict_config["loggers"][name] = dict_config["loggers"][template] logging.config.dictConfig(dict_config) return logging.getLogger(name) Конфиг { "version": 1, "disable_existing_loggers": false, "formatters": { "strings": { "format": "%(asctime)s - %(processName)-10s - %(name)-10s - %(levelname)-8s - %(message)s", "datefmt": "%Y-%m-%d %H:%M:%S" }, "json": { "()": "pythonjsonlogger.jsonlogger.JsonFormatter", "format": "[ %(asctime)s ] %(username)s %(message)s", "datefmt": "%Y-%m-%d %H:%M:%S", "json_indent": 4 } }, "handlers": { "mainlog": { "formatter": "strings", "level": "INFO", "class": "logging.handlers.RotatingFileHandler", "filename": "log/main.log", "backupCount": 2 }, "errorlog": { "formatter": "strings", "level": "ERROR", "class": "logging.handlers.RotatingFileHandler", "filename": "log/error.log", "backupCount": 2 }, "json": { "formatter": "json", "level": "INFO", "class": "logging.handlers.RotatingFileHandler", "filename": "log/usrlog.xml" } }, "loggers": { "simple": { "level": "DEBUG", "handlers": ["mainlog", "errorlog"] }, "usr_actions": { "level": "DEBUG", "handlers": ["json"] } } }
===== Примеры =====
:!: Минимальный пример для логирования import logging from datetime import datetime start_date = datetime.strftime(datetime.now(), "%Y%m%d_%H%M%S") log_path = f"{start_date}.log" #Настройка логирования. log = logging.getLogger() log.setLevel(logging.INFO) fh = logging.FileHandler(filename=log_path) fh.setLevel(logging.INFO) formatter = logging.Formatter(fmt='%(asctime)s %(levelname)s: %(message)s') fh.setFormatter(formatter) log.addHandler(fh) log.info("test test ")
:!: Еще примеры import logging logging.basicConfig( level=logging.DEBUG, filename = "mylog.log", format = "%(asctime)s - %(module)s - %(levelname)s - %(funcName)s: %(lineno)d - %(message)s", datefmt='%H:%M:%S', ) logging.info('Hello') import logging logging.basicConfig(level=logging.INFO, filename="py_log.log",filemode="w", format="%(asctime)s %(levelname)s %(message)s") x_vals = [2,3,6,4,10] y_vals = [5,7,12,0,1] for x_val,y_val in zip(x_vals,y_vals): x,y = x_val,y_val logging.info(f"The values of x and y are {x} and {y}.") try: x/y logging.info(f"x/y successful with result: {x/y}.") except ZeroDivisionError as err: #logging.exception("ZeroDivisionError") logging.error("ZeroDivisionError",exc_info=True) import logging from test_div import test_division # получение пользовательского логгера и установка уровня логирования py_logger = logging.getLogger(__name__) py_logger.setLevel(logging.INFO) # настройка обработчика и форматировщика в соответствии с нашими нуждами py_handler = logging.FileHandler(f"{__name__}.log", mode='w') py_formatter = logging.Formatter("%(name)s %(asctime)s %(levelname)s %(message)s") # добавление форматировщика к обработчику py_handler.setFormatter(py_formatter) # добавление обработчика к логгеру py_logger.addHandler(py_handler) py_logger.info(f"Testing the custom logger for module {__name__}...") x_vals = [2,3,6,4,10] y_vals = [5,7,12,0,1] for x_val,y_val in zip(x_vals,y_vals): x,y = x_val, y_val # вызов test_division test_division(x,y) py_logger.info(f"Call test_division with args {x} and {y}")