""" Monitoring and metrics collection for FactsDB service Provides Prometheus/Grafana compatible metrics """ import time import threading from flask import Response import json from .database import DatabaseManager from .config import Config # Global metrics storage _metrics = { 'fact_extraction_count': 0, 'file_processing_count': 0, 'error_count': 0, 'last_extraction_time': 0, 'uptime_seconds': 0 } _metrics_lock = threading.Lock() def increment_fact_extraction(): """Increment fact extraction counter""" global _metrics with _metrics_lock: _metrics['fact_extraction_count'] += 1 _metrics['last_extraction_time'] = time.time() def increment_file_processing(): """Increment file processing counter""" global _metrics with _metrics_lock: _metrics['file_processing_count'] += 1 def increment_error(): """Increment error counter""" global _metrics with _metrics_lock: _metrics['error_count'] += 1 def get_metrics(): """Get current metrics in Prometheus format""" global _metrics with _metrics_lock: # Get database stats config = Config() db_manager = DatabaseManager(config.database) db_stats = db_manager.get_database_stats() metrics = [] metrics.append(f"# HELP factsdb_fact_extractions_total Total number of fact extractions") metrics.append(f"# TYPE factsdb_fact_extractions_total counter") metrics.append(f"factsdb_fact_extractions_total {int(_metrics['fact_extraction_count'])}") metrics.append(f"# HELP factsdb_files_processed_total Total number of files processed") metrics.append(f"# TYPE factsdb_files_processed_total counter") metrics.append(f"factsdb_files_processed_total {int(_metrics['file_processing_count'])}") metrics.append(f"# HELP factsdb_errors_total Total number of errors") metrics.append(f"# TYPE factsdb_errors_total counter") metrics.append(f"factsdb_errors_total {int(_metrics['error_count'])}") metrics.append(f"# HELP factsdb_uptime_seconds Service uptime in seconds") metrics.append(f"# TYPE factsdb_uptime_seconds counter") metrics.append(f"factsdb_uptime_seconds {int(_metrics['uptime_seconds'])}") metrics.append(f"# HELP factsdb_total_facts Current total facts in database") metrics.append(f"# TYPE factsdb_total_facts gauge") metrics.append(f"factsdb_total_facts {int(db_stats['total_facts'])}") metrics.append(f"# HELP factsdb_processed_files Current processed files count") metrics.append(f"# TYPE factsdb_processed_files gauge") metrics.append(f"factsdb_processed_files {int(db_stats['processed_files'])}") # Add table-specific metrics for table_name, count in db_stats['table_counts'].items(): metrics.append(f"# HELP factsdb_table_facts_count Number of facts in table '{table_name}'") metrics.append(f"# TYPE factsdb_table_facts_count gauge") metrics.append(f"factsdb_table_facts_count{{table='{table_name}'}} {int(count)}") return "\n".join(metrics) def get_metrics_json(): """Get current metrics in JSON format""" global _metrics with _metrics_lock: config = Config() db_manager = DatabaseManager(config.database) db_stats = db_manager.get_database_stats() return { 'metrics': { 'fact_extractions': int(_metrics['fact_extraction_count']), 'files_processed': int(_metrics['file_processing_count']), 'errors': int(_metrics['error_count']), 'uptime_seconds': int(_metrics['uptime_seconds']), 'total_facts': int(db_stats['total_facts']), 'processed_files': int(db_stats['processed_files']) }, 'database_stats': db_stats, 'timestamp': time.time() } def start_uptime_monitor(): """Start uptime monitoring thread""" def uptime_worker(): while True: time.sleep(1) global _metrics with _metrics_lock: _metrics['uptime_seconds'] += 1 thread = threading.Thread(target=uptime_worker, daemon=True) thread.start() return thread