oedb-backend/extractors/monitor_agendadulibre.py

212 lines
7.9 KiB
Python
Raw Normal View History

2025-10-04 19:26:00 +02:00
#!/usr/bin/env python3
"""
Script de monitoring pour le scraper agenda du libre
Affiche les statistiques et l'état du scraper
"""
import json
import os
import sys
from datetime import datetime, timedelta
from typing import Dict, Any
class AgendaDuLibreMonitor:
def __init__(self, data_file: str = "agendadulibre_events.json"):
self.data_file = data_file
self.events_data = self.load_events_data()
def load_events_data(self) -> Dict[str, Any]:
"""Charge les données d'événements"""
if os.path.exists(self.data_file):
try:
with open(self.data_file, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
print(f"❌ Erreur lors du chargement de {self.data_file}: {e}")
return {"events": {}, "last_update": None}
return {"events": {}, "last_update": None}
def get_statistics(self) -> Dict[str, Any]:
"""Calcule les statistiques des événements"""
events = self.events_data.get("events", {})
stats = {
"total_events": len(events),
"saved": 0,
"already_exists": 0,
"error": 0,
"unknown": 0,
"recent_errors": 0,
"last_update": self.events_data.get("last_update"),
"events_by_status": {},
"recent_events": []
}
# Analyser les statuts
for event_id, event_data in events.items():
status = event_data.get("status", "unknown")
stats["events_by_status"][status] = stats["events_by_status"].get(status, 0) + 1
if status == "saved":
stats["saved"] += 1
elif status == "already_exists":
stats["already_exists"] += 1
elif status == "error":
stats["error"] += 1
else:
stats["unknown"] += 1
# Vérifier les erreurs récentes (dernières 24h)
last_attempt = event_data.get("last_attempt")
if last_attempt and status == "error":
try:
attempt_time = datetime.fromisoformat(last_attempt.replace('Z', '+00:00'))
if datetime.now() - attempt_time.replace(tzinfo=None) < timedelta(hours=24):
stats["recent_errors"] += 1
except:
pass
# Collecter les événements récents (derniers 10)
if len(stats["recent_events"]) < 10:
event_info = {
"id": event_id,
"label": event_data.get("event", {}).get("properties", {}).get("label", "Sans titre"),
"status": status,
"last_attempt": last_attempt,
"message": event_data.get("message", "")
}
stats["recent_events"].append(event_info)
return stats
def display_statistics(self):
"""Affiche les statistiques de manière formatée"""
stats = self.get_statistics()
print("📊 Statistiques du scraper agenda du libre")
print("=" * 50)
# Informations générales
print(f"📁 Fichier de données: {self.data_file}")
print(f"📅 Dernière mise à jour: {stats['last_update'] or 'Jamais'}")
print(f"📈 Total d'événements traités: {stats['total_events']}")
print()
# Répartition par statut
print("📋 Répartition par statut:")
for status, count in stats["events_by_status"].items():
emoji = {
"saved": "",
"already_exists": "⚠️",
"error": "",
"unknown": ""
}.get(status, "")
print(f" {emoji} {status}: {count}")
print()
# Erreurs récentes
if stats["recent_errors"] > 0:
print(f"🚨 Erreurs récentes (24h): {stats['recent_errors']}")
print()
# Événements récents
if stats["recent_events"]:
print("🕒 Événements récents:")
for event in stats["recent_events"][:5]:
emoji = {
"saved": "",
"already_exists": "⚠️",
"error": "",
"unknown": ""
}.get(event["status"], "")
print(f" {emoji} {event['label'][:50]}{'...' if len(event['label']) > 50 else ''}")
if event["status"] == "error":
print(f" 💬 {event['message']}")
print()
# Recommandations
self.display_recommendations(stats)
def display_recommendations(self, stats: Dict[str, Any]):
"""Affiche des recommandations basées sur les statistiques"""
print("💡 Recommandations:")
if stats["total_events"] == 0:
print(" - Aucun événement traité. Exécutez le scraper pour commencer.")
elif stats["error"] > stats["saved"]:
print(" - Beaucoup d'erreurs détectées. Vérifiez la connectivité API.")
elif stats["recent_errors"] > 5:
print(" - Erreurs récentes nombreuses. Vérifiez les logs.")
elif stats["saved"] > 0:
print(" - Scraper fonctionne correctement.")
if stats["already_exists"] > stats["saved"]:
print(" - Beaucoup d'événements déjà existants. Le système de déduplication fonctionne.")
print()
def check_file_status(self):
"""Vérifie l'état du fichier de données"""
if not os.path.exists(self.data_file):
print(f"❌ Fichier de données non trouvé: {self.data_file}")
return False
try:
stat = os.stat(self.data_file)
size = stat.st_size
mtime = datetime.fromtimestamp(stat.st_mtime)
print(f"📁 État du fichier de données:")
print(f" - Taille: {size:,} octets")
print(f" - Dernière modification: {mtime}")
print(f" - Lisible: {'' if os.access(self.data_file, os.R_OK) else ''}")
print(f" - Écriture: {'' if os.access(self.data_file, os.W_OK) else ''}")
print()
return True
except Exception as e:
print(f"❌ Erreur lors de la vérification du fichier: {e}")
return False
def show_help(self):
"""Affiche l'aide"""
print("🔍 Monitor agenda du libre - Aide")
print("=" * 40)
print("Usage: python3 monitor_agendadulibre.py [options]")
print()
print("Options:")
print(" --stats, -s Afficher les statistiques (défaut)")
print(" --file, -f Vérifier l'état du fichier")
print(" --help, -h Afficher cette aide")
print()
print("Exemples:")
print(" python3 monitor_agendadulibre.py")
print(" python3 monitor_agendadulibre.py --file")
print(" python3 monitor_agendadulibre.py --stats")
def main():
"""Fonction principale"""
import argparse
parser = argparse.ArgumentParser(description="Monitor pour le scraper agenda du libre")
parser.add_argument("--stats", "-s", action="store_true", default=True,
help="Afficher les statistiques")
parser.add_argument("--file", "-f", action="store_true",
help="Vérifier l'état du fichier de données")
parser.add_argument("--data-file", default="agendadulibre_events.json",
help="Fichier de données à analyser")
args = parser.parse_args()
monitor = AgendaDuLibreMonitor(args.data_file)
if args.file:
monitor.check_file_status()
if args.stats:
monitor.display_statistics()
if __name__ == "__main__":
main()