Dev 2 #2
35
Makefile
35
Makefile
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: help build up down logs clean restart status deploy backup restore update clean-monitoring monitoring check-deps check-bot-deps
|
.PHONY: help build up down logs clean restart status deploy backup restore update clean-monitoring monitoring check-deps check-bot-deps check-anonBot-deps
|
||||||
|
|
||||||
help: ## Показать справку
|
help: ## Показать справку
|
||||||
@echo "🏗️ Production Infrastructure - Доступные команды:"
|
@echo "🏗️ Production Infrastructure - Доступные команды:"
|
||||||
@@ -11,6 +11,7 @@ help: ## Показать справку
|
|||||||
@echo " Grafana: http://localhost:3000 (admin/admin)"
|
@echo " Grafana: http://localhost:3000 (admin/admin)"
|
||||||
@echo " Server Monitor: http://localhost:9091/health"
|
@echo " Server Monitor: http://localhost:9091/health"
|
||||||
@echo " Bot Health: http://localhost:8080/health"
|
@echo " Bot Health: http://localhost:8080/health"
|
||||||
|
@echo " AnonBot Health: http://localhost:8081/health"
|
||||||
|
|
||||||
build: ## Собрать все контейнеры
|
build: ## Собрать все контейнеры
|
||||||
docker-compose build
|
docker-compose build
|
||||||
@@ -36,6 +37,9 @@ logs-grafana: ## Показать логи Grafana
|
|||||||
logs-bot: ## Показать логи Telegram бота
|
logs-bot: ## Показать логи Telegram бота
|
||||||
docker-compose logs -f telegram-bot
|
docker-compose logs -f telegram-bot
|
||||||
|
|
||||||
|
logs-anonBot: ## Показать логи AnonBot
|
||||||
|
docker-compose logs -f anon-bot
|
||||||
|
|
||||||
restart: ## Перезапустить все сервисы
|
restart: ## Перезапустить все сервисы
|
||||||
docker-compose down
|
docker-compose down
|
||||||
docker-compose build --no-cache
|
docker-compose build --no-cache
|
||||||
@@ -53,12 +57,16 @@ restart-grafana: ## Перезапустить только Grafana
|
|||||||
restart-bot: ## Перезапустить только Telegram бота
|
restart-bot: ## Перезапустить только Telegram бота
|
||||||
docker-compose restart telegram-bot
|
docker-compose restart telegram-bot
|
||||||
|
|
||||||
|
restart-anonBot: ## Перезапустить только AnonBot
|
||||||
|
docker-compose restart anon-bot
|
||||||
|
|
||||||
status: ## Показать статус контейнеров
|
status: ## Показать статус контейнеров
|
||||||
docker-compose ps
|
docker-compose ps
|
||||||
|
|
||||||
health: ## Проверить здоровье сервисов
|
health: ## Проверить здоровье сервисов
|
||||||
@echo "🏥 Checking service health..."
|
@echo "🏥 Checking service health..."
|
||||||
@curl -f http://localhost:8080/health || echo "❌ Bot health check failed"
|
@curl -f http://localhost:8080/health || echo "❌ Bot health check failed"
|
||||||
|
@curl -f http://localhost:8081/health || echo "❌ AnonBot health check failed"
|
||||||
@curl -f http://localhost:9090/-/healthy || echo "❌ Prometheus health check failed"
|
@curl -f http://localhost:9090/-/healthy || echo "❌ Prometheus health check failed"
|
||||||
@curl -f http://localhost:3000/api/health || echo "❌ Grafana health check failed"
|
@curl -f http://localhost:3000/api/health || echo "❌ Grafana health check failed"
|
||||||
@curl -f http://localhost:9091/health || echo "❌ Server monitor health check failed"
|
@curl -f http://localhost:9091/health || echo "❌ Server monitor health check failed"
|
||||||
@@ -120,22 +128,26 @@ start: build up ## Собрать и запустить все сервисы
|
|||||||
@echo "📊 Prometheus: http://localhost:9090"
|
@echo "📊 Prometheus: http://localhost:9090"
|
||||||
@echo "📈 Grafana: http://localhost:3000 (admin/admin)"
|
@echo "📈 Grafana: http://localhost:3000 (admin/admin)"
|
||||||
@echo "🤖 Bot Health: http://localhost:8080/health"
|
@echo "🤖 Bot Health: http://localhost:8080/health"
|
||||||
|
@echo "🔒 AnonBot Health: http://localhost:8081/health"
|
||||||
@echo "📡 Server Monitor: http://localhost:9091/health"
|
@echo "📡 Server Monitor: http://localhost:9091/health"
|
||||||
@echo "📝 Логи: make logs"
|
@echo "📝 Логи: make logs"
|
||||||
|
|
||||||
stop: down ## Остановить все сервисы
|
stop: down ## Остановить все сервисы
|
||||||
@echo "🛑 Все сервисы остановлены"
|
@echo "🛑 Все сервисы остановлены"
|
||||||
|
|
||||||
test: check-deps check-bot-deps ## Запустить все тесты в проекте
|
test: check-deps check-bot-deps check-anonBot-deps ## Запустить все тесты в проекте
|
||||||
@echo "🧪 Запускаю все тесты в проекте..."
|
@echo "🧪 Запускаю все тесты в проекте..."
|
||||||
@echo "📊 Тесты инфраструктуры..."
|
@echo "📊 Тесты инфраструктуры..."
|
||||||
@python3 -m pytest tests/infra/ -q --tb=no
|
@python3 -m pytest tests/infra/ -q --tb=no
|
||||||
@echo "🤖 Тесты Telegram бота..."
|
@echo "🤖 Тесты Telegram бота..."
|
||||||
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -m pytest tests/ -q --tb=no
|
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -m pytest tests/ -q --tb=no
|
||||||
|
@echo "🔒 Тесты AnonBot..."
|
||||||
|
@cd bots/AnonBot && python3 -m pytest tests/ -q --tb=no
|
||||||
@echo "✅ Все тесты завершены!"
|
@echo "✅ Все тесты завершены!"
|
||||||
@echo "📈 Общая статистика:"
|
@echo "📈 Общая статистика:"
|
||||||
@echo " - Инфраструктура: $(shell python3 count_tests.py | head -1) тестов"
|
@echo " - Инфраструктура: $(shell python3 count_tests.py | head -1) тестов"
|
||||||
@echo " - Telegram бот: $(shell python3 count_tests.py | head -2 | tail -1) тестов"
|
@echo " - Telegram бот: $(shell python3 count_tests.py | head -2 | tail -1) тестов"
|
||||||
|
@echo " - AnonBot: $(shell python3 count_tests.py | head -3 | tail -1) тестов"
|
||||||
@echo " - Всего: $(shell python3 count_tests.py | tail -1) тестов"
|
@echo " - Всего: $(shell python3 count_tests.py | tail -1) тестов"
|
||||||
|
|
||||||
test-all: ## Запустить все тесты в одном процессе (только для разработчиков)
|
test-all: ## Запустить все тесты в одном процессе (только для разработчиков)
|
||||||
@@ -152,16 +164,23 @@ test-bot: check-bot-deps ## Запустить тесты Telegram бота
|
|||||||
@echo "🤖 Запускаю тесты Telegram бота..."
|
@echo "🤖 Запускаю тесты Telegram бота..."
|
||||||
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -m pytest tests/ -v
|
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -m pytest tests/ -v
|
||||||
|
|
||||||
test-coverage: check-deps check-bot-deps ## Запустить все тесты с отчетом о покрытии
|
test-anonBot: check-anonBot-deps ## Запустить тесты AnonBot
|
||||||
|
@echo "🔒 Запускаю тесты AnonBot..."
|
||||||
|
@cd bots/AnonBot && python3 -m pytest tests/ -v
|
||||||
|
|
||||||
|
test-coverage: check-deps check-bot-deps check-anonBot-deps ## Запустить все тесты с отчетом о покрытии
|
||||||
@echo "📊 Запускаю все тесты с отчетом о покрытии..."
|
@echo "📊 Запускаю все тесты с отчетом о покрытии..."
|
||||||
@echo "📈 Покрытие для инфраструктуры..."
|
@echo "📈 Покрытие для инфраструктуры..."
|
||||||
@python3 -m pytest tests/infra/ --cov=infra --cov-report=term-missing --cov-report=html:htmlcov/infra
|
@python3 -m pytest tests/infra/ --cov=infra --cov-report=term-missing --cov-report=html:htmlcov/infra
|
||||||
@echo "🤖 Покрытие для Telegram бота..."
|
@echo "🤖 Покрытие для Telegram бота..."
|
||||||
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -m pytest tests/ --cov=helper_bot --cov-report=term-missing --cov-report=html:htmlcov/bot
|
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -m pytest tests/ --cov=helper_bot --cov-report=term-missing --cov-report=html:htmlcov/bot
|
||||||
|
@echo "🔒 Покрытие для AnonBot..."
|
||||||
|
@cd bots/AnonBot && python3 -m pytest tests/ --cov=. --cov-report=term-missing --cov-report=html:htmlcov/anonbot
|
||||||
@echo "📊 Отчеты о покрытии сохранены в htmlcov/"
|
@echo "📊 Отчеты о покрытии сохранены в htmlcov/"
|
||||||
@echo "📈 Общая статистика:"
|
@echo "📈 Общая статистика:"
|
||||||
@echo " - Инфраструктура: $(shell python3 count_tests.py | head -1) тестов"
|
@echo " - Инфраструктура: $(shell python3 count_tests.py | head -1) тестов"
|
||||||
@echo " - Telegram бот: $(shell python3 count_tests.py | head -2 | tail -1) тестов"
|
@echo " - Telegram бот: $(shell python3 count_tests.py | head -2 | tail -1) тестов"
|
||||||
|
@echo " - AnonBot: $(shell python3 count_tests.py | head -3 | tail -1) тестов"
|
||||||
@echo " - Всего: $(shell python3 count_tests.py | tail -1) тестов"
|
@echo " - Всего: $(shell python3 count_tests.py | tail -1) тестов"
|
||||||
|
|
||||||
test-clean: ## Очистить все файлы тестирования и отчеты
|
test-clean: ## Очистить все файлы тестирования и отчеты
|
||||||
@@ -173,6 +192,9 @@ test-clean: ## Очистить все файлы тестирования и о
|
|||||||
@rm -rf bots/telegram-helper-bot/.pytest_cache/
|
@rm -rf bots/telegram-helper-bot/.pytest_cache/
|
||||||
@rm -rf bots/telegram-helper-bot/htmlcov/
|
@rm -rf bots/telegram-helper-bot/htmlcov/
|
||||||
@rm -rf bots/telegram-helper-bot/.coverage
|
@rm -rf bots/telegram-helper-bot/.coverage
|
||||||
|
@rm -rf bots/AnonBot/.pytest_cache/
|
||||||
|
@rm -rf bots/AnonBot/htmlcov/
|
||||||
|
@rm -rf bots/AnonBot/.coverage
|
||||||
@find . -name "*.pyc" -delete 2>/dev/null || true
|
@find . -name "*.pyc" -delete 2>/dev/null || true
|
||||||
@find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
@find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||||
@echo "✅ Файлы тестирования очищены"
|
@echo "✅ Файлы тестирования очищены"
|
||||||
@@ -187,6 +209,8 @@ check-ports: ## Проверить занятые порты
|
|||||||
@lsof -i :9091 2>/dev/null || echo " Free"
|
@lsof -i :9091 2>/dev/null || echo " Free"
|
||||||
@echo "Port 8080 (Telegram Bot):"
|
@echo "Port 8080 (Telegram Bot):"
|
||||||
@lsof -i :8080 2>/dev/null || echo " Free"
|
@lsof -i :8080 2>/dev/null || echo " Free"
|
||||||
|
@echo "Port 8081 (AnonBot):"
|
||||||
|
@lsof -i :8081 2>/dev/null || echo " Free"
|
||||||
|
|
||||||
check-grafana: ## Проверить состояние Grafana
|
check-grafana: ## Проверить состояние Grafana
|
||||||
@echo "📊 Checking Grafana status..."
|
@echo "📊 Checking Grafana status..."
|
||||||
@@ -202,6 +226,11 @@ check-bot-deps: ## Проверить зависимости Telegram бота
|
|||||||
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -c "import aiogram, aiosqlite, pytest" 2>/dev/null || (echo "❌ Отсутствуют зависимости бота. Установите: cd bots/telegram-helper-bot && source .venv/bin/activate && pip install -r requirements.txt" && exit 1)
|
@cd bots/telegram-helper-bot && source .venv/bin/activate && python3 -c "import aiogram, aiosqlite, pytest" 2>/dev/null || (echo "❌ Отсутствуют зависимости бота. Установите: cd bots/telegram-helper-bot && source .venv/bin/activate && pip install -r requirements.txt" && exit 1)
|
||||||
@echo "✅ Зависимости Telegram бота установлены"
|
@echo "✅ Зависимости Telegram бота установлены"
|
||||||
|
|
||||||
|
check-anonBot-deps: ## Проверить зависимости AnonBot
|
||||||
|
@echo "🔍 Проверяю зависимости AnonBot..."
|
||||||
|
@cd bots/AnonBot && python3 -c "import aiogram, aiosqlite, pytest, loguru, pydantic" 2>/dev/null || (echo "❌ Отсутствуют зависимости AnonBot. Установите: cd bots/AnonBot && pip install -r requirements.txt" && exit 1)
|
||||||
|
@echo "✅ Зависимости AnonBot установлены"
|
||||||
|
|
||||||
logs-tail: ## Показать последние логи всех сервисов
|
logs-tail: ## Показать последние логи всех сервисов
|
||||||
@echo "📝 Recent logs from all services:"
|
@echo "📝 Recent logs from all services:"
|
||||||
@docker-compose logs --tail=50
|
@docker-compose logs --tail=50
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
Скрипт для подсчета количества тестов в проекте
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
def count_tests_in_directory(directory):
|
|
||||||
"""Подсчитывает количество тестов в указанной директории"""
|
|
||||||
try:
|
|
||||||
# Запускаем pytest --collect-only для подсчета тестов
|
|
||||||
result = subprocess.run(
|
|
||||||
[sys.executable, '-m', 'pytest', directory, '--collect-only', '-q'],
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
cwd=os.getcwd()
|
|
||||||
)
|
|
||||||
|
|
||||||
if result.returncode == 0:
|
|
||||||
# Ищем строку с количеством собранных тестов
|
|
||||||
for line in result.stdout.split('\n'):
|
|
||||||
if 'collected' in line:
|
|
||||||
# Извлекаем число из строки вида "78 collected"
|
|
||||||
parts = line.strip().split()
|
|
||||||
for part in parts:
|
|
||||||
if part.isdigit():
|
|
||||||
return int(part)
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Ошибка при подсчете тестов в {directory}: {e}", file=sys.stderr)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def count_bot_tests():
|
|
||||||
"""Подсчитывает количество тестов бота"""
|
|
||||||
try:
|
|
||||||
# Переходим в директорию бота и запускаем pytest
|
|
||||||
bot_dir = os.path.join(os.getcwd(), 'bots', 'telegram-helper-bot')
|
|
||||||
result = subprocess.run(
|
|
||||||
[sys.executable, '-m', 'pytest', 'tests/', '--collect-only', '-q'],
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
cwd=bot_dir
|
|
||||||
)
|
|
||||||
|
|
||||||
if result.returncode == 0:
|
|
||||||
# Ищем строку с количеством собранных тестов
|
|
||||||
for line in result.stdout.split('\n'):
|
|
||||||
if 'collected' in line:
|
|
||||||
# Извлекаем число из строки вида "201 collected"
|
|
||||||
parts = line.strip().split()
|
|
||||||
for part in parts:
|
|
||||||
if part.isdigit():
|
|
||||||
return int(part)
|
|
||||||
return 0
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Ошибка при подсчете тестов бота: {e}", file=sys.stderr)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Основная функция"""
|
|
||||||
# Подсчитываем тесты инфраструктуры
|
|
||||||
infra_tests = count_tests_in_directory('tests/infra/')
|
|
||||||
|
|
||||||
# Подсчитываем тесты бота
|
|
||||||
bot_tests = count_bot_tests()
|
|
||||||
|
|
||||||
total_tests = infra_tests + bot_tests
|
|
||||||
|
|
||||||
# Выводим результат в формате для Makefile
|
|
||||||
print(f"{infra_tests}")
|
|
||||||
print(f"{bot_tests}")
|
|
||||||
print(f"{total_tests}")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -130,11 +130,64 @@ services:
|
|||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 512M
|
memory: 256M
|
||||||
cpus: '0.5'
|
cpus: '0.5'
|
||||||
reservations:
|
reservations:
|
||||||
|
memory: 128M
|
||||||
|
cpus: '0.25'
|
||||||
|
|
||||||
|
# AnonBot - Anonymous Q&A Bot
|
||||||
|
anon-bot:
|
||||||
|
build:
|
||||||
|
context: ./bots/AnonBot
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: bots_anon_bot
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- ./bots/AnonBot/.env
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
environment:
|
||||||
|
- PYTHONPATH=/app
|
||||||
|
- PYTHONUNBUFFERED=1
|
||||||
|
- DOCKER_CONTAINER=true
|
||||||
|
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
||||||
|
# AnonBot settings
|
||||||
|
- ANON_BOT_TOKEN=${BOT_TOKEN}
|
||||||
|
- ANON_BOT_ADMINS=${ADMINS}
|
||||||
|
- ANON_BOT_DATABASE_PATH=/app/database/anon_qna.db
|
||||||
|
- ANON_BOT_DEBUG=${DEBUG:-false}
|
||||||
|
- ANON_BOT_MAX_QUESTION_LENGTH=${MAX_QUESTION_LENGTH:-1000}
|
||||||
|
- ANON_BOT_MAX_ANSWER_LENGTH=${MAX_ANSWER_LENGTH:-2000}
|
||||||
|
# Rate limiting settings
|
||||||
|
- RATE_LIMIT_ENV=${RATE_LIMIT_ENV:-production}
|
||||||
|
- RATE_LIMIT_MESSAGES_PER_SECOND=${RATE_LIMIT_MESSAGES_PER_SECOND:-0.5}
|
||||||
|
- RATE_LIMIT_BURST_LIMIT=${RATE_LIMIT_BURST_LIMIT:-2}
|
||||||
|
- RATE_LIMIT_RETRY_MULTIPLIER=${RATE_LIMIT_RETRY_MULTIPLIER:-1.5}
|
||||||
|
- RATE_LIMIT_MAX_RETRY_DELAY=${RATE_LIMIT_MAX_RETRY_DELAY:-30.0}
|
||||||
|
- RATE_LIMIT_MAX_RETRIES=${RATE_LIMIT_MAX_RETRIES:-3}
|
||||||
|
volumes:
|
||||||
|
- ./bots/AnonBot/database:/app/database:rw
|
||||||
|
- ./bots/AnonBot/logs:/app/logs:rw
|
||||||
|
- ./bots/AnonBot/.env:/app/.env:ro
|
||||||
|
networks:
|
||||||
|
- bots_network
|
||||||
|
depends_on:
|
||||||
|
- prometheus
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8081/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
memory: 256M
|
memory: 256M
|
||||||
cpus: '0.25'
|
cpus: '0.25'
|
||||||
|
reservations:
|
||||||
|
memory: 128M
|
||||||
|
cpus: '0.1'
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
prometheus_data:
|
prometheus_data:
|
||||||
|
|||||||
@@ -0,0 +1,874 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_active_users",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Active Users",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Active Users",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 6,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_active_questions",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Active Questions",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Active Questions",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_questions_total{status=\"created\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Questions Created/min",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_questions_total{status=\"processed\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Questions Processed/min",
|
||||||
|
"refId": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_questions_total{status=\"rejected\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Questions Rejected/min",
|
||||||
|
"refId": "C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_questions_total{status=\"deleted\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Questions Deleted/min",
|
||||||
|
"refId": "D"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Questions Flow (per minute)",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_answers_total{status=\"sent\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Answers Sent/min",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_answers_total{status=\"delivered\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Answers Delivered/min",
|
||||||
|
"refId": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_answers_total{status=\"delivery_failed\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Delivery Failed/min",
|
||||||
|
"refId": "C"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Answers Flow (per minute)",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_users_total{action=\"created\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "New Users/min",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_users_total{action=\"updated\"}[5m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Updated Users/min",
|
||||||
|
"refId": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "User Activity (per minute)",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 16
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum(rate(anon_bot_messages_total[1d])) by (message_type)",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{message_type}} (daily)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Daily Trends - Messages",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 16
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum(rate(anon_bot_questions_total[1d])) by (status)",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{status}} (daily)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Daily Trends - Questions",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 0,
|
||||||
|
"y": 24
|
||||||
|
},
|
||||||
|
"id": 8,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_active_users",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Live Active Users",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Live Activity - Active Users",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 6,
|
||||||
|
"y": 24
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_messages_total[1m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Messages/min",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Messages per Minute",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 12,
|
||||||
|
"y": 24
|
||||||
|
},
|
||||||
|
"id": 10,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_questions_total[1h]) * 3600",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Questions/hour",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Questions per Hour",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 18,
|
||||||
|
"y": 24
|
||||||
|
},
|
||||||
|
"id": 11,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_answers_total[1m]) * 60",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Answers/min",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Answers per Minute",
|
||||||
|
"type": "stat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "5s",
|
||||||
|
"schemaVersion": 30,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [
|
||||||
|
"anonbot",
|
||||||
|
"overview",
|
||||||
|
"monitoring"
|
||||||
|
],
|
||||||
|
"templating": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-1h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "AnonBot Overview",
|
||||||
|
"uid": "anonbot-overview",
|
||||||
|
"version": 1,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,877 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "histogram_quantile(0.95, rate(anon_bot_message_processing_seconds_bucket[5m]))",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Message Processing 95th percentile",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "histogram_quantile(0.95, rate(anon_bot_question_processing_seconds_bucket[5m]))",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Question Processing 95th percentile",
|
||||||
|
"refId": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "histogram_quantile(0.95, rate(anon_bot_answer_processing_seconds_bucket[5m]))",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Answer Processing 95th percentile",
|
||||||
|
"refId": "C"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Response Time - 95th Percentile",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_message_processing_seconds_bucket[5m])",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{le}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Latency Heatmap - Message Processing",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "histogram_quantile(0.95, rate(anon_bot_db_query_duration_seconds_bucket[5m]))",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "DB Query 95th percentile - {{operation}}/{{table}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Database Performance - Query Duration",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 0,
|
||||||
|
"y": 16
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_db_connections_active",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Active DB Connections",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Database Connections - Active",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "percent"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 6,
|
||||||
|
"x": 6,
|
||||||
|
"y": 16
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "8.5.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_db_pool_utilization_percent",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Pool Utilization %",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "DB Pool Utilization",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "percent"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_messages_total{status=\"success\"}[5m]) / rate(anon_bot_messages_total[5m]) * 100",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Messages Success Rate",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_questions_total{status=\"processed\"}[5m]) / rate(anon_bot_questions_total[5m]) * 100",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Questions Success Rate",
|
||||||
|
"refId": "B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_answers_total{status=\"sent\"}[5m]) / rate(anon_bot_answers_total[5m]) * 100",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "Answers Success Rate",
|
||||||
|
"refId": "C"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Success/Error Rates",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 16
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_errors_total[5m])",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{component}} - {{error_type}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Error Rate by Component",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 24
|
||||||
|
},
|
||||||
|
"id": 8,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum(rate(anon_bot_errors_total[5m])) by (error_type)",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{error_type}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Error Types Distribution",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 24
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_db_queries_total{status=\"error\"}[5m])",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{operation}}/{{table}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Database Errors",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"id": 10,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_pagination_errors_total[5m])",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{entity_type}} - {{error_type}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Pagination Errors",
|
||||||
|
"type": "timeseries"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "5s",
|
||||||
|
"schemaVersion": 30,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [
|
||||||
|
"anonbot",
|
||||||
|
"performance",
|
||||||
|
"monitoring"
|
||||||
|
],
|
||||||
|
"templating": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-1h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "Performance AnonBot",
|
||||||
|
"uid": "anonbot-performance",
|
||||||
|
"version": 1,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -84,7 +84,7 @@
|
|||||||
"unit": "percent"
|
"unit": "percent"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gridPos": {"h": 8, "w": 6, "x": 12, "y": 0}
|
"gridPos": {"h": 8, "w": 6, "x": 18, "y": 16}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 4,
|
"id": 4,
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 8}
|
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 16}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 5,
|
"id": 5,
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
"unit": "s"
|
"unit": "s"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gridPos": {"h": 8, "w": 6, "x": 12, "y": 8}
|
"gridPos": {"h": 8, "w": 6, "x": 12, "y": 16}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 6,
|
"id": 6,
|
||||||
@@ -186,7 +186,7 @@
|
|||||||
"unit": "percent"
|
"unit": "percent"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gridPos": {"h": 8, "w": 6, "x": 0, "y": 16}
|
"gridPos": {"h": 8, "w": 6, "x": 12, "y": 16}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 7,
|
"id": 7,
|
||||||
@@ -213,7 +213,432 @@
|
|||||||
"unit": "percent"
|
"unit": "percent"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gridPos": {"h": 8, "w": 6, "x": 6, "y": 16}
|
"gridPos": {"h": 8, "w": 6, "x": 18, "y": 16}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"title": "CPU Usage Gauge",
|
||||||
|
"type": "gauge",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "cpu_usage_percent",
|
||||||
|
"legendFormat": "CPU %"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"thresholds": {
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "yellow", "value": 70},
|
||||||
|
{"color": "red", "value": 90}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "percent",
|
||||||
|
"min": 0,
|
||||||
|
"max": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"values": false,
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": ""
|
||||||
|
},
|
||||||
|
"showThresholdLabels": false,
|
||||||
|
"showThresholdMarkers": true
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 6, "x": 12, "y": 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"title": "RAM Usage Gauge",
|
||||||
|
"type": "gauge",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "ram_usage_percent",
|
||||||
|
"legendFormat": "RAM %"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"thresholds": {
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "yellow", "value": 70},
|
||||||
|
{"color": "red", "value": 90}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "percent",
|
||||||
|
"min": 0,
|
||||||
|
"max": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"values": false,
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": ""
|
||||||
|
},
|
||||||
|
"showThresholdLabels": false,
|
||||||
|
"showThresholdMarkers": true
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 6, "x": 18, "y": 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"title": "System Resources Overview",
|
||||||
|
"type": "timeseries",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "cpu_usage_percent",
|
||||||
|
"legendFormat": "CPU %"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "ram_usage_percent",
|
||||||
|
"legendFormat": "RAM %"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "disk_usage_percent",
|
||||||
|
"legendFormat": "Disk %"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "Usage %",
|
||||||
|
"axisPlacement": "left",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 20,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 2,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unit": "percent",
|
||||||
|
"min": 0,
|
||||||
|
"max": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 8}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"title": "AnonBot Health Status",
|
||||||
|
"type": "timeseries",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_errors_total[5m])",
|
||||||
|
"legendFormat": "{{component}} - {{error_type}}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 24}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"title": "AnonBot Database Connections",
|
||||||
|
"type": "timeseries",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_db_connections_active",
|
||||||
|
"legendFormat": "Active Connections"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_db_connections_total[5m])",
|
||||||
|
"legendFormat": "Total Connections/min - {{status}}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 24}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"title": "AnonBot System Health",
|
||||||
|
"type": "stat",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_active_users",
|
||||||
|
"legendFormat": "Active Users"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"thresholds": {
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "yellow", "value": 10},
|
||||||
|
{"color": "red", "value": 50}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 6, "x": 0, "y": 32}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"title": "AnonBot Active Questions",
|
||||||
|
"type": "stat",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "anon_bot_active_questions",
|
||||||
|
"legendFormat": "Active Questions"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"thresholds": {
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "yellow", "value": 20},
|
||||||
|
{"color": "red", "value": 100}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 6, "x": 6, "y": 32}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"title": "AnonBot Message Rate",
|
||||||
|
"type": "stat",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_messages_total[1m]) * 60",
|
||||||
|
"legendFormat": "Messages/min"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"thresholds": {
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "yellow", "value": 10},
|
||||||
|
{"color": "red", "value": 50}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 6, "x": 12, "y": 32}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"title": "AnonBot Error Rate",
|
||||||
|
"type": "stat",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(anon_bot_errors_total[5m])",
|
||||||
|
"legendFormat": "Errors/min"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"thresholds": {
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "yellow", "value": 1},
|
||||||
|
{"color": "red", "value": 5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 8, "w": 6, "x": 18, "y": 32}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": {
|
"time": {
|
||||||
|
|||||||
@@ -899,6 +899,190 @@
|
|||||||
],
|
],
|
||||||
"title": "Database Query Time (P95)",
|
"title": "Database Query Time (P95)",
|
||||||
"type": "timeseries"
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 40
|
||||||
|
},
|
||||||
|
"id": 11,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"expr": "topk(5, sum by(content_type) (rate(media_processing_total[5m])))",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Top Media Types",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"vis": false
|
||||||
|
},
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "bytes"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 40
|
||||||
|
},
|
||||||
|
"id": 12,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"expr": "histogram_quantile(0.5, rate(file_download_size_bytes_bucket[5m])) by (content_type)",
|
||||||
|
"refId": "A",
|
||||||
|
"legendFormat": "{{content_type}} P50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "PBFA97CFB590B2093"
|
||||||
|
},
|
||||||
|
"expr": "histogram_quantile(0.95, rate(file_download_size_bytes_bucket[5m])) by (content_type)",
|
||||||
|
"refId": "B",
|
||||||
|
"legendFormat": "{{content_type}} P95"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "File Download Size Distribution",
|
||||||
|
"type": "timeseries"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"refresh": "5s",
|
"refresh": "5s",
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
# PID Manager - Управление процессами ботов
|
|
||||||
|
|
||||||
## Описание
|
|
||||||
|
|
||||||
`pid_manager.py` - это общий модуль для управления PID файлами всех ботов в проекте. Он обеспечивает создание, отслеживание и очистку PID файлов для мониторинга состояния процессов.
|
|
||||||
|
|
||||||
## Использование
|
|
||||||
|
|
||||||
### Для новых ботов
|
|
||||||
|
|
||||||
Чтобы добавить PID мониторинг в новый бот, выполните следующие шаги:
|
|
||||||
|
|
||||||
1. **Импортируйте PID менеджер в ваш скрипт запуска:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
# Добавляем путь к инфраструктуре в sys.path
|
|
||||||
infra_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'infra', 'monitoring')
|
|
||||||
if infra_path not in sys.path:
|
|
||||||
sys.path.insert(0, infra_path)
|
|
||||||
|
|
||||||
from pid_manager import get_bot_pid_manager
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Создайте PID менеджер в начале main функции:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
async def main():
|
|
||||||
# Создаем PID менеджер для отслеживания процесса (если доступен)
|
|
||||||
pid_manager = None
|
|
||||||
if get_bot_pid_manager:
|
|
||||||
pid_manager = get_bot_pid_manager("your_bot_name") # Замените на имя вашего бота
|
|
||||||
if not pid_manager.create_pid_file():
|
|
||||||
logger.error("Не удалось создать PID файл, завершаем работу")
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
logger.info("PID менеджер недоступен, запуск без PID файла")
|
|
||||||
|
|
||||||
# Ваш код запуска бота...
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Очистите PID файл при завершении:**
|
|
||||||
|
|
||||||
```python
|
|
||||||
try:
|
|
||||||
# Ваш код работы бота...
|
|
||||||
finally:
|
|
||||||
# Очищаем PID файл (если PID менеджер доступен)
|
|
||||||
if pid_manager:
|
|
||||||
pid_manager.cleanup_pid_file()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Для мониторинга
|
|
||||||
|
|
||||||
Чтобы добавить новый бот в систему мониторинга:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from infra.monitoring.metrics_collector import MetricsCollector
|
|
||||||
|
|
||||||
# Создаем экземпляр коллектора метрик
|
|
||||||
collector = MetricsCollector()
|
|
||||||
|
|
||||||
# Добавляем новый бот в мониторинг
|
|
||||||
collector.add_bot_to_monitoring("your_bot_name")
|
|
||||||
|
|
||||||
# Теперь можно проверять статус
|
|
||||||
status, uptime = collector.check_process_status("your_bot_name")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Структура файлов
|
|
||||||
|
|
||||||
```
|
|
||||||
prod/
|
|
||||||
├── infra/
|
|
||||||
│ └── monitoring/
|
|
||||||
│ ├── pid_manager.py # Основной модуль
|
|
||||||
│ ├── metrics_collector.py # Мониторинг процессов
|
|
||||||
│ └── README_PID_MANAGER.md # Эта документация
|
|
||||||
├── bots/
|
|
||||||
│ ├── telegram-helper-bot/
|
|
||||||
│ │ └── run_helper.py # Использует PID менеджер
|
|
||||||
│ └── your-new-bot/
|
|
||||||
│ └── run_your_bot.py # Будет использовать PID менеджер
|
|
||||||
├── helper_bot.pid # PID файл helper_bot
|
|
||||||
├── your_bot.pid # PID файл вашего бота
|
|
||||||
└── .gitignore # Содержит *.pid
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### PIDManager
|
|
||||||
|
|
||||||
- `create_pid_file()` - Создает PID файл
|
|
||||||
- `cleanup_pid_file()` - Удаляет PID файл
|
|
||||||
- `is_running()` - Проверяет, запущен ли процесс
|
|
||||||
- `get_pid()` - Получает PID из файла
|
|
||||||
|
|
||||||
### Функции
|
|
||||||
|
|
||||||
- `get_bot_pid_manager(bot_name)` - Создает PID менеджер для бота
|
|
||||||
- `create_pid_manager(process_name, project_root)` - Создает PID менеджер с настройками
|
|
||||||
|
|
||||||
## Примеры
|
|
||||||
|
|
||||||
### Простой бот
|
|
||||||
|
|
||||||
```python
|
|
||||||
import asyncio
|
|
||||||
from pid_manager import get_bot_pid_manager
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
# Создаем PID менеджер
|
|
||||||
pid_manager = get_bot_pid_manager("simple_bot")
|
|
||||||
if not pid_manager.create_pid_file():
|
|
||||||
print("Не удалось создать PID файл")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Ваш код бота
|
|
||||||
print("Бот запущен...")
|
|
||||||
await asyncio.sleep(3600) # Работаем час
|
|
||||||
finally:
|
|
||||||
# Очищаем PID файл
|
|
||||||
pid_manager.cleanup_pid_file()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
asyncio.run(main())
|
|
||||||
```
|
|
||||||
|
|
||||||
### Бот с обработкой сигналов
|
|
||||||
|
|
||||||
```python
|
|
||||||
import asyncio
|
|
||||||
import signal
|
|
||||||
from pid_manager import get_bot_pid_manager
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
pid_manager = get_bot_pid_manager("advanced_bot")
|
|
||||||
if not pid_manager.create_pid_file():
|
|
||||||
return
|
|
||||||
|
|
||||||
# Флаг для корректного завершения
|
|
||||||
shutdown_event = asyncio.Event()
|
|
||||||
|
|
||||||
def signal_handler(signum, frame):
|
|
||||||
print(f"Получен сигнал {signum}, завершаем работу...")
|
|
||||||
shutdown_event.set()
|
|
||||||
|
|
||||||
# Регистрируем обработчики сигналов
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Ваш код бота
|
|
||||||
await shutdown_event.wait()
|
|
||||||
finally:
|
|
||||||
pid_manager.cleanup_pid_file()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
asyncio.run(main())
|
|
||||||
```
|
|
||||||
|
|
||||||
## Примечания
|
|
||||||
|
|
||||||
- PID файлы создаются в корне проекта
|
|
||||||
- Все PID файлы автоматически игнорируются Git (см. `.gitignore`)
|
|
||||||
- PID менеджер автоматически обрабатывает сигналы SIGTERM и SIGINT
|
|
||||||
- При завершении процесса PID файл автоматически удаляется
|
|
||||||
- Система мониторинга автоматически находит PID файлы в корне проекта
|
|
||||||
|
|
||||||
## Изолированный запуск
|
|
||||||
|
|
||||||
При запуске бота изолированно (без доступа к основному проекту):
|
|
||||||
|
|
||||||
- PID менеджер автоматически не создается
|
|
||||||
- Бот запускается без PID файла
|
|
||||||
- В логах появляется сообщение "PID менеджер недоступен (изолированный запуск), PID файл не создается"
|
|
||||||
- Это позволяет запускать бота в любой среде без ошибок
|
|
||||||
|
|
||||||
## Автоматическое определение
|
|
||||||
|
|
||||||
Система автоматически определяет доступность PID менеджера:
|
|
||||||
|
|
||||||
1. **В основном проекте**: PID менеджер доступен, создается PID файл для мониторинга
|
|
||||||
2. **Изолированно**: PID менеджер недоступен, бот работает без PID файла
|
|
||||||
3. **Fallback**: Если PID менеджер недоступен, бот продолжает работать нормально
|
|
||||||
@@ -64,6 +64,39 @@ class MessageSender:
|
|||||||
logger.error(f"Ошибка при отправке сообщения в Telegram: {e}")
|
logger.error(f"Ошибка при отправке сообщения в Telegram: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def get_anonbot_status(self) -> Tuple[str, str]:
|
||||||
|
"""Получение статуса AnonBot через HTTP API"""
|
||||||
|
try:
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
# AnonBot доступен через Docker network
|
||||||
|
url = "http://bots_anon_bot:8081/status"
|
||||||
|
|
||||||
|
async with session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
data = await response.json()
|
||||||
|
status = data.get('status', 'unknown')
|
||||||
|
uptime = data.get('uptime', 'unknown')
|
||||||
|
|
||||||
|
# Форматируем статус с эмодзи
|
||||||
|
if status == 'running':
|
||||||
|
status_emoji = "✅"
|
||||||
|
elif status == 'stopped':
|
||||||
|
status_emoji = "❌"
|
||||||
|
else:
|
||||||
|
status_emoji = "⚠️"
|
||||||
|
|
||||||
|
return f"{status_emoji}", uptime
|
||||||
|
else:
|
||||||
|
logger.warning(f"AnonBot API вернул статус {response.status}")
|
||||||
|
return "⚠️ AnonBot", "API недоступен"
|
||||||
|
|
||||||
|
except aiohttp.ClientError as e:
|
||||||
|
logger.warning(f"Ошибка подключения к AnonBot API: {e}")
|
||||||
|
return "❌", "Недоступен"
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Неожиданная ошибка при получении статуса AnonBot: {e}")
|
||||||
|
return "⚠️", "Ошибка"
|
||||||
|
|
||||||
def should_send_status(self) -> bool:
|
def should_send_status(self) -> bool:
|
||||||
"""Проверка, нужно ли отправить статус (каждые N минут)"""
|
"""Проверка, нужно ли отправить статус (каждые N минут)"""
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
@@ -74,7 +107,6 @@ class MessageSender:
|
|||||||
|
|
||||||
if self.last_status_time is None:
|
if self.last_status_time is None:
|
||||||
logger.info(f"should_send_status: last_status_time is None, отправляем статус")
|
logger.info(f"should_send_status: last_status_time is None, отправляем статус")
|
||||||
self.last_status_time = now
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Вычисляем разницу в минутах
|
# Вычисляем разницу в минутах
|
||||||
@@ -84,7 +116,6 @@ class MessageSender:
|
|||||||
# Проверяем, что прошло N минут с последней отправки
|
# Проверяем, что прошло N минут с последней отправки
|
||||||
if time_diff_minutes >= self.status_update_interval_minutes:
|
if time_diff_minutes >= self.status_update_interval_minutes:
|
||||||
logger.info(f"should_send_status: отправляем статус (прошло {time_diff_minutes:.1f} минут)")
|
logger.info(f"should_send_status: отправляем статус (прошло {time_diff_minutes:.1f} минут)")
|
||||||
self.last_status_time = now
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logger.info(f"should_send_status: статус не отправляем (прошло {time_diff_minutes:.1f} минут)")
|
logger.info(f"should_send_status: статус не отправляем (прошло {time_diff_minutes:.1f} минут)")
|
||||||
@@ -92,7 +123,12 @@ class MessageSender:
|
|||||||
|
|
||||||
def should_send_startup_status(self) -> bool:
|
def should_send_startup_status(self) -> bool:
|
||||||
"""Проверка, нужно ли отправить статус при запуске"""
|
"""Проверка, нужно ли отправить статус при запуске"""
|
||||||
return self.last_status_time is None
|
# Отправляем статус при запуске только если он еще не был отправлен
|
||||||
|
if self.last_status_time is None:
|
||||||
|
logger.info("should_send_startup_status: отправляем статус при запуске")
|
||||||
|
return True
|
||||||
|
logger.info("should_send_startup_status: статус уже был отправлен, пропускаем")
|
||||||
|
return False
|
||||||
|
|
||||||
def _get_disk_space_emoji(self, disk_percent: float) -> str:
|
def _get_disk_space_emoji(self, disk_percent: float) -> str:
|
||||||
"""Получение эмодзи для дискового пространства"""
|
"""Получение эмодзи для дискового пространства"""
|
||||||
@@ -144,11 +180,14 @@ class MessageSender:
|
|||||||
else:
|
else:
|
||||||
return "🚨"
|
return "🚨"
|
||||||
|
|
||||||
def get_status_message(self, system_info: Dict) -> str:
|
async def get_status_message(self, system_info: Dict) -> str:
|
||||||
"""Формирование сообщения со статусом сервера"""
|
"""Формирование сообщения со статусом сервера"""
|
||||||
try:
|
try:
|
||||||
helper_bot_status, helper_bot_uptime = self.metrics_collector.check_process_status('helper_bot')
|
helper_bot_status, helper_bot_uptime = self.metrics_collector.check_process_status('helper_bot')
|
||||||
|
|
||||||
|
# Получаем статус AnonBot
|
||||||
|
anonbot_status, anonbot_uptime = await self.get_anonbot_status()
|
||||||
|
|
||||||
# Получаем эмодзи для всех метрик
|
# Получаем эмодзи для всех метрик
|
||||||
cpu_emoji = self._get_cpu_emoji(system_info['cpu_percent'])
|
cpu_emoji = self._get_cpu_emoji(system_info['cpu_percent'])
|
||||||
ram_emoji = self._get_memory_emoji(system_info['ram_percent'])
|
ram_emoji = self._get_memory_emoji(system_info['ram_percent'])
|
||||||
@@ -180,6 +219,7 @@ Read: <b>{system_info['disk_read_speed']}</b> | Write: <b>{system_info['disk_wri
|
|||||||
|
|
||||||
**🤖 Процессы:**
|
**🤖 Процессы:**
|
||||||
{helper_bot_status} helper-bot - {helper_bot_uptime}
|
{helper_bot_status} helper-bot - {helper_bot_uptime}
|
||||||
|
{anonbot_status} AnonBot - {anonbot_uptime}
|
||||||
---------------------------------
|
---------------------------------
|
||||||
⏰ Uptime сервера: {system_info['system_uptime']}
|
⏰ Uptime сервера: {system_info['system_uptime']}
|
||||||
🔍 Уровень мониторинга: {level_text} ({monitoring_level})"""
|
🔍 Уровень мониторинга: {level_text} ({monitoring_level})"""
|
||||||
@@ -256,8 +296,15 @@ Read: <b>{system_info['disk_read_speed']}</b> | Write: <b>{system_info['disk_wri
|
|||||||
logger.error("Не удалось получить информацию о системе")
|
logger.error("Не удалось получить информацию о системе")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
status_message = self.get_status_message(system_info)
|
status_message = await self.get_status_message(system_info)
|
||||||
return await self.send_telegram_message(self.group_for_logs, status_message)
|
success = await self.send_telegram_message(self.group_for_logs, status_message)
|
||||||
|
|
||||||
|
# Обновляем время последней отправки только при успешной отправке
|
||||||
|
if success:
|
||||||
|
self.last_status_time = datetime.now()
|
||||||
|
logger.info("send_status_message: время последней отправки обновлено")
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка при отправке статуса: {e}")
|
logger.error(f"Ошибка при отправке статуса: {e}")
|
||||||
|
|||||||
@@ -590,13 +590,16 @@ class MetricsCollector:
|
|||||||
alerts.append(('cpu', system_info['cpu_percent'], f"Нагрузка за 1 мин: {system_info['load_avg_1m']}"))
|
alerts.append(('cpu', system_info['cpu_percent'], f"Нагрузка за 1 мин: {system_info['load_avg_1m']}"))
|
||||||
logger.warning(f"CPU ALERT: {system_info['cpu_percent']:.1f}% > {self.threshold}% (задержка {self.alert_delays['cpu']}s)")
|
logger.warning(f"CPU ALERT: {system_info['cpu_percent']:.1f}% > {self.threshold}% (задержка {self.alert_delays['cpu']}s)")
|
||||||
else:
|
else:
|
||||||
# CPU ниже порога - сбрасываем состояние
|
# CPU ниже порога - сбрасываем состояние только если был активный алерт
|
||||||
if self.alert_states['cpu']:
|
if self.alert_states['cpu']:
|
||||||
self.alert_states['cpu'] = False
|
self.alert_states['cpu'] = False
|
||||||
recoveries.append(('cpu', system_info['cpu_percent']))
|
recoveries.append(('cpu', system_info['cpu_percent']))
|
||||||
logger.info(f"CPU RECOVERY: {system_info['cpu_percent']:.1f}% < {self.recovery_threshold}%")
|
logger.info(f"CPU RECOVERY: {system_info['cpu_percent']:.1f}% < {self.recovery_threshold}%")
|
||||||
|
# Сбрасываем время начала превышения только после отправки алерта
|
||||||
# Сбрасываем время начала превышения
|
self.alert_start_times['cpu'] = None
|
||||||
|
elif system_info['cpu_percent'] < self.recovery_threshold and self.alert_start_times['cpu'] is not None:
|
||||||
|
# Если CPU опустился значительно ниже порога, сбрасываем время начала превышения
|
||||||
|
logger.debug(f"CPU значительно ниже порога {self.recovery_threshold}%: {system_info['cpu_percent']:.1f}% - сбрасываем время начала превышения")
|
||||||
self.alert_start_times['cpu'] = None
|
self.alert_start_times['cpu'] = None
|
||||||
|
|
||||||
# Проверка RAM с задержкой
|
# Проверка RAM с задержкой
|
||||||
@@ -613,13 +616,16 @@ class MetricsCollector:
|
|||||||
alerts.append(('ram', system_info['ram_percent'], f"Используется: {system_info['ram_used']} GB из {system_info['ram_total']} GB"))
|
alerts.append(('ram', system_info['ram_percent'], f"Используется: {system_info['ram_used']} GB из {system_info['ram_total']} GB"))
|
||||||
logger.warning(f"RAM ALERT: {system_info['ram_percent']:.1f}% > {self.threshold}% (задержка {self.alert_delays['ram']}s)")
|
logger.warning(f"RAM ALERT: {system_info['ram_percent']:.1f}% > {self.threshold}% (задержка {self.alert_delays['ram']}s)")
|
||||||
else:
|
else:
|
||||||
# RAM ниже порога - сбрасываем состояние
|
# RAM ниже порога - сбрасываем состояние только если был активный алерт
|
||||||
if self.alert_states['ram']:
|
if self.alert_states['ram']:
|
||||||
self.alert_states['ram'] = False
|
self.alert_states['ram'] = False
|
||||||
recoveries.append(('ram', system_info['ram_percent']))
|
recoveries.append(('ram', system_info['ram_percent']))
|
||||||
logger.info(f"RAM RECOVERY: {system_info['ram_percent']:.1f}% < {self.recovery_threshold}%")
|
logger.info(f"RAM RECOVERY: {system_info['ram_percent']:.1f}% < {self.recovery_threshold}%")
|
||||||
|
# Сбрасываем время начала превышения только после отправки алерта
|
||||||
# Сбрасываем время начала превышения
|
self.alert_start_times['ram'] = None
|
||||||
|
elif system_info['ram_percent'] < self.recovery_threshold and self.alert_start_times['ram'] is not None:
|
||||||
|
# Если RAM опустился значительно ниже порога, сбрасываем время начала превышения
|
||||||
|
logger.debug(f"RAM значительно ниже порога {self.recovery_threshold}%: {system_info['ram_percent']:.1f}% - сбрасываем время начала превышения")
|
||||||
self.alert_start_times['ram'] = None
|
self.alert_start_times['ram'] = None
|
||||||
|
|
||||||
# Проверка диска с задержкой
|
# Проверка диска с задержкой
|
||||||
@@ -636,13 +642,16 @@ class MetricsCollector:
|
|||||||
alerts.append(('disk', system_info['disk_percent'], f"Свободно: {system_info['disk_free']} GB на /"))
|
alerts.append(('disk', system_info['disk_percent'], f"Свободно: {system_info['disk_free']} GB на /"))
|
||||||
logger.warning(f"DISK ALERT: {system_info['disk_percent']:.1f}% > {self.threshold}% (задержка {self.alert_delays['disk']}s)")
|
logger.warning(f"DISK ALERT: {system_info['disk_percent']:.1f}% > {self.threshold}% (задержка {self.alert_delays['disk']}s)")
|
||||||
else:
|
else:
|
||||||
# Диск ниже порога - сбрасываем состояние
|
# Диск ниже порога - сбрасываем состояние только если был активный алерт
|
||||||
if self.alert_states['disk']:
|
if self.alert_states['disk']:
|
||||||
self.alert_states['disk'] = False
|
self.alert_states['disk'] = False
|
||||||
recoveries.append(('disk', system_info['disk_percent']))
|
recoveries.append(('disk', system_info['disk_percent']))
|
||||||
logger.info(f"DISK RECOVERY: {system_info['disk_percent']:.1f}% < {self.recovery_threshold}%")
|
logger.info(f"DISK RECOVERY: {system_info['disk_percent']:.1f}% < {self.recovery_threshold}%")
|
||||||
|
# Сбрасываем время начала превышения только после отправки алерта
|
||||||
# Сбрасываем время начала превышения
|
self.alert_start_times['disk'] = None
|
||||||
|
elif system_info['disk_percent'] < self.recovery_threshold and self.alert_start_times['disk'] is not None:
|
||||||
|
# Если диск опустился значительно ниже порога, сбрасываем время начала превышения
|
||||||
|
logger.debug(f"Disk значительно ниже порога {self.recovery_threshold}%: {system_info['disk_percent']:.1f}% - сбрасываем время начала превышения")
|
||||||
self.alert_start_times['disk'] = None
|
self.alert_start_times['disk'] = None
|
||||||
|
|
||||||
return alerts, recoveries
|
return alerts, recoveries
|
||||||
|
|||||||
@@ -32,6 +32,18 @@ scrape_configs:
|
|||||||
scrape_timeout: 10s
|
scrape_timeout: 10s
|
||||||
honor_labels: true
|
honor_labels: true
|
||||||
|
|
||||||
|
- job_name: 'anon-bot'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['bots_anon_bot:8081'] # AnonBot на порту 8081
|
||||||
|
labels:
|
||||||
|
bot_name: 'anon-bot'
|
||||||
|
environment: 'production'
|
||||||
|
service: 'anon-bot'
|
||||||
|
metrics_path: '/metrics'
|
||||||
|
scrape_interval: 15s
|
||||||
|
scrape_timeout: 10s
|
||||||
|
honor_labels: true
|
||||||
|
|
||||||
alerting:
|
alerting:
|
||||||
alertmanagers:
|
alertmanagers:
|
||||||
- static_configs:
|
- static_configs:
|
||||||
|
|||||||
@@ -252,21 +252,21 @@ class TestMetricsCollector:
|
|||||||
def test_check_process_status_pid_file(self, metrics_collector, tmp_path):
|
def test_check_process_status_pid_file(self, metrics_collector, tmp_path):
|
||||||
"""Тест проверки статуса процесса по PID файлу"""
|
"""Тест проверки статуса процесса по PID файлу"""
|
||||||
# Создаем временный PID файл
|
# Создаем временный PID файл
|
||||||
pid_file = tmp_path / "helper_bot.pid"
|
pid_file = tmp_path / "test_bot.pid"
|
||||||
pid_file.write_text("12345")
|
pid_file.write_text("12345")
|
||||||
|
|
||||||
# Временно заменяем путь к PID файлу
|
# Временно заменяем путь к PID файлу
|
||||||
original_pid_files = metrics_collector.pid_files.copy()
|
original_pid_files = metrics_collector.pid_files.copy()
|
||||||
metrics_collector.pid_files['helper_bot'] = str(pid_file)
|
metrics_collector.pid_files['test_bot'] = str(pid_file)
|
||||||
|
|
||||||
with patch('metrics_collector.psutil.pid_exists', return_value=True), \
|
with patch('infra.monitoring.metrics_collector.psutil.pid_exists', return_value=True), \
|
||||||
patch('metrics_collector.psutil.Process') as mock_process:
|
patch('infra.monitoring.metrics_collector.psutil.Process') as mock_process:
|
||||||
|
|
||||||
mock_proc = Mock()
|
mock_proc = Mock()
|
||||||
mock_proc.create_time.return_value = time.time() - 3600
|
mock_proc.create_time.return_value = time.time() - 3600
|
||||||
mock_process.return_value = mock_proc
|
mock_process.return_value = mock_proc
|
||||||
|
|
||||||
status, uptime = metrics_collector.check_process_status('helper_bot')
|
status, uptime = metrics_collector.check_process_status('test_bot')
|
||||||
|
|
||||||
assert status == "✅"
|
assert status == "✅"
|
||||||
assert "Uptime" in uptime
|
assert "Uptime" in uptime
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class TestPrometheusConfig:
|
|||||||
assert len(static_configs) > 0, "Should have at least one static config"
|
assert len(static_configs) > 0, "Should have at least one static config"
|
||||||
|
|
||||||
targets = static_configs[0].get('targets', [])
|
targets = static_configs[0].get('targets', [])
|
||||||
assert 'host.docker.internal:9091' in targets, "Should scrape host.docker.internal:9091"
|
assert 'bots_server_monitor:9091' in targets, "Should scrape bots_server_monitor:9091"
|
||||||
|
|
||||||
def test_telegram_bot_job(self, prometheus_config):
|
def test_telegram_bot_job(self, prometheus_config):
|
||||||
"""Тест job для telegram-helper-bot"""
|
"""Тест job для telegram-helper-bot"""
|
||||||
@@ -145,7 +145,7 @@ class TestPrometheusConfig:
|
|||||||
|
|
||||||
# Проверяем targets
|
# Проверяем targets
|
||||||
targets = static_configs[0].get('targets', [])
|
targets = static_configs[0].get('targets', [])
|
||||||
assert 'host.docker.internal:8080' in targets, "Should scrape host.docker.internal:8080"
|
assert 'bots_telegram_bot:8080' in targets, "Should scrape bots_telegram_bot:8080"
|
||||||
|
|
||||||
# Проверяем labels
|
# Проверяем labels
|
||||||
labels = static_configs[0].get('labels', {})
|
labels = static_configs[0].get('labels', {})
|
||||||
|
|||||||
Reference in New Issue
Block a user