145 lines
5.0 KiB
Python
145 lines
5.0 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
Мониторинг Redis Trigger в n8n
|
|||
|
|
Проверяет наличие подписчиков на канале ticket_form:description
|
|||
|
|
и отправляет алерт если подписчиков нет
|
|||
|
|
"""
|
|||
|
|
import redis
|
|||
|
|
import time
|
|||
|
|
import logging
|
|||
|
|
from datetime import datetime
|
|||
|
|
import sys
|
|||
|
|
|
|||
|
|
# Настройки
|
|||
|
|
REDIS_HOST = "crm.clientright.ru"
|
|||
|
|
REDIS_PORT = 6379
|
|||
|
|
REDIS_PASSWORD = "CRM_Redis_Pass_2025_Secure!"
|
|||
|
|
CHANNEL = "ticket_form:description"
|
|||
|
|
CHECK_INTERVAL = 60 # Проверка каждую минуту
|
|||
|
|
ALERT_THRESHOLD = 0 # Если подписчиков меньше этого значения - алерт
|
|||
|
|
|
|||
|
|
logging.basicConfig(
|
|||
|
|
level=logging.INFO,
|
|||
|
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
|||
|
|
handlers=[
|
|||
|
|
logging.FileHandler('/var/www/fastuser/data/www/crm.clientright.ru/ticket_form/logs/n8n_redis_monitor.log'),
|
|||
|
|
logging.StreamHandler(sys.stdout)
|
|||
|
|
]
|
|||
|
|
)
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def check_subscribers():
|
|||
|
|
"""Проверка количества подписчиков на канале"""
|
|||
|
|
try:
|
|||
|
|
r = redis.Redis(
|
|||
|
|
host=REDIS_HOST,
|
|||
|
|
port=REDIS_PORT,
|
|||
|
|
password=REDIS_PASSWORD,
|
|||
|
|
decode_responses=True,
|
|||
|
|
socket_connect_timeout=5,
|
|||
|
|
socket_timeout=5
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# Проверка подключения
|
|||
|
|
r.ping()
|
|||
|
|
|
|||
|
|
# Проверка подписчиков
|
|||
|
|
numsub = r.pubsub_numsub(CHANNEL)
|
|||
|
|
subscribers = numsub[0][1] if numsub else 0
|
|||
|
|
|
|||
|
|
logger.info(f"📊 Канал {CHANNEL}: {subscribers} подписчиков")
|
|||
|
|
|
|||
|
|
if subscribers <= ALERT_THRESHOLD:
|
|||
|
|
logger.warning(
|
|||
|
|
f"⚠️ ВНИМАНИЕ: На канале {CHANNEL} нет подписчиков! "
|
|||
|
|
f"n8n workflow может быть неактивен или завис."
|
|||
|
|
)
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
except redis.ConnectionError as e:
|
|||
|
|
logger.error(f"❌ Ошибка подключения к Redis: {e}")
|
|||
|
|
return False
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ Неожиданная ошибка: {e}")
|
|||
|
|
return False
|
|||
|
|
finally:
|
|||
|
|
try:
|
|||
|
|
r.close()
|
|||
|
|
except:
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
|
|||
|
|
def send_test_message():
|
|||
|
|
"""Отправка тестового сообщения для проверки"""
|
|||
|
|
try:
|
|||
|
|
r = redis.Redis(
|
|||
|
|
host=REDIS_HOST,
|
|||
|
|
port=REDIS_PORT,
|
|||
|
|
password=REDIS_PASSWORD,
|
|||
|
|
decode_responses=True,
|
|||
|
|
socket_connect_timeout=5,
|
|||
|
|
socket_timeout=5
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
test_message = {
|
|||
|
|
"type": "test",
|
|||
|
|
"session_id": "monitor_test",
|
|||
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|||
|
|
"message": "Health check from monitor script"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
import json
|
|||
|
|
subscribers = r.publish(CHANNEL, json.dumps(test_message))
|
|||
|
|
logger.info(f"📤 Тестовое сообщение отправлено. Получено подписчиками: {subscribers}")
|
|||
|
|
|
|||
|
|
r.close()
|
|||
|
|
return subscribers > 0
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ Ошибка отправки тестового сообщения: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
"""Основной цикл мониторинга"""
|
|||
|
|
logger.info("🚀 Запуск мониторинга Redis Trigger для n8n")
|
|||
|
|
logger.info(f"📡 Канал: {CHANNEL}")
|
|||
|
|
logger.info(f"⏱️ Интервал проверки: {CHECK_INTERVAL} секунд")
|
|||
|
|
|
|||
|
|
consecutive_failures = 0
|
|||
|
|
max_failures = 3 # После 3 неудачных проверок подряд - критический алерт
|
|||
|
|
|
|||
|
|
while True:
|
|||
|
|
try:
|
|||
|
|
is_ok = check_subscribers()
|
|||
|
|
|
|||
|
|
if is_ok:
|
|||
|
|
consecutive_failures = 0
|
|||
|
|
else:
|
|||
|
|
consecutive_failures += 1
|
|||
|
|
|
|||
|
|
if consecutive_failures >= max_failures:
|
|||
|
|
logger.critical(
|
|||
|
|
f"🚨 КРИТИЧЕСКОЕ СОСТОЯНИЕ: "
|
|||
|
|
f"Канал {CHANNEL} не имеет подписчиков уже {consecutive_failures} проверок подряд! "
|
|||
|
|
f"Требуется перезапуск n8n workflow!"
|
|||
|
|
)
|
|||
|
|
# Можно добавить отправку уведомления (email, telegram, etc.)
|
|||
|
|
|
|||
|
|
time.sleep(CHECK_INTERVAL)
|
|||
|
|
|
|||
|
|
except KeyboardInterrupt:
|
|||
|
|
logger.info("⏹️ Остановка мониторинга по запросу пользователя")
|
|||
|
|
break
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ Критическая ошибка в цикле мониторинга: {e}")
|
|||
|
|
time.sleep(CHECK_INTERVAL)
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
main()
|
|||
|
|
|