Spaces:
Running
# HTS Investigation Suite - Système Monitoring Complet
Browse files# HIGH TECH SECURITY - Surveillance et alertes automatisées
import asyncio
import json
import logging
import smtplib
import time
from datetime import datetime, timedelta
from email.mime.text import MimeText
from email.mime.multipart import MimeMultipart
from typing import Dict, List, Optional
import psutil
import redis
import requests
from sqlalchemy import create_engine, text
from prometheus_client import start_http_server, Gauge, Counter, Histogram, Info
import structlog
# Configuration
class MonitoringConfig:
# Métriques Prometheus
PROMETHEUS_PORT = 8001
# Seuils d'alerte
THRESHOLDS = {
'cpu_usage': 80.0,
'memory_usage': 85.0,
'disk_usage': 90.0,
'response_time': 5.0, # secondes
'error_rate': 10.0, # pourcentage
'failed_analyses': 5 # nombre
}
# Configuration email
SMTP_CONFIG = {
'server': 'smtp.gmail.com',
'port': 587,
'username': 'hts-monitoring@gmail.com',
'password': 'HTS_Monitor_2025!',
'from_email': 'hts-monitoring@hts-investigation.com'
}
# Destinataires alertes
ALERT_RECIPIENTS = [
'admin@hts-investigation.com',
'contact@hts-investigation.com'
]
# URLs à surveiller
ENDPOINTS_TO_MONITOR = [
'http://localhost:8000/health',
'http://localhost:8000/',
'http://localhost:8000/api/stats/global'
]
# Configuration logging
logger = structlog.get_logger()
# Métriques Prometheus
system_cpu_usage = Gauge('hts_system_cpu_usage_percent', 'CPU usage percentage')
system_memory_usage = Gauge('hts_system_memory_usage_percent', 'Memory usage percentage')
system_disk_usage = Gauge('hts_system_disk_usage_percent', 'Disk usage percentage')
api_response_time = Histogram('hts_api_response_time_seconds', 'API response time')
api_requests_total = Counter('hts_api_requests_total', 'Total API requests', ['method', 'endpoint', 'status'])
active_investigations = Gauge('hts_active_investigations_total', 'Number of active investigations')
failed_analyses = Counter('hts_failed_analyses_total', 'Number of failed analyses')
threat_alerts = Counter('hts_threat_alerts_total', 'Number of threat alerts', ['severity'])
system_info = Info('hts_system_info', 'System information')
class HTSMonitoringSystem:
def __init__(self):
self.redis_client = redis.Redis(host='localhost', port=6379, password='HTS_Redis_2025!', db=0)
self.db_engine = create_engine('postgresql://hts_user:HTS_Investigation_2025!@localhost/hts_investigation')
self.alerts_sent = {}
self.last_health_check = {}
# Initialisation métriques système
system_info.info({
'version': '2.1.0',
'company': 'HIGH TECH SECURITY',
'address': '203-205 The Vale, London W3 7QS, United Kingdom',
'company_number': '7849187',
'policy_number': '550.232.804'
})
async def start_monitoring(self):
"""Démarrage du système de monitoring"""
logger.info("🛡️ HIGH TECH SECURITY - Démarrage monitoring")
# Démarrage serveur Prometheus
start_http_server(MonitoringConfig.PROMETHEUS_PORT)
logger.info(f"Prometheus metrics server démarré sur le port {MonitoringConfig.PROMETHEUS_PORT}")
# Boucle principale de monitoring
while True:
try:
await self.run_monitoring_cycle()
await asyncio.sleep(30) # Cycle toutes les 30 secondes
except Exception as e:
logger.error(f"Erreur dans le cycle de monitoring: {e}")
await asyncio.sleep(60)
async def run_monitoring_cycle(self):
"""Cycle complet de monitoring"""
tasks = [
self.monitor_system_resources(),
self.monitor_api_health(),
self.monitor_database_health(),
self.monitor_business_metrics(),
self.check_security_alerts(),
self.cleanup_old_data()
]
await asyncio.gather(*tasks, return_exceptions=True)
async def monitor_system_resources(self):
"""Surveillance des ressources système"""
try:
# CPU
cpu_percent = psutil.cpu_percent(interval=1)
system_cpu_usage.set(cpu_percent)
# Mémoire
memory = psutil.virtual_memory()
memory_percent = memory.percent
system_memory_usage.set(memory_percent)
# Disque
disk = psutil.disk_usage('/')
disk_percent = (disk.used / disk.total) * 100
system_disk_usage.set(disk_percent)
# Vérification seuils
if cpu_percent > MonitoringConfig.THRESHOLDS['cpu_usage']:
await self.send_alert('system', f'CPU usage élevé: {cpu_percent:.1f}%', 'high')
if memory_percent > MonitoringConfig.THRESHOLDS['memory_usage']:
await self.send_alert('system', f'Mémoire usage élevé: {memory_percent:.1f}%', 'high')
if disk_percent > MonitoringConfig.THRESHOLDS['disk_usage']:
await self.send_alert('system', f'Disque usage élevé: {disk_percent:.1f}%', 'critical')
logger.debug(f"Ressources: CPU {cpu_percent:.1f}%, Mémoire {memory_percent:.1f}%, Disque {disk_percent:.1f}%")
except Exception as e:
logger.error(f"Erreur monitoring ressources système: {e}")
async def monitor_api_health(self):
"""Surveillance santé API"""
for endpoint in MonitoringConfig.ENDPOINTS_TO_MONITOR:
try:
start_time = time.time()
response = requests.get(endpoint, timeout=10)
response_time = time.time() - start_time
# Métriques Prometheus
api_response_time.observe(response_time)
api_requests_total.labels(
method='GET',
endpoint=endpoint,
status=response.status_code
).inc()
# Vérification santé
if response.status_code != 200:
await self.send_alert('api', f'Endpoint {endpoint} retourne {response.status_code}', 'critical')
if response_time > MonitoringConfig.THRESHOLDS['response_time']:
await self.send_alert('api', f'Temps de réponse élevé pour {endpoint}: {response_time:.2f}s', 'warning')
self.last_health_check[endpoint] = {
'status': response.status_code,
'response_time': response_time,
'timestamp': datetime.now()
}
except requests.exceptions.RequestException as e:
await self.send_alert('api', f'Endpoint {endpoint} inaccessible: {str(e)}', 'critical')
api_requests_total.labels(method='GET', endpoint=endpoint, status='timeout').inc()
async def monitor_database_health(self):
"""Surveillance santé base de données"""
try:
with self.db_engine.connect() as conn:
# Test connexion
start_time = time.time()
result = conn.execute(text("SELECT 1"))
db_response_time = time.time() - start_time
if db_response_time > 2.0:
await self.send_alert('database', f'Base de données lente: {db_response_time:.2f}s', 'warning')
# Vérification taille base
size_result = conn.execute(text("""
SELECT pg_size_pretty(pg_database_size('hts_investigation')) as size,
pg_database_size('hts_investigation') as size_bytes
"""))
size_info = size_result.fetchone()
# Vérification connexions actives
conn_result = conn.execute(text("""
SELECT count(*) as active_connections
FROM pg_stat_activity
WHERE state = 'active'
"""))
active_connections = conn_result.fetchone()[0]
if active_connections > 50:
await self.send_alert('database', f'Trop de connexions actives: {active_connections}', 'warning')
logger.debug(f"DB: {size_info[0]}, {active_connections} connexions actives")
except Exception as e:
await self.send_alert('database', f'Erreur base de données: {str(e)}', 'critical')
logger.error(f"Erreur monitoring base de données: {e}")
async def monitor_business_metrics(self):
"""Surveillance métriques business"""
try:
with self.db_engine.connect() as conn:
# Investigations actives
investigations_result = conn.execute(text("""
SELECT COUNT(*) FROM investigations WHERE status = 'active'
"""))
active_inv_count = investigations_result.fetchone()[0]
active_investigations.set(active_inv_count)
# Analyses échouées (dernières 24h)
failed_result = conn.execute(text("""
SELECT COUNT(*) FROM analysis_results
WHERE created_at > NOW() - INTERVAL '24 hours'
AND confidence_score < 0.5
"""))
failed_count = failed_result.fetchone()[0]
if failed_count > MonitoringConfig.THRESHOLDS['failed_analyses']:
await self.send_alert('business', f'Trop d\'analyses échouées: {failed_count}', 'warning')
# Alertes par sévérité (dernières 24h)
alerts_result = conn.execute(text("""
SELECT sev
- monitoring.html +349 -0
|
@@ -0,0 +1,349 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
```html
|
| 2 |
+
<!DOCTYPE html>
|
| 3 |
+
<html lang="en">
|
| 4 |
+
<head>
|
| 5 |
+
<meta charset="UTF-8">
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 7 |
+
<title>Monitoring | HTS Investigation Suite</title>
|
| 8 |
+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
| 9 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script>
|
| 12 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
| 13 |
+
<style>
|
| 14 |
+
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Rubik:wght@300;400;500;600;700&display=swap');
|
| 15 |
+
body {
|
| 16 |
+
font-family: 'Rubik', sans-serif;
|
| 17 |
+
}
|
| 18 |
+
.vanta-canvas {
|
| 19 |
+
position: absolute;
|
| 20 |
+
top: 0;
|
| 21 |
+
left: 0;
|
| 22 |
+
width: 100%;
|
| 23 |
+
height: 100%;
|
| 24 |
+
z-index: 0;
|
| 25 |
+
opacity: 0.15;
|
| 26 |
+
}
|
| 27 |
+
.alert-critical {
|
| 28 |
+
background: linear-gradient(90deg, rgba(239,68,68,0.1) 0%, rgba(239,68,68,0.3) 100%);
|
| 29 |
+
border-left: 4px solid #ef4444;
|
| 30 |
+
}
|
| 31 |
+
.alert-high {
|
| 32 |
+
background: linear-gradient(90deg, rgba(249,115,22,0.1) 0%, rgba(249,115,22,0.3) 100%);
|
| 33 |
+
border-left: 4px solid #f97316;
|
| 34 |
+
}
|
| 35 |
+
.alert-medium {
|
| 36 |
+
background: linear-gradient(90deg, rgba(234,179,8,0.1) 0%, rgba(234,179,8,0.3) 100%);
|
| 37 |
+
border-left: 4px solid #eab308;
|
| 38 |
+
}
|
| 39 |
+
.alert-low {
|
| 40 |
+
background: linear-gradient(90deg, rgba(59,130,246,0.1) 0%, rgba(59,130,246,0.3) 100%);
|
| 41 |
+
border-left: 4px solid #3b82f6;
|
| 42 |
+
}
|
| 43 |
+
.animate-pulse-slow {
|
| 44 |
+
animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
| 45 |
+
}
|
| 46 |
+
@keyframes pulse {
|
| 47 |
+
0%, 100% { opacity: 1; }
|
| 48 |
+
50% { opacity: 0.5; }
|
| 49 |
+
}
|
| 50 |
+
</style>
|
| 51 |
+
</head>
|
| 52 |
+
<body class="bg-gray-50">
|
| 53 |
+
<div id="vanta-bg" class="vanta-canvas"></div>
|
| 54 |
+
|
| 55 |
+
<!-- Header -->
|
| 56 |
+
<header class="relative z-10 bg-white shadow-lg border-b border-gray-200">
|
| 57 |
+
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
| 58 |
+
<div class="flex items-center justify-between">
|
| 59 |
+
<div class="flex items-center space-x-4">
|
| 60 |
+
<div class="bg-blue-600 p-2 rounded-lg">
|
| 61 |
+
<i data-feather="shield" class="text-white w-6 h-6"></i>
|
| 62 |
+
</div>
|
| 63 |
+
<div>
|
| 64 |
+
<h1 class="text-2xl font-bold text-gray-900">HIGH TECH SECURITY</h1>
|
| 65 |
+
<p class="text-sm text-gray-600">HTS Investigation Suite v2.1</p>
|
| 66 |
+
</div>
|
| 67 |
+
</div>
|
| 68 |
+
|
| 69 |
+
<div class="hidden md:flex items-center space-x-6">
|
| 70 |
+
<div class="text-right">
|
| 71 |
+
<div class="text-gray-600">203-205 The Vale, London W3 7QS</div>
|
| 72 |
+
<div class="text-gray-600">UK: +44 7591 665201 | Company: 7849187</div>
|
| 73 |
+
</div>
|
| 74 |
+
<div class="flex items-center space-x-2">
|
| 75 |
+
<i data-feather="lock" class="w-5 h-5 text-green-500"></i>
|
| 76 |
+
<span class="text-sm text-green-600 font-medium">Sécurisé</span>
|
| 77 |
+
</div>
|
| 78 |
+
</div>
|
| 79 |
+
</div>
|
| 80 |
+
</div>
|
| 81 |
+
</header>
|
| 82 |
+
|
| 83 |
+
<!-- Navigation -->
|
| 84 |
+
<nav class="relative z-10 bg-gray-800 text-white">
|
| 85 |
+
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
| 86 |
+
<div class="flex space-x-1 overflow-x-auto py-2 hide-scrollbar">
|
| 87 |
+
<a href="/" class="flex items-center space-x-2 px-4 py-3 border-b-2 border-transparent hover:border-gray-600 transition-colors">
|
| 88 |
+
<i data-feather="trending-up" class="w-4 h-4"></i>
|
| 89 |
+
<span>Dashboard</span>
|
| 90 |
+
</a>
|
| 91 |
+
<a href="/darkbert" class="flex items-center space-x-2 px-4 py-3 border-b-2 border-transparent hover:border-gray-600 transition-colors">
|
| 92 |
+
<i data-feather="brain" class="w-4 h-4"></i>
|
| 93 |
+
<span>DarkBERT Analysis</span>
|
| 94 |
+
</a>
|
| 95 |
+
<a href="/investigations" class="flex items-center space-x-2 px-4 py-3 border-b-2 border-transparent hover:border-gray-600 transition-colors">
|
| 96 |
+
<i data-feather="search" class="w-4 h-4"></i>
|
| 97 |
+
<span>Investigations</span>
|
| 98 |
+
</a>
|
| 99 |
+
<a href="/monitoring" class="flex items-center space-x-2 px-4 py-3 border-b-2 border-blue-400 text-blue-400 transition-colors">
|
| 100 |
+
<i data-feather="eye" class="w-4 h-4"></i>
|
| 101 |
+
<span>Monitoring</span>
|
| 102 |
+
</a>
|
| 103 |
+
</div>
|
| 104 |
+
</div>
|
| 105 |
+
</nav>
|
| 106 |
+
|
| 107 |
+
<!-- Main Content -->
|
| 108 |
+
<main class="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
| 109 |
+
<!-- System Status Overview -->
|
| 110 |
+
<div class="bg-white rounded-xl shadow-lg p-6 mb-8">
|
| 111 |
+
<div class="flex items-center justify-between mb-6">
|
| 112 |
+
<h2 class="text-2xl font-bold text-gray-900">System Monitoring Dashboard</h2>
|
| 113 |
+
<div class="flex items-center space-x-2">
|
| 114 |
+
<div class="w-2 h-2 rounded-full bg-green-500 animate-pulse-slow"></div>
|
| 115 |
+
<span class="text-sm text-gray-600">Real-time monitoring active</span>
|
| 116 |
+
</div>
|
| 117 |
+
</div>
|
| 118 |
+
|
| 119 |
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
| 120 |
+
<!-- CPU Usage -->
|
| 121 |
+
<div class="bg-white rounded-xl shadow p-4 border border-gray-200">
|
| 122 |
+
<div class="flex items-center justify-between mb-2">
|
| 123 |
+
<div class="flex items-center space-x-2">
|
| 124 |
+
<i data-feather="cpu" class="w-5 h-5 text-blue-600"></i>
|
| 125 |
+
<span class="font-medium text-gray-700">CPU Usage</span>
|
| 126 |
+
</div>
|
| 127 |
+
<span class="text-sm font-bold" id="cpu-percent">--%</span>
|
| 128 |
+
</div>
|
| 129 |
+
<div class="h-2 bg-gray-200 rounded-full overflow-hidden">
|
| 130 |
+
<div id="cpu-bar" class="h-full bg-blue-600 rounded-full" style="width: 0%"></div>
|
| 131 |
+
</div>
|
| 132 |
+
</div>
|
| 133 |
+
|
| 134 |
+
<!-- Memory Usage -->
|
| 135 |
+
<div class="bg-white rounded-xl shadow p-4 border border-gray-200">
|
| 136 |
+
<div class="flex items-center justify-between mb-2">
|
| 137 |
+
<div class="flex items-center space-x-2">
|
| 138 |
+
<i data-feather="hard-drive" class="w-5 h-5 text-purple-600"></i>
|
| 139 |
+
<span class="font-medium text-gray-700">Memory Usage</span>
|
| 140 |
+
</div>
|
| 141 |
+
<span class="text-sm font-bold" id="memory-percent">--%</span>
|
| 142 |
+
</div>
|
| 143 |
+
<div class="h-2 bg-gray-200 rounded-full overflow-hidden">
|
| 144 |
+
<div id="memory-bar" class="h-full bg-purple-600 rounded-full" style="width: 0%"></div>
|
| 145 |
+
</div>
|
| 146 |
+
</div>
|
| 147 |
+
|
| 148 |
+
<!-- Disk Usage -->
|
| 149 |
+
<div class="bg-white rounded-xl shadow p-4 border border-gray-200">
|
| 150 |
+
<div class="flex items-center justify-between mb-2">
|
| 151 |
+
<div class="flex items-center space-x-2">
|
| 152 |
+
<i data-feather="database" class="w-5 h-5 text-orange-600"></i>
|
| 153 |
+
<span class="font-medium text-gray-700">Disk Usage</span>
|
| 154 |
+
</div>
|
| 155 |
+
<span class="text-sm font-bold" id="disk-percent">--%</span>
|
| 156 |
+
</div>
|
| 157 |
+
<div class="h-2 bg-gray-200 rounded-full overflow-hidden">
|
| 158 |
+
<div id="disk-bar" class="h-full bg-orange-600 rounded-full" style="width: 0%"></div>
|
| 159 |
+
</div>
|
| 160 |
+
</div>
|
| 161 |
+
|
| 162 |
+
<!-- Active Investigations -->
|
| 163 |
+
<div class="bg-white rounded-xl shadow p-4 border border-gray-200">
|
| 164 |
+
<div class="flex items-center justify-between mb-2">
|
| 165 |
+
<div class="flex items-center space-x-2">
|
| 166 |
+
<i data-feather="file-text" class="w-5 h-5 text-green-600"></i>
|
| 167 |
+
<span class="font-medium text-gray-700">Active Investigations</span>
|
| 168 |
+
</div>
|
| 169 |
+
<span class="text-sm font-bold" id="active-investigations">--</span>
|
| 170 |
+
</div>
|
| 171 |
+
<div class="h-2 bg-gray-200 rounded-full overflow-hidden">
|
| 172 |
+
<div id="investigations-bar" class="h-full bg-green-600 rounded-full" style="width: 0%"></div>
|
| 173 |
+
</div>
|
| 174 |
+
</div>
|
| 175 |
+
</div>
|
| 176 |
+
|
| 177 |
+
<!-- Resource Usage Charts -->
|
| 178 |
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
|
| 179 |
+
<div class="bg-white rounded-xl shadow-lg p-4 border border-gray-200">
|
| 180 |
+
<h3 class="text-lg font-semibold text-gray-900 mb-4">CPU & Memory Usage (Last 24h)</h3>
|
| 181 |
+
<canvas id="system-usage-chart" height="200"></canvas>
|
| 182 |
+
</div>
|
| 183 |
+
<div class="bg-white rounded-xl shadow-lg p-4 border border-gray-200">
|
| 184 |
+
<h3 class="text-lg font-semibold text-gray-900 mb-4">API Response Times (Last 24h)</h3>
|
| 185 |
+
<canvas id="api-response-chart" height="200"></canvas>
|
| 186 |
+
</div>
|
| 187 |
+
</div>
|
| 188 |
+
|
| 189 |
+
<!-- Alerts Section -->
|
| 190 |
+
<div class="bg-white rounded-xl shadow-lg p-6 border border-gray-200">
|
| 191 |
+
<div class="flex items-center justify-between mb-4">
|
| 192 |
+
<h3 class="text-lg font-semibold text-gray-900">Recent Alerts</h3>
|
| 193 |
+
<div class="flex space-x-2">
|
| 194 |
+
<button class="px-3 py-1 text-xs bg-blue-100 text-blue-800 rounded-full">All</button>
|
| 195 |
+
<button class="px-3 py-1 text-xs bg-red-100 text-red-800 rounded-full">Critical</button>
|
| 196 |
+
<button class="px-3 py-1 text-xs bg-orange-100 text-orange-800 rounded-full">High</button>
|
| 197 |
+
<button class="px-3 py-1 text-xs bg-yellow-100 text-yellow-800 rounded-full">Medium</button>
|
| 198 |
+
<button class="px-3 py-1 text-xs bg-blue-100 text-blue-800 rounded-full">Low</button>
|
| 199 |
+
</div>
|
| 200 |
+
</div>
|
| 201 |
+
|
| 202 |
+
<div class="space-y-3 max-h-96 overflow-y-auto">
|
| 203 |
+
<!-- Sample Alert Items -->
|
| 204 |
+
<div class="p-4 rounded-lg alert-critical">
|
| 205 |
+
<div class="flex justify-between items-start">
|
| 206 |
+
<div>
|
| 207 |
+
<span class="font-medium">Critical CPU Usage (95.7%)</span>
|
| 208 |
+
<span class="text-xs ml-2 px-2 py-1 bg-red-600 text-white rounded-full">Critical</span>
|
| 209 |
+
</div>
|
| 210 |
+
<span class="text-xs text-gray-500">2 min ago</span>
|
| 211 |
+
</div>
|
| 212 |
+
<p class="text-sm mt-1">CPU usage exceeds critical threshold of 90%</p>
|
| 213 |
+
</div>
|
| 214 |
+
|
| 215 |
+
<div class="p-4 rounded-lg alert-high">
|
| 216 |
+
<div class="flex justify-between items-start">
|
| 217 |
+
<div>
|
| 218 |
+
<span class="font-medium">High Memory Usage (87.2%)</span>
|
| 219 |
+
<span class="text-xs ml-2 px-2 py-1 bg-orange-600 text-white rounded-full">High</span>
|
| 220 |
+
</div>
|
| 221 |
+
<span class="text-xs text-gray-500">15 min ago</span>
|
| 222 |
+
</div>
|
| 223 |
+
<p class="text-sm mt-1">Memory usage exceeds warning threshold of 85%</p>
|
| 224 |
+
</div>
|
| 225 |
+
|
| 226 |
+
<div class="p-4 rounded-lg alert-medium">
|
| 227 |
+
<div class="flex justify-between items-start">
|
| 228 |
+
<div>
|
| 229 |
+
<span class="font-medium">Slow API Response (5.2s)</span>
|
| 230 |
+
<span class="text-xs ml-2 px-2 py-1 bg-yellow-600 text-white rounded-full">Medium</span>
|
| 231 |
+
</div>
|
| 232 |
+
<span class="text-xs text-gray-500">1 hour ago</span>
|
| 233 |
+
</div>
|
| 234 |
+
<p class="text-sm mt-1">API endpoint /health responded slowly</p>
|
| 235 |
+
</div>
|
| 236 |
+
|
| 237 |
+
<div class="p-4 rounded-lg alert-low">
|
| 238 |
+
<div class="flex justify-between items-start">
|
| 239 |
+
<div>
|
| 240 |
+
<span class="font-medium">Database Connection Warning</span>
|
| 241 |
+
<span class="text-xs ml-2 px-2 py-1 bg-blue-600 text-white rounded-full">Low</span>
|
| 242 |
+
</div>
|
| 243 |
+
<span class="text-xs text-gray-500">3 hours ago</span>
|
| 244 |
+
</div>
|
| 245 |
+
<p class="text-sm mt-1">Database response time exceeded 2 seconds</p>
|
| 246 |
+
</div>
|
| 247 |
+
</div>
|
| 248 |
+
</div>
|
| 249 |
+
</div>
|
| 250 |
+
</main>
|
| 251 |
+
|
| 252 |
+
<script>
|
| 253 |
+
// Initialize Vanta.js globe effect
|
| 254 |
+
feather.replace();
|
| 255 |
+
VANTA.GLOBE({
|
| 256 |
+
el: "#vanta-bg",
|
| 257 |
+
mouseControls: true,
|
| 258 |
+
touchControls: true,
|
| 259 |
+
gyroControls: false,
|
| 260 |
+
minHeight: 200.00,
|
| 261 |
+
minWidth: 200.00,
|
| 262 |
+
scale: 1.00,
|
| 263 |
+
scaleMobile: 1.00,
|
| 264 |
+
color: 0x3b82f6,
|
| 265 |
+
backgroundColor: 0xf8fafc,
|
| 266 |
+
size: 0.8
|
| 267 |
+
});
|
| 268 |
+
|
| 269 |
+
// Initialize charts
|
| 270 |
+
const systemUsageCtx = document.getElementById('system-usage-chart').getContext('2d');
|
| 271 |
+
const apiResponseCtx = document.getElementById('api-response-chart').getContext('2d');
|
| 272 |
+
|
| 273 |
+
// Sample data for charts
|
| 274 |
+
const labels = Array.from({length: 24}, (_, i) => `${i}:00`);
|
| 275 |
+
|
| 276 |
+
const systemUsageChart = new Chart(systemUsageCtx, {
|
| 277 |
+
type: 'line',
|
| 278 |
+
data: {
|
| 279 |
+
labels: labels,
|
| 280 |
+
datasets: [
|
| 281 |
+
{
|
| 282 |
+
label: 'CPU Usage (%)',
|
| 283 |
+
data: [45, 48, 52, 55, 60, 65, 70, 75, 80, 85, 90, 95, 92, 88, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40],
|
| 284 |
+
borderColor: '#3b82f6',
|
| 285 |
+
backgroundColor: 'rgba(59, 130, 246, 0.1)',
|
| 286 |
+
tension: 0.3,
|
| 287 |
+
fill: true
|
| 288 |
+
},
|
| 289 |
+
{
|
| 290 |
+
label: 'Memory Usage (%)',
|
| 291 |
+
data: [60, 62, 65, 68, 70, 72, 75, 78, 80, 82, 85, 87, 85, 82, 80, 78, 75, 72, 70, 68, 65, 62, 60, 58],
|
| 292 |
+
borderColor: '#8b5cf6',
|
| 293 |
+
backgroundColor: 'rgba(139, 92, 246, 0.1)',
|
| 294 |
+
tension: 0.3,
|
| 295 |
+
fill: true
|
| 296 |
+
}
|
| 297 |
+
]
|
| 298 |
+
},
|
| 299 |
+
options: {
|
| 300 |
+
responsive: true,
|
| 301 |
+
plugins: {
|
| 302 |
+
legend: {
|
| 303 |
+
position: 'top',
|
| 304 |
+
}
|
| 305 |
+
},
|
| 306 |
+
scales: {
|
| 307 |
+
y: {
|
| 308 |
+
beginAtZero: true,
|
| 309 |
+
max: 100
|
| 310 |
+
}
|
| 311 |
+
}
|
| 312 |
+
}
|
| 313 |
+
});
|
| 314 |
+
|
| 315 |
+
const apiResponseChart = new Chart(apiResponseCtx, {
|
| 316 |
+
type: 'bar',
|
| 317 |
+
data: {
|
| 318 |
+
labels: labels,
|
| 319 |
+
datasets: [
|
| 320 |
+
{
|
| 321 |
+
label: 'API Response Time (ms)',
|
| 322 |
+
data: [120, 150, 180, 200, 220, 250, 300, 350, 400, 450, 500, 550, 500, 450, 400, 350, 300, 250, 200, 150, 120, 100, 90, 80],
|
| 323 |
+
backgroundColor: '#10b981',
|
| 324 |
+
borderColor: '#10b981',
|
| 325 |
+
borderWidth: 1
|
| 326 |
+
}
|
| 327 |
+
]
|
| 328 |
+
},
|
| 329 |
+
options: {
|
| 330 |
+
responsive: true,
|
| 331 |
+
plugins: {
|
| 332 |
+
legend: {
|
| 333 |
+
position: 'top',
|
| 334 |
+
}
|
| 335 |
+
},
|
| 336 |
+
scales: {
|
| 337 |
+
y: {
|
| 338 |
+
beginAtZero: true
|
| 339 |
+
}
|
| 340 |
+
}
|
| 341 |
+
}
|
| 342 |
+
});
|
| 343 |
+
|
| 344 |
+
// Simulate real-time updates
|
| 345 |
+
function updateMetrics() {
|
| 346 |
+
// Simulate random values
|
| 347 |
+
const cpu = Math.floor(Math.random() * 30) + 60;
|
| 348 |
+
const memory = Math.floor(Math.random() * 25) + 60;
|
| 349 |
+
const disk = Math.floor(Math.random()
|