Fix logger system

Remove someuseless function
This commit is contained in:
Udo Chudo 2024-07-29 15:22:12 +05:00
parent 2d4d3f265e
commit b719850b15
4 changed files with 158 additions and 42 deletions

6
.dockerignore Normal file
View File

@ -0,0 +1,6 @@
/TODO.txt
/venv/
/.idea
/.env
/.gitignore
/.git

View File

@ -1,9 +1,23 @@
FROM python:3.11.9-slim
LABEL authors="UdoChudo"
# Установим необходимые пакеты
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Установим рабочую директорию
WORKDIR /app
# Скопируем файлы проекта
COPY . /app
RUN pip install gunicorn
RUN pip install --no-cache-dir -r requests.txt
# Установим зависимости проекта
RUN pip install --no-cache-dir -r requirements.txt
# Откроем порт для нашего приложения
EXPOSE 5000
ENV FLASK_APP=telezab.py
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "telezab:app"]
# Запуск Gunicorn
CMD ["python3", "telezab.py"]

View File

@ -1,23 +1,25 @@
anyio==4.4.0
aiohttp==3.9.5
aiosignal==1.3.1
attrs==23.2.0
blinker==1.8.2
certifi==2024.6.2
certifi==2024.7.4
charset-normalizer==3.3.2
click==8.1.7
colorama==0.4.6
Flask==3.0.3
h11==0.14.0
httpcore==1.0.5
httpx==0.27.0
frozenlist==1.4.1
idna==3.7
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==2.1.5
multidict==6.0.5
packaging==24.1
pyTelegramBotAPI==4.19.2
pika==1.3.2
pyTelegramBotAPI==4.21.0
python-dotenv==1.0.1
python-telegram-bot==21.3
pyzabbix==1.3.1
requests==2.32.3
sniffio==1.3.1
telebot==0.0.5
urllib3==2.2.2
Werkzeug==3.0.3
yarl==1.9.4

View File

