import sys import time import logging import logging.handlers import os import schedule import config from database import DatabaseManager from sd_api import ServiceDeskClient from sync_logic import Synchronizer def setup_logging(): """ Настраивает продвинутую конфигурацию логирования с ротацией файлов и разными уровнями для консоли и файла. """ # 1. Устанавливаем корневому логгеру самый низкий уровень (DEBUG). # Это позволяет хэндлерам самим решать, что пропускать. root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG) # 2. Создаем директорию для логов, если она не существует. try: if not os.path.exists(config.LOG_PATH): os.makedirs(config.LOG_PATH) except OSError as e: print(f"Ошибка создания директории для логов {config.LOG_PATH}: {e}") # В случае ошибки выходим, т.к. логирование в файл не будет работать sys.exit(1) # 3. Настраиваем форматтер для логов. log_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 4. Настраиваем хэндлер для вывода в консоль (уровень INFO). console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(logging.INFO) console_handler.setFormatter(log_formatter) # 5. Настраиваем хэндлер для записи в файл с ежедневной ротацией (уровень DEBUG). # Файлы будут вида sync_service.log, sync_service.log.2023-10-27 и т.д. log_file = os.path.join(config.LOG_PATH, 'sync_service.log') file_handler = logging.handlers.TimedRotatingFileHandler( log_file, when='midnight', # Ротация в полночь interval=1, # Каждый день backupCount=7, # Хранить 7 старых файлов encoding='utf-8' ) file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(log_formatter) # 6. Добавляем оба хэндлера к корневому логгеру. root_logger.addHandler(console_handler) root_logger.addHandler(file_handler) # 7. Отключаем слишком "болтливые" логи от сторонних библиотек. logging.getLogger("requests").setLevel(logging.WARNING) logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("schedule").setLevel(logging.INFO) def job(): """ Основная задача, которую будет выполнять планировщик. """ log = logging.getLogger(__name__) log.info("Запуск задачи синхронизации...") try: # Инициализация всех компонентов db_manager = DatabaseManager(config.DB_FULL_PATH) sd_client = ServiceDeskClient(config.SD_ACCESS_KEY, config.SD_BASE_URL) # Контекстный менеджер для БД гарантирует открытие/закрытие соединения with db_manager as db: # Перед первым запуском создаем таблицы, если их нет db.setup_tables() synchronizer = Synchronizer(db, sd_client) synchronizer.run_full_sync() except Exception as e: log.critical(f"Произошла непредвиденная ошибка на верхнем уровне: {e}", exc_info=True) if __name__ == '__main__': setup_logging() main_log = logging.getLogger(__name__) # --- Первоначальный запуск --- # Можно запустить один раз при старте, чтобы не ждать первого интервала main_log.info("Первый запуск сервиса...") job() # --- Настройка расписания --- # В вашем коде было 3 минуты, можно настроить как угодно sync_interval_minutes = 15 main_log.info(f"Сервис запущен. Синхронизация будет выполняться каждые {sync_interval_minutes} минут.") schedule.every(sync_interval_minutes).minutes.do(job) while True: schedule.run_pending() time.sleep(1)