Add Log rotation

Add logging for Telebot and Flask
Add routing for Enable debugging for Flask and Telebot separately
This commit is contained in:
Влад Зверев 2024-08-02 11:09:40 +05:00
parent 41487ef5c6
commit 730de38cee

View File

@ -1,8 +1,10 @@
import os
from flask import Flask, request, jsonify
import telebot
import schedule
from dotenv import load_dotenv
import hashlib
import telebot
from telebot import logger
import logging
from logging.config import dictConfig
import zipfile
@ -23,21 +25,6 @@ import re
# Load environment variables
load_dotenv()
# Read environment variables for logging configuration
ENABLE_CONSOLE_LOGGING = os.getenv('ENABLE_CONSOLE_LOGGING', 'true').lower() in ['true', '1', 'yes']
ENABLE_FILE_LOGGING = os.getenv('ENABLE_FILE_LOGGING', 'true').lower() in ['true', '1', 'yes']
# Define log paths
LOG_PATH_ERRORS = os.getenv('LOG_PATH_ERRORS', 'logs/errors.log')
LOG_PATH_EVENTS = os.getenv('LOG_PATH_EVENTS', 'logs/events.log')
LOG_PATH_FLASK = os.getenv('LOG_PATH_FLASK', 'logs/flask.log')
LOG_ARCHIVE_PATH = os.getenv('LOG_ARCHIVE_PATH', 'logs/archive')
# Create log directories if they do not exist
os.makedirs(os.path.dirname(LOG_PATH_ERRORS), exist_ok=True)
os.makedirs(os.path.dirname(LOG_PATH_EVENTS), exist_ok=True)
os.makedirs(LOG_ARCHIVE_PATH, exist_ok=True)
class UTF8StreamHandler(logging.StreamHandler):
def __init__(self, stream=None):
super().__init__(stream)
@ -48,120 +35,90 @@ class UTF8StreamHandler(logging.StreamHandler):
if hasattr(stream, 'reconfigure'):
stream.reconfigure(encoding='utf-8')
# Конфигурация логирования
handlers = {}
if ENABLE_CONSOLE_LOGGING:
handlers['console'] = {
'class': 'telezab.UTF8StreamHandler',
'stream': 'ext://sys.stdout', # Вывод в консоль
'formatter': 'console',
}
if ENABLE_FILE_LOGGING:
handlers['file_errors'] = {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': LOG_PATH_ERRORS,
'when': 'midnight',
'interval': 1,
'backupCount': 7,
'formatter': 'error',
'encoding': 'utf-8', # Убедитесь, что используется кодировка UTF-8
}
handlers['file_events'] = {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': LOG_PATH_EVENTS,
'when': 'midnight',
'interval': 1,
'backupCount': 7,
'formatter': 'event',
'encoding': 'utf-8', # Убедитесь, что используется кодировка UTF-8
}
# Configure Flask logger
flask_handlers = {
'flask': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': LOG_PATH_FLASK,
'when': 'midnight',
'interval': 1,
'backupCount': 7,
'formatter': 'default',
'encoding': 'utf-8',
}
}
# Include flask_handlers in dictConfig
# Определение пути к основному лог-файлу
LOG_FILE = 'logs/app.log'
# Определение функции архивирования логов
def archive_old_logs():
# Получаем дату предыдущего дня
yesterday_date = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
# Проверяем существует ли основной лог-файл
if os.path.exists(LOG_FILE):
# Путь к архиву в той же папке
archive_name = f"app_{yesterday_date}.zip"
archive_path = os.path.join(os.path.dirname(LOG_FILE), archive_name)
# Создание архива и добавление лог-файла
with zipfile.ZipFile(archive_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
zipf.write(LOG_FILE, arcname=os.path.basename(LOG_FILE))
# Удаление старого лог-файла после архивирования
os.remove(LOG_FILE)
class FilterByMessage(logging.Filter):
def filter(self, record):
# Фильтруем сообщения, содержащие 'Received 1 new updates'
return 'Received ' not in record.getMessage()
# Initialize Flask application
app = Flask(__name__)
# Настройка логирования
dictConfig({
'version': 1,
'formatters': {
'default': {
'format': '[%(asctime)s] %(levelname)s %(module)s: %(message)s',
},
},
'handlers': {
'console': {
'format': '[%(asctime)s] %(levelname)s %(module)s: %(message)s',
'class': 'telezab.UTF8StreamHandler', # Замените на путь к вашему классу UTF8StreamHandler
'stream': 'ext://sys.stdout', # Вывод в консоль
'formatter': 'default',
'filters': ['filter_by_message']
},
'error': {
'format': '[%(asctime)s] ERROR %(module)s: %(message)s',
},
'event': {
'format': '[%(asctime)s] EVENT %(module)s: %(message)s',
'file': {
'class': 'logging.FileHandler',
'filename': 'app.log', # Запись в файл
'formatter': 'default',
'encoding': 'utf-8', # Кодировка файла
},
},
'filters': {
'filter_by_message': {
'()': FilterByMessage,
},
},
'handlers': {**handlers, **flask_handlers},
'loggers': {
'default': {
'level': 'INFO',
'handlers': ['console', 'file_events'],
},
'error': {
'level': 'ERROR',
'handlers': ['console', 'file_errors'],
'propagate': False,
},
'flask': {
'level': 'INFO',
'handlers': ['flask'],
'level': 'DEBUG',
'handlers': ['console', 'file'],
'propagate': False,
}
},
'telebot': {
'level': 'DEBUG',
'handlers': ['console', 'file'],
'propagate': False,
},
},
'root': {
'level': 'INFO',
'handlers': ['console', 'file_events'],
'level': 'DEBUG',
'handlers': ['console', 'file'],
}
})
# Set Flask app logger to use the 'flask' logger
# Определение функции архивирования логов
def archive_old_logs():
yesterday_date = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
for log_file in [LOG_PATH_ERRORS, LOG_PATH_EVENTS]:
log_dir, log_filename = os.path.split(log_file)
for filename in os.listdir(log_dir):
if filename.startswith(log_filename) and filename != log_filename:
log_file_path = os.path.join(log_dir, filename)
archive_name = f"{log_filename}_{yesterday_date}.zip"
archive_path = os.path.join(LOG_ARCHIVE_PATH, archive_name)
with zipfile.ZipFile(archive_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
zipf.write(log_file_path, arcname=filename)
os.remove(log_file_path)
# Create loggers
logger = logging.getLogger('default')
error_logger = logging.getLogger('error')
# Call archive_old_logs function after logging setup
archive_old_logs()
# Initialize Flask application
app = Flask(__name__)
app.logger.handlers = []
app.logger.propagate = True
flask_logger = logging.getLogger('flask')
app.logger.addHandler(flask_logger.handlers[0])
# Настройка уровня логирования для Flask
app.logger.setLevel(logging.DEBUG)
# Настройка pyTelegramBotAPI logger
telebot.logger = logging.getLogger('telebot')
# Get the token from environment variables
TOKEN = os.getenv('TELEGRAM_TOKEN')
ZABBIX_URL = os.getenv('ZABBIX_URL')
@ -191,17 +148,22 @@ user_timers = {}
# Initialize SQLite database
def init_db():
global st
st = datetime.now()
try:
with db_lock:
conn = sqlite3.connect('telezab.db')
cursor = conn.cursor()
# Create events table
cursor.execute('''CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hash TEXT UNIQUE,
data TEXT,
delivered BOOLEAN)''')
# Create subscriptions table with username and active flag
cursor.execute('''CREATE TABLE IF NOT EXISTS subscriptions (
chat_id INTEGER,
region_id TEXT,
@ -209,29 +171,39 @@ def init_db():
active BOOLEAN DEFAULT TRUE,
skip BOOLEAN DEFAULT FALSE,
UNIQUE(chat_id, region_id))''')
# Create whitelist table
cursor.execute('''CREATE TABLE IF NOT EXISTS whitelist (
chat_id INTEGER PRIMARY KEY)''')
# Create regions table with active flag
cursor.execute('''CREATE TABLE IF NOT EXISTS regions (
region_id TEXT PRIMARY KEY,
region_name TEXT,
active BOOLEAN DEFAULT TRUE)''')
# Create user events table for logging
cursor.execute('''CREATE TABLE IF NOT EXISTS user_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chat_id INTEGER,
username TEXT,
action TEXT,
timestamp TEXT)''')
# Insert sample regions
cursor.execute('''INSERT OR IGNORE INTO regions (region_id, region_name) VALUES
('01', 'Адыгея'),
('02', 'Башкортостан (Уфа)'),
('04', 'Алтай'),
('19', 'Республика Хакасия')''')
conn.commit()
logger.info("Database initialized successfully.")
app.logger.info("Database initialized successfully.")
except Exception as e:
error_logger.error(f"Error initializing database: {e}")
app.logger.error(f"Error initializing database: {e}")
finally:
conn.close()
app.logger.info(f"init_db completed in {datetime.now() - st}")
# Hash the incoming data
@ -245,7 +217,7 @@ def is_whitelisted(chat_id):
conn = sqlite3.connect('telezab.db')
cursor = conn.cursor()
query = 'SELECT COUNT(*) FROM whitelist WHERE chat_id = ?'
app.logger.debug(f"Executing query: {query} with chat_id={chat_id}")
telebot.logger.debug(f"Executing query: {query} with chat_id={chat_id}")
cursor.execute(query, (chat_id,))
count = cursor.fetchone()[0]
conn.close()
@ -258,7 +230,7 @@ def add_to_whitelist(chat_id, username):
conn = sqlite3.connect('telezab.db')
cursor = conn.cursor()
query = 'INSERT OR IGNORE INTO whitelist (chat_id, username) VALUES (?, ?)'
app.logger.debug(f"Executing query: {query} with chat_id={chat_id}, username={username}")
telebot.logger.debug(f"Executing query: {query} with chat_id={chat_id}, username={username}")
cursor.execute(query, (chat_id, username))
conn.commit()
conn.close()
@ -270,7 +242,7 @@ def remove_from_whitelist(chat_id):
conn = sqlite3.connect('telezab.db')
cursor = conn.cursor()
query = 'DELETE FROM whitelist WHERE chat_id = ?'
app.logger.debug(f"Executing query: {query} with chat_id={chat_id}")
telebot.logger.debug(f"Executing query: {query} with chat_id={chat_id}")
cursor.execute(query, (chat_id,))
conn.commit()
conn.close()
@ -355,12 +327,12 @@ def log_user_event(chat_id, username, action):
conn = sqlite3.connect('telezab.db')
cursor = conn.cursor()
query = 'INSERT INTO user_events (chat_id, username, action, timestamp) VALUES (?, ?, ?, ?)'
logger.debug(f"Executing query: {query} with chat_id={chat_id}, username={username}, action={action}, timestamp={timestamp}")
telebot.logger.debug(f"Executing query: {query} with chat_id={chat_id}, username={username}, action={action}, timestamp={timestamp}")
cursor.execute(query, (chat_id, username, action, timestamp))
conn.commit()
logger.info(f"User event logged: {chat_id} ({username}) - {action} at {timestamp}.")
telebot.logger.info(f"User event logged: {chat_id} ({username}) - {action} at {timestamp}.")
except Exception as e:
error_logger.error(f"Error logging user event: {e}")
telebot.logger.error(f"Error logging user event: {e}")
finally:
conn.close()
@ -397,7 +369,8 @@ def reset_settings_timer(chat_id):
def transition_to_notification_mode(chat_id):
set_user_state(chat_id, NOTIFICATION_MODE)
bot.send_message(chat_id, "Вы были автоматически переведены в режим получения уведомлений.")
app.logger.info(f"User {chat_id} automatically transitioned to notification mode.")
show_main_menu(chat_id)
telebot.logger.info(f"User {chat_id} automatically transitioned to notification mode.")
# Main menu for users
@ -434,7 +407,7 @@ def handle_start(message):
set_user_state(chat_id, NOTIFICATION_MODE)
show_main_menu(chat_id)
app.logger.info(f"User {chat_id} ({username}) started with command /start.")
telebot.logger.info(f"User {chat_id} ({username}) started with command /start.")
# Handle menu button presses
@ -498,7 +471,7 @@ def handle_subscribe(message):
chat_id = message.chat.id
if not is_whitelisted(chat_id):
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
app.logger.info(f"Unauthorized access attempt by {chat_id}")
telebot.logger.info(f"Unauthorized access attempt by {chat_id}")
return
username = message.from_user.username
@ -529,16 +502,16 @@ def process_subscription(message, chat_id, username):
bot.send_message(chat_id, f"Регион с ID {region_id} не существует или недопустимый формат. Введите только существующие номера регионов.")
return show_settings_menu(chat_id)
query = 'INSERT OR IGNORE INTO subscriptions (chat_id, region_id, username, active) VALUES (?, ?, ?, TRUE)'
app.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}, username={username}")
telebot.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}, username={username}")
cursor.execute(query, (chat_id, region_id, username))
if cursor.rowcount == 0:
query = 'UPDATE subscriptions SET active = TRUE WHERE chat_id = ? AND region_id = ?'
app.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}")
cursor.execute(query, (chat_id, region_id))
conn.commit()
conn.close()
bot.send_message(chat_id, f"Подписка на регионы: {', '.join(region_ids)} оформлена.")
app.logger.info(f"User {chat_id} ({username}) subscribed to regions: {', '.join(region_ids)}.")
telebot.logger.info(f"User {chat_id} ({username}) subscribed to regions: {', '.join(region_ids)}.")
log_user_event(chat_id, username, f"Subscribed to regions: {', '.join(region_ids)}")
show_settings_menu(chat_id)
@ -549,7 +522,7 @@ def handle_unsubscribe(message):
chat_id = message.chat.id
if not is_whitelisted(chat_id):
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
app.logger.info(f"Unauthorized access attempt by {chat_id}")
telebot.logger.info(f"Unauthorized access attempt by {chat_id}")
return
user_regions = get_user_subscribed_regions(chat_id)
@ -562,6 +535,7 @@ def handle_unsubscribe(message):
bot.register_next_step_handler_by_chat_id(chat_id, process_unsubscription, chat_id)
# Пример функции, которая использует bot и log
def process_unsubscription(message, chat_id):
if message.text.lower() == 'отмена':
bot.send_message(chat_id, "Действие отменено.")
@ -579,13 +553,13 @@ def process_unsubscription(message, chat_id):
bot.send_message(chat_id, f"Регион с ID {region_id} не существует или недопустимый формат. Введите только номера регионов, на которые вы подписаны.")
return show_settings_menu(chat_id)
query = 'UPDATE subscriptions SET active = FALSE WHERE chat_id = ? AND region_id = ?'
app.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with chat_id={chat_id}, region_id={region_id}")
cursor.execute(query, (chat_id, region_id))
conn.commit()
conn.close()
bot.send_message(chat_id, f"Отписка от регионов: {', '.join(region_ids)} оформлена.")
app.logger.info(f"User {chat_id} unsubscribed from regions: {', '.join(region_ids)}.")
username = message.from_user.username if message.from_user.username else "N/A"
telebot.logger.info(f"User {chat_id} unsubscribed from regions: {', '.join(region_ids)}.")
username = "@" + message.from_user.username if message.from_user.username else "N/A"
log_user_event(chat_id, username, f"Unsubscribed from regions: {', '.join(region_ids)}")
show_settings_menu(chat_id)
@ -663,7 +637,7 @@ def process_register(message, chat_id, username):
reply_markup=markup
)
bot.send_message(chat_id, "Запрос отправлен администратору для одобрения.")
app.logger.info(f"User {chat_id} ({username}) requested registration.")
telebot.logger.info(f"User {chat_id} ({username}) requested registration.")
else:
bot.send_message(chat_id, "Некорректный выбор. Регистрация отменена.")
show_main_menu(chat_id)
@ -688,17 +662,17 @@ def process_add_region(message):
conn = sqlite3.connect('telezab.db')
cursor = conn.cursor()
query = 'SELECT region_name, active FROM regions WHERE region_id = ?'
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with region_id={region_id}")
cursor.execute(query, (region_id,))
result = cursor.fetchone()
if result:
existing_region_name, active = result
if existing_region_name == region_name:
query = 'UPDATE regions SET active = TRUE WHERE region_id = ?'
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with region_id={region_id}")
cursor.execute(query, (region_id,))
bot.send_message(chat_id, f"Регион {region_id} - {region_name} активирован.")
app.logger.info(f"Admin {chat_id} reactivated region {region_id} - {region_name}.")
telebot.logger.info(f"Admin {chat_id} reactivated region {region_id} - {region_name}.")
else:
markup = telebot.types.InlineKeyboardMarkup()
markup.add(telebot.types.InlineKeyboardButton(text="Заменить", callback_data=f"replace_{region_id}_{region_name}"))
@ -707,10 +681,10 @@ def process_add_region(message):
bot.send_message(chat_id, f"Регион {region_id} уже существует с названием {existing_region_name}. Хотите заменить его или активировать старый регион?", reply_markup=markup)
else:
query = 'INSERT OR IGNORE INTO regions (region_id, region_name) VALUES (?, ?)'
app.logger.debug(f"Executing query: {query} with region_id={region_id}, region_name={region_name}")
telebot.logger.debug(f"Executing query: {query} with region_id={region_id}, region_name={region_name}")
cursor.execute(query, (region_id, region_name))
bot.send_message(chat_id, f"Регион {region_id} - {region_name} добавлен.")
app.logger.info(f"Admin {chat_id} added region {region_id} - {region_name}.")
telebot.logger.info(f"Admin {chat_id} added region {region_id} - {region_name}.")
conn.commit()
conn.close()
except (IndexError, ValueError):
@ -736,19 +710,19 @@ def handle_region_action(call):
cursor = conn.cursor()
if action == "replace":
query = 'UPDATE regions SET region_name = ?, active = TRUE WHERE region_id = ?'
app.logger.debug(f"Executing query: {query} with region_name={region_name}, region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with region_name={region_name}, region_id={region_id}")
cursor.execute(query, (region_name, region_id))
bot.send_message(chat_id, f"Регион {region_id} обновлен до {region_name} и активирован.")
app.logger.info(f"Admin {chat_id} replaced and reactivated region {region_id} with {region_name}.")
telebot.logger.info(f"Admin {chat_id} replaced and reactivated region {region_id} with {region_name}.")
elif action == "reactivate":
query = 'UPDATE regions SET active = TRUE WHERE region_id = ?'
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with region_id={region_id}")
cursor.execute(query, (region_id,))
bot.send_message(chat_id, f"Регион {region_id} активирован.")
app.logger.info(f"Admin {chat_id} reactivated region {region_id}.")
telebot.logger.info(f"Admin {chat_id} reactivated region {region_id}.")
elif action == "cancel_region":
bot.send_message(chat_id, "Действие отменено.")
app.logger.info(f"Admin {chat_id} canceled region action.")
telebot.logger.info(f"Admin {chat_id} canceled region action.")
conn.commit()
conn.close()
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None)
@ -771,15 +745,15 @@ def process_remove_region(message):
return show_settings_menu(chat_id)
query = 'UPDATE regions SET active = FALSE WHERE region_id = ?'
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with region_id={region_id}")
cursor.execute(query, (region_id,))
query = 'UPDATE subscriptions SET active = FALSE WHERE region_id = ? AND active = TRUE'
app.logger.debug(f"Executing query: {query} with region_id={region_id}")
telebot.logger.debug(f"Executing query: {query} with region_id={region_id}")
cursor.execute(query, (region_id,))
conn.commit()
conn.close()
bot.send_message(chat_id, f"Регион {region_id} теперь неактивен и все активные подписки обновлены.")
app.logger.info(f"Admin {chat_id} set region {region_id} to inactive and updated subscriptions.")
telebot.logger.info(f"Admin {chat_id} set region {region_id} to inactive and updated subscriptions.")
except IndexError:
bot.send_message(chat_id, "Неверный формат. Используйте: <region_id>")
show_settings_menu(chat_id)
@ -789,7 +763,7 @@ def handle_my_subscriptions(message):
chat_id = message.chat.id
if not is_whitelisted(chat_id):
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
app.logger.info(f"Unauthorized access attempt by {chat_id}")
telebot.logger.info(f"Unauthorized access attempt by {chat_id}")
return
user_regions = get_user_subscribed_regions(chat_id)
@ -807,7 +781,7 @@ def handle_active_regions(message):
chat_id = message.chat.id
if not is_whitelisted(chat_id):
bot.send_message(chat_id, "Вы не авторизованы для использования этого бота.")
app.logger.info(f"Unauthorized access attempt by {chat_id}")
telebot.logger.info(f"Unauthorized access attempt by {chat_id}")
return
regions = get_sorted_regions() # Используем функцию для получения отсортированных регионов
@ -855,7 +829,7 @@ async def consume_from_queue():
await send_notification_message(chat_id, message_text)
channel.basic_ack(method_frame.delivery_tag)
except Exception as e:
app.logger.error(f"Error sending message from queue: {e}")
telebot.logger.error(f"Error sending message from queue: {e}")
# Optionally, you can nack the message to requeue it
# channel.basic_nack(method_frame.delivery_tag)
@ -869,13 +843,13 @@ async def send_message(chat_id, message, is_notification=False):
await run_in_executor(bot.send_message, chat_id, message)
except telebot.apihelper.ApiTelegramException as e:
if "429" in str(e):
app.logger.warning(f"Rate limit exceeded for chat_id {chat_id}. Retrying...")
telebot.logger.warning(f"Rate limit exceeded for chat_id {chat_id}. Retrying...")
await asyncio.sleep(1)
await send_message(chat_id, message, is_notification)
else:
app.logger.error(f"Failed to send message to {chat_id}: {e}")
telebot.logger.error(f"Failed to send message to {chat_id}: {e}")
except Exception as e:
app.logger.error(f"Error sending message to {chat_id}: {e}")
telebot.logger.error(f"Error sending message to {chat_id}: {e}")
await check_telegram_api()
finally:
if is_notification:
@ -897,11 +871,11 @@ async def check_telegram_api():
async with aiohttp.ClientSession() as session:
async with session.get('https://api.telegram.org') as response:
if response.status == 200:
app.logger.info("Telegram API is reachable.")
telebot.logger.info("Telegram API is reachable.")
else:
app.logger.error("Telegram API is not reachable.")
telebot.logger.error("Telegram API is not reachable.")
except Exception as e:
app.logger.error(f"Error checking Telegram API: {e}")
telebot.logger.error(f"Error checking Telegram API: {e}")
def extract_region_number(host):
@ -1029,6 +1003,48 @@ def add_user():
app.logger.error("Invalid data received for adding user.")
return jsonify({"status": "failure", "reason": "Invalid data"}), 400
# Обработчик для переключения уровня логирования Flask
@app.route('/debug/flask', methods=['POST'])
def toggle_flask_debug():
try:
data = request.get_json()
level = data.get('level', 'DEBUG').upper()
if level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']:
return jsonify({'status': 'error', 'message': 'Invalid log level'}), 400
log_level = getattr(logging, level, logging.DEBUG)
app.logger.setLevel(log_level)
# Обновление уровня логирования для каждого обработчика
for handler in app.logger.handlers:
handler.setLevel(log_level)
return jsonify({'status': 'success', 'level': level})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# Обработчик для переключения уровня логирования Telebot
@app.route('/debug/telebot', methods=['POST'])
def toggle_telebot_debug():
try:
data = request.get_json()
level = data.get('level', 'DEBUG').upper()
if level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']:
return jsonify({'status': 'error', 'message': 'Invalid log level'}), 400
log_level = getattr(logging, level, logging.DEBUG)
telebot.logger.setLevel(log_level)
# Обновление уровня логирования для каждого обработчика
for handler in telebot.logger.handlers:
handler.setLevel(log_level)
return jsonify({'status': 'success', 'level': level})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# Handle active triggers
def handle_active_triggers(message):
chat_id = message.chat.id
@ -1090,7 +1106,7 @@ def handle_region_selection(call):
bot.send_message(chat_id, f"Найдены следующие группы хостов для региона {region_id}:", reply_markup=markup)
except Exception as e:
logging.error(f"Error connecting to Zabbix API: {e}")
telebot.logger.error(f"Error connecting to Zabbix API: {e}")
bot.send_message(chat_id, "Не удалось подключиться к Zabbix API. Пожалуйста, попробуйте позже.")
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None)
@ -1113,7 +1129,7 @@ def handle_group_selection(call):
bot.send_message(chat_id, trigger, parse_mode="html")
time.sleep(1/5)
except Exception as e:
logging.error(f"Error processing group selection: {e}")
telebot.logger.error(f"Error processing group selection: {e}")
bot.send_message(chat_id, "Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже.")
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None)
@ -1219,7 +1235,7 @@ def get_zabbix_triggers(group_id):
return trigger_messages
except Exception as e:
logging.error(f"Error connecting to Zabbix API: {e}")
telebot.logger.error(f"Error connecting to Zabbix API: {e}")
return None
@ -1264,20 +1280,34 @@ def simulate_triggers(message):
def run_polling():
bot.polling(none_stop=True, interval=0)
bot.polling(non_stop=True, interval=0)
# Запуск Flask-приложения
def run_flask():
app.run(port=5000, host='0.0.0.0', debug=True, use_reloader=False)
if __name__ == '__main__':
def schedule_jobs():
schedule.every().day.at("00:00").do(archive_old_logs)
while True:
schedule.run_pending()
time.sleep(60) # Проверять раз в минуту
# Основная функция для запуска
def main():
# Инициализация базы данных
init_db()
print('Bootstrap wait...')
# Start Flask app in a separate thread
Thread(target=app.run, kwargs={'port': 5000, 'host': '0.0.0.0', 'debug': True, 'use_reloader': False}, daemon=True).start()
# Start bot polling in a separate thread
# Запуск Flask и бота в отдельных потоках
Thread(target=run_flask, daemon=True).start()
Thread(target=run_polling, daemon=True).start()
# Запуск планировщика задач в отдельном потоке
Thread(target=schedule_jobs, daemon=True).start()
# Запуск асинхронных задач
asyncio.run(consume_from_queue())
# Start async message consumer
loop = asyncio.get_event_loop()
loop.create_task(consume_from_queue())
loop.run_forever()
if __name__ == '__main__':
main()