@ -14,7 +14,7 @@ import pika
import json
from concurrent.futures import ThreadPoolExecutor
from pyzabbix import ZabbixAPI
import requests # Добавлено для имитации POST запроса
import requests
# Load environment variables
load_dotenv()
@ -27,19 +27,72 @@ if DEBUG_LOGGING:
else:
log_level = 'INFO'
# Чтение переменных окружения
ENABLE_CONSOLE_LOGGING = os.getenv('ENABLE_CONSOLE_LOGGING', 'true').lower() in ['true', '1', 'yes']
ENABLE_WSGI_LOGGING = os.getenv('ENABLE_WSGI_LOGGING', 'true').lower() in ['true', '1', 'yes']
ENABLE_FILE_LOGGING_CONSOLE = os.getenv('ENABLE_FILE_LOGGING_CONSOLE', 'false').lower() in ['true', '1', 'yes']
ENABLE_FILE_LOGGING_FLASK = os.getenv('ENABLE_FILE_LOGGING_FLASK', 'false').lower() in ['true', '1', 'yes']
# Определение путей для файлов логирования
LOG_PATH_CONSOLE = os.getenv('LOG_PATH_CONSOLE', 'logs/console.log')
LOG_PATH_FLASK = os.getenv('LOG_PATH_FLASK', 'logs/flask.log')
# Создание директории для логов, если она не существует
os.makedirs(os.path.dirname(LOG_PATH_CONSOLE), exist_ok=True)
os.makedirs(os.path.dirname(LOG_PATH_FLASK), exist_ok=True)
# Определение обработчиков на основе переменных окружения
handlers = {}
if ENABLE_CONSOLE_LOGGING:
handlers['console'] = {
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout', # Вывод в консоль
'formatter': 'console',
}
if ENABLE_WSGI_LOGGING:
handlers['wsgi'] = {
'class': 'logging.StreamHandler',
'stream': 'ext://flask.logging.wsgi_errors_stream', # Логирование ошибок WSGI
'formatter': 'flask',
}
if ENABLE_FILE_LOGGING_CONSOLE:
handlers['file_console'] = {
'class': 'logging.FileHandler',
'filename': LOG_PATH_CONSOLE,
'formatter': 'console',
}
if ENABLE_FILE_LOGGING_FLASK:
handlers['file_flask'] = {
'class': 'logging.FileHandler',
'filename': LOG_PATH_FLASK,
'formatter': 'flask',
}
dictConfig({
'version': 1,
'formatters': {'default': {
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
}},
'handlers': {'wsgi': {
'class': 'logging.StreamHandler',
'stream': 'ext://flask.logging.wsgi_errors_stream',
'formatter': 'default'
}},
'formatters': {
'default': {
'format': '[%(asctime)s] %(levelname)s %(module)s: %(message)s [Location: %(extra)s]',
},
'console': {
'format': '[Location: console] [%(asctime)s] %(levelname)s %(module)s: %(message)s ',
},
'flask': {
'format': '[Location: flask] [%(asctime)s] %(levelname)s %(module)s: %(message)s ',
},
},
'handlers': handlers,
'loggers': {
'werkzeug': { # Flask логер
'level': 'INFO',
'handlers': ['console'] if ENABLE_CONSOLE_LOGGING else [],
'propagate': False,
'formatter': 'flask',
}
},
'root': {
'level': log_level,
'handlers': ['wsgi']
'level': 'INFO',
'handlers': [handler for handler in handlers.keys()],
}
})
@ -257,6 +310,11 @@ def cancel_settings_timer(chat_id):
user_timers[chat_id].cancel()
del user_timers[chat_id]
def reset_settings_timer(chat_id):
if chat_id in user_timers:
user_timers[chat_id].cancel()
start_settings_timer(chat_id)
def transition_to_notification_mode(chat_id):
set_user_state(chat_id, NOTIFICATION_MODE)
bot.send_message(chat_id, "Вы были автоматически переведены в режим получения уведомлений.")
@ -303,6 +361,7 @@ def handle_menu_selection(message):
text = message.text.strip().lower()
if user_states.get(chat_id, NOTIFICATION_MODE) == SETTINGS_MODE:
reset_settings_timer(chat_id)
handle_settings_menu_selection(message)
else:
if text == 'регистрация':
@ -323,6 +382,8 @@ def handle_settings_menu_selection(message):
chat_id = message.chat.id
text = message.text.strip().lower()
reset_settings_timer(chat_id)
if text == 'подписаться':
handle_subscribe(message)
elif text == 'отписаться':
@ -535,9 +596,18 @@ def process_add_region(message):
@bot.callback_query_handler(func=lambda call: call.data.startswith("replace_") or call.data.startswith("reactivate_"))
def handle_region_action(call):
action, region_id, region_name = call.data.split("_", 2)
parts = call.data.split("_", 2)
action = parts[0]
region_id = parts[1]
region_name = parts[2] if len(parts) > 2 else None
chat_id = call.message.chat.id
if not region_name:
bot.send_message(chat_id, "Ошибка: Недостаточно данных для выполнения действия.")
bot.answer_callback_query(call.id) # Завершение обработки callback
bot.delete_message(chat_id, call.message.message_id)
return show_settings_menu(chat_id)
with db_lock:
conn = sqlite3.connect('telezab.db')
cursor = conn.cursor()
@ -556,6 +626,7 @@ def handle_region_action(call):
conn.commit()
conn.close()
bot.answer_callback_query(call.id) # Завершение обработки callback
show_settings_menu(chat_id)
def process_remove_region(message):
@ -654,16 +725,19 @@ def handle_active_regions(message):
bot.send_message(chat_id, f"Активные регионы:\n{regions_list}")
show_settings_menu(chat_id)
# RabbitMQ configuration
RABBITMQ_HOST = os.getenv('RABBITMQ_HOST', 'localhost')
RABBITMQ_QUEUE = 'telegram_notifications'
def rabbitmq_connection():
connection = pika.BlockingConnection(pika.ConnectionParameters(RABBITMQ_HOST))
channel = connection.channel()
channel.queue_declare(queue=RABBITMQ_QUEUE, durable=True)
return connection, channel
def send_to_queue(message):
connection, channel = rabbitmq_connection()
channel.basic_publish(
@ -675,6 +749,7 @@ def send_to_queue(message):
))
connection.close()
async def consume_from_queue():
connection, channel = rabbitmq_connection()
@ -693,6 +768,7 @@ async def consume_from_queue():
connection.close()
async def send_message(chat_id, message, is_notification=False):
try:
if is_notification:
@ -712,14 +788,17 @@ async def send_message(chat_id, message, is_notification=False):
if is_notification:
rate_limit_semaphore.release()
async def send_notification_message(chat_id, message):
await send_message(chat_id, message, is_notification=True)
async def run_in_executor(func, *args):
loop = asyncio.get_event_loop()
with ThreadPoolExecutor() as pool:
return await loop.run_in_executor(pool, func, *args)
async def check_telegram_api():
try:
async with aiohttp.ClientSession() as session:
@ -731,6 +810,7 @@ async def check_telegram_api():
except Exception as e:
app.logger.error(f"Error checking Telegram API: {e}")
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
@ -777,6 +857,7 @@ def webhook():
return jsonify({"status": "success"}), 200
def format_message(data):
return (f"Zabbix Alert\n"
f"Host: {data['host']}\n"
@ -784,6 +865,7 @@ def format_message(data):
f"Trigger: {data['trigger']}\n"
f"Value: {data['value']}")
# Handle active triggers
def handle_active_triggers(message):
chat_id = message.chat.id
@ -794,6 +876,7 @@ def handle_active_triggers(message):
markup = create_region_markup(regions, start_index, regions_per_page)
bot.send_message(chat_id, "По какому региону хотите получить активные проблемы:", reply_markup=markup)
def create_region_markup(regions, start_index, regions_per_page):
markup = telebot.types.InlineKeyboardMarkup()
end_index = min(start_index + regions_per_page, len(regions))
@ -812,18 +895,22 @@ def create_region_markup(regions, start_index, regions_per_page):
markup.row(*row_buttons)
return markup
@bot.callback_query_handler(func=lambda call: call.data.startswith("region_"))
def handle_region_selection(call):
region_id = call.data.split("_")[1]
chat_id = call.message.chat.id
# Mocking the Zabbix triggers for the given region_id
triggers = get_mocked_zabbix_triggers(region_id)
# Получение триггеров из реального Zabbix API
triggers = get_zabbix_triggers(region_id)
if not triggers:
bot.send_message(chat_id, "Нет активных проблем по указанному региону за последние 24 часа.")
else:
bot.send_message(chat_id, triggers, parse_mode="Markdown")
bot.answer_callback_query(call.id) # Завершение обработки callback
@bot.callback_query_handler(func=lambda call: call.data.startswith("prev_") or call.data.startswith("next_"))
def handle_pagination(call):
direction, index = call.data.split("_")
@ -839,22 +926,25 @@ def handle_pagination(call):
markup = create_region_markup(regions, start_index, regions_per_page)
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=markup)
def get_mocked_zabbix_triggers(region_id):
# Mocked Zabbix triggers
triggers = [
{
"triggerid": "1",
"description": f"Проблема {region_id}-1",
"priority": "4",
"hosts": [{"hostid": region_id, "name": f"Хост {region_id}-1"}]
},
{
"triggerid": "2",
"description": f"Проблема {region_id}-2",
"priority": "5",
"hosts": [{"hostid": region_id, "name": f"Хост {region_id}-2"}]
}
]
bot.answer_callback_query(call.id) # Завершение обработки callback
# Функция для получения активных триггеров из Zabbix API
def get_zabbix_triggers(region_id):
zapi = ZabbixAPI(ZABBIX_URL)
zapi.login(api_token=ZABBIX_API_TOKEN)
# Получение триггеров уровня "Высокая" и "Авария" за последние 24 часа
triggers = zapi.trigger.get(
output=["triggerid", "description", "priority"],
selectHosts=["hostid", "name"],
filter={"priority": ["4", "5"], "value": "1"},
search={"host": region_id},
only_true=1,
active=1,
withLastEventUnacknowledged=1,
limit=100
)
priority_map = {
'4': 'Высокая',
@ -872,6 +962,7 @@ def get_mocked_zabbix_triggers(region_id):
return "\n\n---\n\n".join(trigger_messages)
# Test functions for admin
def simulate_event(message):
chat_id = message.chat.id
@ -888,12 +979,13 @@ def simulate_event(message):
app.logger.info(f"Response from webhook: {response.status_code} - {response.text}")
bot.send_message(chat_id, f"Тестовое событие отправлено. Статус ответа: {response.status_code}")
def simulate_triggers(message):
chat_id = message.chat.id
regions = ["12", "19", "35", "40"]
trigger_messages = []
for region_id in regions:
triggers = get_mocked_zabbix_triggers(region_id)
triggers = get_zabbix_triggers(region_id)
if triggers:
trigger_messages.append(f"Регион {region_id}:\n{triggers}")
@ -902,9 +994,11 @@ def simulate_triggers(message):
else:
bot.send_message(chat_id, "Нет активных проблем по указанным регионам за последние 24 часа.")
def run_polling():
bot.polling(none_stop=True, interval=0)
if __name__ == '__main__':
init_db()