|
|
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." |
|
|
|
|
|
|
|
|
classifier = pipeline( |
|
|
"text-classification", |
|
|
model="distilbert/distilbert-base-uncased-finetuned-sst-2-english" |
|
|
) |
|
|
|
|
|
|
|
|
log_lines = [line for line in logs.split('\n') if line.strip()] |
|
|
|
|
|
if not log_lines: |
|
|
return "⚠️ No valid log entries found." |
|
|
|
|
|
|
|
|
anomalies = [] |
|
|
total_lines = len(log_lines) |
|
|
negative_count = 0 |
|
|
|
|
|
for line_num, line in enumerate(log_lines, 1): |
|
|
try: |
|
|
|
|
|
result = classifier(line[:512])[0] |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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 = """ |
|
|
: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 = [ |
|
|
"""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""" |
|
|
] |
|
|
|
|
|
|
|
|
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 |
|
|
) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch( |
|
|
server_name="0.0.0.0", |
|
|
server_port=7860, |
|
|
share=True, |
|
|
show_error=True |
|
|
) |