#!/usr/bin/env python3 """ Monitor translation quality in real-time. Shows statistics about translation quality and detects issues. """ import os import sys import time import psycopg2 from datetime import datetime, timedelta from dotenv import load_dotenv load_dotenv() DB_CONFIG = { "host": os.environ.get("DB_HOST", "localhost"), "port": int(os.environ.get("DB_PORT", 5432)), "dbname": os.environ.get("DB_NAME", "rss"), "user": os.environ.get("DB_USER", "rss"), "password": os.environ.get("DB_PASS", ""), } def get_stats(conn, hours=24): """Get translation statistics for the last N hours.""" with conn.cursor() as cur: # Total translations in period cur.execute(""" SELECT COUNT(*) as total, COUNT(CASE WHEN status='done' THEN 1 END) as done, COUNT(CASE WHEN status='pending' THEN 1 END) as pending, COUNT(CASE WHEN status='processing' THEN 1 END) as processing, COUNT(CASE WHEN status='error' THEN 1 END) as errors FROM traducciones WHERE created_at > NOW() - INTERVAL '%s hours' """, (hours,)) stats = cur.fetchone() # Check for repetitive patterns in recent translations cur.execute(""" SELECT COUNT(*) FROM traducciones WHERE status='done' AND created_at > NOW() - INTERVAL '%s hours' AND ( resumen_trad LIKE '%%la lΓ­nea de la lΓ­nea%%' OR resumen_trad LIKE '%%de la la %%' OR resumen_trad LIKE '%%de Internet de Internet%%' ) """, (hours,)) repetitive = cur.fetchone()[0] # Get error messages cur.execute(""" SELECT error, COUNT(*) as count FROM traducciones WHERE status='error' AND created_at > NOW() - INTERVAL '%s hours' GROUP BY error ORDER BY count DESC LIMIT 5 """, (hours,)) errors = cur.fetchall() return { 'total': stats[0], 'done': stats[1], 'pending': stats[2], 'processing': stats[3], 'errors': stats[4], 'repetitive': repetitive, 'error_details': errors } def print_stats(stats, hours): """Pretty print statistics.""" print(f"\n{'='*60}") print(f"πŸ“Š Translation Quality Report - Last {hours}h") print(f"{'='*60}") print(f"Total Translations: {stats['total']}") print(f" βœ… Done: {stats['done']:>6} ({stats['done']/max(stats['total'],1)*100:>5.1f}%)") print(f" ⏳ Pending: {stats['pending']:>6} ({stats['pending']/max(stats['total'],1)*100:>5.1f}%)") print(f" πŸ”„ Processing: {stats['processing']:>6} ({stats['processing']/max(stats['total'],1)*100:>5.1f}%)") print(f" ❌ Errors: {stats['errors']:>6} ({stats['errors']/max(stats['total'],1)*100:>5.1f}%)") print(f"\nπŸ” Quality Issues:") print(f" ⚠️ Repetitive: {stats['repetitive']:>6} ({stats['repetitive']/max(stats['done'],1)*100:>5.1f}% of done)") if stats['error_details']: print(f"\nπŸ“‹ Top Error Messages:") for error, count in stats['error_details']: error_short = (error[:50] + '...') if error and len(error) > 50 else (error or 'Unknown') print(f" β€’ {error_short}: {count}") # Quality score if stats['done'] > 0: quality_score = (1 - stats['repetitive'] / stats['done']) * 100 quality_emoji = "🟒" if quality_score > 95 else "🟑" if quality_score > 90 else "πŸ”΄" print(f"\n{quality_emoji} Quality Score: {quality_score:.1f}%") print(f"{'='*60}\n") def main(): import argparse parser = argparse.ArgumentParser(description='Monitor translation quality') parser.add_argument('--hours', type=int, default=24, help='Hours to look back (default: 24)') parser.add_argument('--watch', action='store_true', help='Continuous monitoring mode') parser.add_argument('--interval', type=int, default=60, help='Update interval in seconds (default: 60)') args = parser.parse_args() conn = psycopg2.connect(**DB_CONFIG) try: if args.watch: print("πŸ”„ Starting continuous monitoring (Ctrl+C to stop)...") while True: stats = get_stats(conn, args.hours) print(f"\033[2J\033[H") # Clear screen print(f"Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print_stats(stats, args.hours) time.sleep(args.interval) else: stats = get_stats(conn, args.hours) print_stats(stats, args.hours) except KeyboardInterrupt: print("\n\nπŸ‘‹ Monitoring stopped") finally: conn.close() if __name__ == "__main__": main()