add: логи внутри TUI

This commit is contained in:
2025-06-08 22:28:00 +03:00
parent e6dd940d8a
commit 22bd7ee303
3 changed files with 194 additions and 64 deletions

View File

@@ -3,69 +3,105 @@
import argparse
import logging
import sys
from config import load_config, ConfigError, ConfigNotFoundError, InvalidConfigFormatError
from tui import PGanecApp
from logging.handlers import MemoryHandler
from pganec.config import load_config, ConfigError, ConfigNotFoundError, InvalidConfigFormatError
from pganec.tui import PGanecApp
# --- Настройки и инициирование логирования ---
logger = logging.getLogger(__name__)
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press ⌘F8 to toggle the breakpoint.
# Press the green button in the gutter to run the script.
# --- Главная функция приложения ---
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="PGanec — TUI резервного копирования и восстановления баз PostgreSQL")
parser.add_argument("-c", "--config", required=True,
help="Путь к файлу конфигурации (YAML)")
parser.add_argument("-d", "--debug-level", default="QUIET",
parser.add_argument("-d", "--debug-level", default="INFO",
help="Уровень отладки (QUIET, NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL)")
parser.add_argument("-l", "--loging", default="",
help="Путь к файлу логирования (если не указан, логирование не будет вестись)")
args = parser.parse_args()
# Настройка отладочных логов
# --- Определение числового уровня логирования для передачи в TUI ---
level_input_str = args.debug_level.upper()
chosen_log_level = None
if level_input_str == "QUIET": # Опция "QUIET"
chosen_log_level = logging.CRITICAL + 1
else:
chosen_log_level = getattr(logging, level_input_str, None)
if chosen_log_level is None:
logger.warning(f"Неизвестный уровень отладки '{args.debug_level}'. Используется DEBUG.")
chosen_log_level = logging.DEBUG
log_level_to_pass = logging.INFO # Значение по умолчанию, если что-то пойдет не так
logging.basicConfig(
level=chosen_log_level,
format="%(asctime)s - %(name)s - %(levelname)s - %(module)s.%(funcName)s:%(lineno)d - %(message)s"
)
logger.debug(f"Параметрами: {args}")
logger.debug(f"Уровень: {chosen_log_level}")
if level_input_str == "QUIET":
log_level_to_pass = logging.CRITICAL + 1
else:
# Пытаемся получить числовое значение для стандартных уровней
parsed_level = getattr(logging, level_input_str, None)
if parsed_level is not None and isinstance(parsed_level, int):
log_level_to_pass = parsed_level
else:
# Если уровень не распознан, выводим предупреждение в stderr,
# так как logger.warning может быть еще не настроен для вывода.
print(f"Предупреждение: Неизвестный уровень логирования '{args.debug_level}'. "
f"Используется INFO по умолчанию.", file=sys.stderr)
log_level_to_pass = logging.INFO # Возвращаемся к INFO по умолчанию
# --- Настройка раннего логирования с MemoryHandler ---
# 1. Устанавливаем уровень корневого логгера, чтобы он пропускал нужные сообщения
root_logger = logging.getLogger()
root_logger.setLevel(log_level_to_pass) # Важно для MemoryHandler
# 2. Создаем MemoryHandler
# Он будет копить логи до момента, когда TUI сможет их отобразить.
# `capacity` - сколько записей хранить.
# `flushLevel` - уровень, при котором MemoryHandler попытается сбросить логи в target.
# Ставим очень высокий, чтобы он не сбрасывал сам по себе, т.к. target еще нет.
# `target` - пока None, установим его в TUI.
memory_handler = MemoryHandler(capacity=200, flushLevel=logging.CRITICAL + 10, target=None)
memory_handler.setLevel(logging.NOTSET) # MemoryHandler должен принимать все, что пропускает root_logger
# 3. Добавляем MemoryHandler к корневому логгеру
root_logger.addHandler(memory_handler)
logger.debug(
f"main.py: MemoryHandler добавлен. Log Level: '{logging.getLevelName(root_logger.getEffectiveLevel())}'")
logging.getLogger().setLevel(log_level_to_pass)
logger.debug(f"Запущено с параметрами: {args}")
logger.info(f"Задан уровень логирования: '{logging.getLevelName(log_level_to_pass)}'"
f" ({log_level_to_pass})")
# logging.basicConfig(
# level=chosen_log_level_int,
# format="%(asctime)s - %(name)s - %(levelname)s - %(module)s.%(funcName)s:%(lineno)d - %(message)s"
# )
# Загрузка конфигурации
config = None # Инициализируем config
try:
config = load_config(args.config)
logger.info(f"Конфигурация успешно загружена: {config}")
if config: # Добавим проверку, что config не None, если load_config может вернуть None при успехе (хотя по типу не должен)
logger.debug(
f"Конфигурация успешно загружена: {list(config.keys())}") # Логируем ключи, а не всю конфигурацию
else:
# Эта ситуация не должна возникать, если load_config выбрасывает исключения при ошибках
# или возвращает dict. Но для полноты.
print(f"Ошибка: Конфигурация не была загружена из '{args.config}', но исключение не было выброшено.",
file=sys.stderr)
sys.exit(1)
except ConfigNotFoundError:
print(f"Ошибка: Файл конфигурации '{args.config}' не найден.", file=sys.stderr)
# Возможно сюда стоит добавить TUI интерфейс для ввода (выбора) файла конфигурации...
# Но так как ошибка может быть связана с правами доступа (например, TUI запущен от неправильного
# пользователя), оставим идею "на-подумать", а пока просто завершим выполнение программы.
sys.exit(1)
except InvalidConfigFormatError as e:
print(f"Ошибка: Файл конфигурации '{args.config}' имеет неверный формат. {e}", file=sys.stderr)
sys.exit(1)
except ConfigError as e: # Общая ошибка конфигурации (должна быть последней в цепочке)
except ConfigError as e:
print(f"Ошибка при загрузке конфигурации: {e}", file=sys.stderr)
sys.exit(1)
except Exception as e: # Для совсем непредвиденных, не ConfigError
except Exception as e:
logger.critical(f"Необработанная ошибка во время инициализации: {e}", exc_info=True)
print(f"Произошла критическая и непредвиденная ошибка: {e}", file=sys.stderr)
sys.exit(2)
# Запуск главного меню TUI
PGanecApp().run()
# Запуск главного меню TUI с передачей числового уровня логирования
# app = PGanecApp(log_level_int=log_level_to_pass) # Передаем и конфигурацию
app = PGanecApp(log_level_int=log_level_to_pass, app_config=config, early_log_handler=memory_handler)
app.run()
# PGanecApp().run()