import gradio as gr from transformers import pipeline import re def anomalies_detector(logs: str) -> str: """ Detect anomalies in software logs using a Hugging Face transformer model. This function uses a specialized model trained to identify unusual patterns in system logs, such as: - Error messages - Unusual system states - Security-related events - Performance anomalies - Unexpected behavior patterns Args: logs (str): The input text containing log entries Returns: str: Formatted analysis results with detected anomalies """ if not logs or not logs.strip(): return "⚠️ No log data provided. Please enter log entries to analyze." # Initialize the text classification pipeline classifier = pipeline( "text-classification", model="distilbert/distilbert-base-uncased-finetuned-sst-2-english" ) # Split logs into lines log_lines = [line for line in logs.split('\n') if line.strip()] if not log_lines: return "⚠️ No valid log entries found." # Process each line anomalies = [] total_lines = len(log_lines) negative_count = 0 for line_num, line in enumerate(log_lines, 1): try: # Get classification result result = classifier(line[:512])[0] # Limit to 512 chars for model # Consider "NEGATIVE" sentiment as potential anomaly if result['label'] == 'NEGATIVE' and result['score'] > 0.7: anomalies.append({ 'line': line_num, 'text': line, 'confidence': result['score'] }) negative_count += 1 except Exception as e: continue # Format output output = f"📊 **Analysis Summary**\n" output += f"{'='*60}\n\n" output += f"📝 Total log entries analyzed: **{total_lines}**\n" output += f"🔍 Potential anomalies detected: **{negative_count}**\n" output += f"✅ Health rate: **{((total_lines - negative_count) / total_lines * 100):.1f}%**\n\n" if anomalies: output += f"⚠️ **Detected Anomalies:**\n" output += f"{'-'*60}\n\n" for idx, anomaly in enumerate(anomalies, 1): output += f"**#{idx} | Line {anomaly['line']}** (Confidence: {anomaly['confidence']:.2%})\n" output += f"```\n{anomaly['text']}\n```\n\n" else: output += "✨ **No significant anomalies detected!**\n" output += "Your logs appear to be healthy.\n" return output # Custom CSS for dark navy blue and electric blue theme custom_css = """ :root { --electric-blue: #00D4FF; --bright-blue: #0099FF; --navy-blue: #001F3F; --dark-navy: #001129; --deep-navy: #000814; --white: #FFFFFF; --off-white: #F8FCFF; --light-gray: #E8F4F8; --cyber-glow: rgba(0, 212, 255, 0.3); } /* Main background */ .gradio-container { background: linear-gradient(135deg, var(--deep-navy) 0%, var(--dark-navy) 50%, var(--navy-blue) 100%) !important; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important; position: relative !important; } .gradio-container::before { content: '' !important; position: absolute !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; background: radial-gradient(circle at 20% 50%, rgba(0, 212, 255, 0.08) 0%, transparent 50%), radial-gradient(circle at 80% 80%, rgba(0, 153, 255, 0.06) 0%, transparent 50%) !important; pointer-events: none !important; } /* Header styling */ .contain { background: rgba(255, 255, 255, 0.98) !important; border-radius: 20px !important; box-shadow: 0 20px 60px rgba(0, 212, 255, 0.2), 0 0 40px rgba(0, 153, 255, 0.1) !important; padding: 2rem !important; margin: 2rem auto !important; max-width: 1400px !important; border: 1px solid rgba(0, 212, 255, 0.1) !important; } /* Title styling */ h1 { background: linear-gradient(135deg, var(--bright-blue), var(--electric-blue)) !important; -webkit-background-clip: text !important; -webkit-text-fill-color: transparent !important; background-clip: text !important; font-weight: 800 !important; font-size: 2.5rem !important; margin-bottom: 0.5rem !important; text-align: center !important; filter: drop-shadow(0 0 20px rgba(0, 212, 255, 0.3)) !important; } /* Description text */ .prose p { color: var(--navy-blue) !important; font-size: 1.1rem !important; text-align: center !important; margin-bottom: 1.5rem !important; } /* Input/Output boxes */ .input-text, .output-text, textarea { border: 2px solid var(--bright-blue) !important; border-radius: 12px !important; background: var(--white) !important; font-family: 'Fira Code', 'Courier New', monospace !important; font-size: 0.95rem !important; transition: all 0.3s ease !important; box-shadow: 0 2px 10px rgba(0, 153, 255, 0.1) !important; } .input-text:focus, textarea:focus { border-color: var(--electric-blue) !important; box-shadow: 0 0 0 3px var(--cyber-glow), 0 0 20px rgba(0, 212, 255, 0.2) !important; outline: none !important; } /* Labels */ label { color: var(--navy-blue) !important; font-weight: 600 !important; font-size: 1rem !important; margin-bottom: 0.5rem !important; } /* Submit button */ .submit-button, button[id$="-submit-button"] { background: linear-gradient(135deg, var(--bright-blue), var(--electric-blue)) !important; color: var(--white) !important; border: none !important; border-radius: 12px !important; padding: 0.75rem 2rem !important; font-weight: 600 !important; font-size: 1rem !important; cursor: pointer !important; transition: all 0.3s ease !important; box-shadow: 0 4px 15px rgba(0, 212, 255, 0.3), 0 0 20px rgba(0, 153, 255, 0.2) !important; } .submit-button:hover, button[id$="-submit-button"]:hover { transform: translateY(-2px) !important; box-shadow: 0 6px 20px rgba(0, 212, 255, 0.4), 0 0 30px rgba(0, 153, 255, 0.3) !important; filter: brightness(1.1) !important; } /* Clear button */ .clear-button, button.secondary { background: var(--white) !important; color: var(--navy-blue) !important; border: 2px solid var(--bright-blue) !important; border-radius: 12px !important; padding: 0.75rem 2rem !important; font-weight: 600 !important; transition: all 0.3s ease !important; } .clear-button:hover, button.secondary:hover { background: var(--electric-blue) !important; color: var(--white) !important; transform: translateY(-2px) !important; box-shadow: 0 4px 15px rgba(0, 212, 255, 0.3) !important; } /* Output markdown styling */ .markdown-text { background: var(--off-white) !important; padding: 1.5rem !important; border-radius: 12px !important; border-left: 4px solid var(--electric-blue) !important; box-shadow: 0 2px 10px rgba(0, 153, 255, 0.1) !important; } .markdown-text code { background: var(--white) !important; padding: 0.2rem 0.4rem !important; border-radius: 4px !important; color: var(--navy-blue) !important; border: 1px solid var(--bright-blue) !important; } .markdown-text pre { background: var(--white) !important; border: 2px solid var(--bright-blue) !important; border-radius: 8px !important; padding: 1rem !important; box-shadow: inset 0 2px 8px rgba(0, 153, 255, 0.05) !important; } /* Footer */ footer { background: transparent !important; color: var(--white) !important; text-align: center !important; padding: 2rem !important; text-shadow: 0 0 10px rgba(0, 212, 255, 0.5) !important; } footer a { color: var(--electric-blue) !important; text-decoration: underline !important; } /* Examples section */ .examples { background: var(--off-white) !important; border-radius: 12px !important; padding: 1rem !important; border: 2px solid var(--bright-blue) !important; box-shadow: 0 2px 10px rgba(0, 153, 255, 0.1) !important; } /* Scrollbar styling */ ::-webkit-scrollbar { width: 10px !important; } ::-webkit-scrollbar-track { background: var(--light-gray) !important; border-radius: 5px !important; } ::-webkit-scrollbar-thumb { background: linear-gradient(180deg, var(--electric-blue), var(--bright-blue)) !important; border-radius: 5px !important; box-shadow: 0 0 10px rgba(0, 212, 255, 0.3) !important; } ::-webkit-scrollbar-thumb:hover { background: var(--electric-blue) !important; box-shadow: 0 0 15px rgba(0, 212, 255, 0.5) !important; } /* Cyber glow effects */ .submit-button::before, button[id$="-submit-button"]::before { content: '' !important; position: absolute !important; top: -2px !important; left: -2px !important; right: -2px !important; bottom: -2px !important; background: linear-gradient(45deg, var(--electric-blue), var(--bright-blue)) !important; border-radius: 12px !important; z-index: -1 !important; opacity: 0 !important; transition: opacity 0.3s ease !important; filter: blur(10px) !important; } .submit-button:hover::before, button[id$="-submit-button"]:hover::before { opacity: 0.7 !important; } """ # Example logs for demonstration example_logs = [ """2024-01-29 10:15:23 INFO User logged in successfully 2024-01-29 10:15:45 INFO Database connection established 2024-01-29 10:16:02 ERROR Failed to connect to payment gateway 2024-01-29 10:16:15 WARN Retry attempt 1 of 3 2024-01-29 10:16:30 ERROR Connection timeout after 30 seconds 2024-01-29 10:16:45 CRITICAL Payment service unavailable""", """2024-01-29 14:22:10 INFO Application started successfully 2024-01-29 14:22:15 INFO Loading configuration files 2024-01-29 14:22:18 INFO Server listening on port 8080 2024-01-29 14:22:20 INFO Ready to accept connections""", """2024-01-29 16:30:45 INFO User authentication request 2024-01-29 16:30:46 WARN Invalid credentials provided 2024-01-29 16:30:50 WARN Login attempt failed for user: admin 2024-01-29 16:30:55 ERROR Multiple failed login attempts detected 2024-01-29 16:31:00 CRITICAL Potential security breach - IP blocked""" ] # Create the Gradio interface demo = gr.Interface( fn=anomalies_detector, inputs=gr.Textbox( label="📋 Log Entries", placeholder="Paste your software logs here (mobile app, desktop, web server, etc.)\n\nExample:\n2024-01-29 10:15:23 INFO User logged in\n2024-01-29 10:16:02 ERROR Connection failed\n2024-01-29 10:16:15 WARN Retry attempt...", lines=15, max_lines=25 ), outputs=gr.Markdown( label="🔍 Analysis Results" ), title="🛡️ Sentinel Log Analyzer", description="**Enterprise-grade anomaly detection for all your software logs.** Supports mobile apps, desktop applications, web servers, and more. Powered by advanced AI to identify errors, security events, and unusual patterns in real-time.", examples=example_logs, css=custom_css, theme=gr.themes.Soft( primary_hue="blue", secondary_hue="cyan", ), allow_flagging="never", analytics_enabled=False ) # Launch the application if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860, share=True, show_error=True )