AIOps - AI for IT Operations
This skill provides comprehensive patterns for implementing AIOps strategies in 2025, including intelligent monitoring, automated incident response, predictive analytics, and observability best practices. The patterns are designed to be framework-agnostic and applicable across different infrastructure platforms.
When to Use This Skill
Use this skill when you need to:
- Implement AIOps strategies for modern infrastructure
- Build intelligent monitoring and alerting systems
- Create automated incident response workflows
- Deploy predictive maintenance solutions
- Implement self-healing capabilities
- Build observability platforms with AI/ML
- Optimize multi-cloud operations
- Create chaos engineering practices
- Implement generative AI for operations
- Build digital twins for infrastructure
1. AIOps Architecture Patterns
Core AIOps Platform Architecture
# aiops/core/architecture.py
from abc import ABC, abstractmethod
from typing import Dict, List, Optional, Any, Union
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from enum import Enum
import asyncio
import json
import logging
logger = logging.getLogger(__name__)
class AlertSeverity(str, Enum):
"""Alert severity levels"""
CRITICAL = "critical"
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
INFO = "info"
class IncidentStatus(str, Enum):
"""Incident status"""
OPEN = "open"
INVESTIGATING = "investigating"
IDENTIFIED = "identified"
MONITORING = "monitoring"
RESOLVED = "resolved"
CLOSED = "closed"
@dataclass
class Metric:
"""Metric data point"""
name: str
value: float
timestamp: datetime
labels: Dict[str, str] = field(default_factory=dict)
source: str = ""
unit: str = ""
@dataclass
class LogEntry:
"""Structured log entry"""
timestamp: datetime
level: str
message: str
service: str
trace_id: Optional[str] = None
span_id: Optional[str] = None
labels: Dict[str, str] = field(default_factory=dict)
stack_trace: Optional[str] = None
@dataclass
class Trace:
"""Distributed trace data"""
trace_id: str
spans: List[Dict[str, Any]]
duration: timedelta
service_map: Dict[str, List[str]]
error_count: int = 0
@dataclass
class Alert:
"""Alert representation"""
id: str
name: str
severity: AlertSeverity
status: IncidentStatus
description: str
source: str
timestamp: datetime
labels: Dict[str, str] = field(default_factory=dict)
annotations: Dict[str, str] = field(default_factory=dict)
fingerprint: str = ""
related_entities: List[str] = field(default_factory=list)
class DataSource(ABC):
"""Abstract data source interface"""
@abstractmethod
async def collect_metrics(
self,
query: str,
start_time: datetime,
end_time: datetime
) -> List[Metric]:
"""Collect metrics from data source"""
pass
@abstractmethod
async def query_logs(
self,
query: str,
start_time: datetime,
end_time: datetime,
limit: int = 100
) -> List[LogEntry]:
"""Query logs from data source"""
pass
@abstractmethod
async def get_trace(self, trace_id: str) -> Optional[Trace]:
"""Get trace data"""
pass
class AIOpsEngine:
"""Core AIOps processing engine"""
def __init__(self):
self.data_sources: List[DataSource] = []
self.alert_processors: List[AlertProcessor] = []
self.ml_models: Dict[str, Any] = {}
self.knowledge_base: KnowledgeBase = KnowledgeBase()
self.automation_engine = AutomationEngine()
def register_data_source(self, data_source: DataSource) -> None:
"""Register a data source"""
self.data_sources.append(data_source)
logger.info(f"Registered data source: {type(data_source).__name__}")
def register_alert_processor(self, processor: 'AlertProcessor') -> None:
"""Register an alert processor"""
self.alert_processors.append(processor)
logger.info(f"Registered alert processor: {type(processor).__name__}")
async def process_alert(self, alert: Alert) -> Dict[str, Any]:
"""Process incoming alert through AIOps pipeline"""
logger.info(f"Processing alert: {alert.id} - {alert.name}")
# 1. Enrich alert with context
enriched_alert = await self._enrich_alert(alert)
# 2. Run through ML models for classification and prediction
analysis = await self._analyze_alert(enriched_alert)
# 3. Determine appropriate response
response_plan = await self._generate_response_plan(enriched_alert, analysis)
# 4. Execute automated actions if applicable
if response_plan.get("auto_execute", False):
await self._execute_response(enriched_alert, response_plan)
# 5. Update knowledge base
await self.knowledge_base.update_from_alert(enriched_alert, analysis, response_plan)
return {
"alert_id": alert.id,
"status": "processed",
"analysis": analysis,
"response_plan": response_plan
}
async def _enrich_alert(self, alert: Alert) -> Alert:
"""Enrich alert with additional context"""
# Get related metrics
for source in self.data_sources:
try:
metrics = await source.collect_metrics(
query=f"{alert.name}[5m]",
start_time=alert.timestamp - timedelta(minutes=5),
end_time=alert.timestamp
)
# Add metrics to alert annotations
alert.annotations[f"metrics_{type(source).__name__}"] = json.dumps([
{"name": m.name, "value": m.value} for m in metrics
])
except Exception as e:
logger.error(f"Failed to enrich alert with metrics: {e}")
# Get related logs
for source in self.data_sources:
try:
logs = await source.query_logs(
query=f"service:{alert.source} level:error",
start_time=alert.timestamp - timedelta(minutes=5),
end_time=alert.timestamp,
limit=10
)
# Add logs to alert context
alert.annotations["recent_errors"] = json.dumps([
{"timestamp": l.timestamp.isoformat(), "message": l.message}
for l in logs
])
except Exception as e:
logger.error(f"Failed to enrich alert with logs: {e}")
return alert
async def _analyze_alert(self, alert: Alert) -> Dict[str, Any]:
"""Analyze alert using ML models"""
analysis = {
"classification": None,
"severity_score": 0.0,
"predicted_impact": "low",
"recommendations": [],
"related_incidents": []
}
# Classification model
if "classification" in self.ml_models:
features = self._extract_features(alert)
analysis["classification"] = self.ml_models["classification"].predict([features])[0]
# Severity prediction
if "severity" in self.ml_models:
features = self._extract_features(alert)
analysis["severity_score"] = self.ml_models["severity"].predict_proba([features])[0][1]
# Impact prediction
if "impact" in self.ml_models:
features = self._extract_features(alert)
analysis["predicted_impact"] = self.ml_models["impact"].predict([features])[0]
# Find related incidents from knowledge base
analysis["related_incidents"] = await self.knowledge_base.find_similar_incidents(alert)
return analysis
async def _generate_response_plan(
self,
alert: Alert,
analysis: Dict[str, Any]
) -> Dict[str, Any]:
"""Generate automated response plan"""
plan = {
"priority": alert.severity,
"actions": [],
"escalation_rules": [],
"auto_execute": False,
"estimated_resolution_time": None
}
# Determine if auto-execution is safe
if (analysis["classification"] in ["known_issue", "false_positive"] and
alert.severity in [AlertSeverity.LOW, AlertSeverity.MEDIUM]):
plan["auto_execute"] = True
# Generate actions based on classification
classification = analysis.get("classification")
if classification == "resource_exhaustion":
plan["actions"].append({
"type": "scale",
"target": alert.source,
"params": {"replicas": "+20%"}
})
plan["actions"].append({
"type": "notify",
"channel": "devops",
"message": f"Resource exhaustion detected in {alert.source}"
})
elif classification == "known_issue":
# Apply known fix
known_fix = await self.knowledge_base.get_known_fix(alert.name)
if known_fix:
plan["actions"].append(known_fix)
elif classification == "false_positive":
plan["actions"].append({
"type": "suppress",
"duration": "1h",
"reason": "False positive detected"
})
# Add escalation rules
if alert.severity == AlertSeverity.CRITICAL:
plan["escalation_rules"].append({
"condition": "no_response_5m",
"action": "escalate_to_oncall",
"timeout": 300
})
return plan
def _extract_features(self, alert: Alert) -> List[float]:
"""Extract features for ML models"""
# Simple feature extraction - in production, use more sophisticated methods
features = [
float(alert.severity == AlertSeverity.CRITICAL),
float(alert.severity == AlertSeverity.HIGH),
float(alert.severity == AlertSeverity.MEDIUM),
len(alert.description),
len(alert.labels),
alert.timestamp.hour / 24.0,
alert.timestamp.weekday() / 7.0
]
return features
async def _execute_response(
self,
alert: Alert,
response_plan: Dict[str, Any]
) -> None:
"""Execute automated response actions"""
for action in response_plan.get("actions", []):
try:
await self.automation_engine.execute(action)
logger.info(f"Executed action for alert {alert.id}: {action['type']}")
except Exception as e:
logger.error(f"Failed to execute action: {e}")
Monitoring Platform Integrations
# aiops/integrations/monitoring.py
import aiohttp
import asyncio
from typing import List, Dict, Any, Optional
from datetime import datetime
from ..core.architecture import DataSource, Metric, LogEntry, Trace, Alert
class PrometheusDataSource(DataSource):
"""Prometheus metrics integration"""
def __init__(self, url: str):
self.url = url.rstrip("/")
self.session = None
async def _get_session(self) -> aiohttp.ClientSession:
if not self.session:
self.session = aiohttp.ClientSession()
return self.session
async def collect_metrics(
self,
query: str,
start_time: datetime,
end_time: datetime
) -> List[Metric]:
"""Query Prometheus for metrics"""
session = await self._get_session()
params = {
"query": query,
"start": start_time.timestamp(),
"end": end_time.timestamp(),
"step": "15s"
}
url = f"{self.url}/api/v1/query_range"
async with session.get(url, params=params) as response:
data = await response.json()
metrics = []
if data["status"] == "success":
result = data["data"]
if result["resultType"] == "matrix":
for series in result["result"]:
labels = series["metric"]
values = series["values"]
for timestamp, value in values:
metrics.append(Metric(
name=query,
value=float(value),
timestamp=datetime.fromtimestamp(float(timestamp)),
labels=labels,
source="prometheus"
))
return metrics
async def query_logs(
self,
query: str,
start_time: datetime,
end_time: datetime,
limit: int = 100
) -> List[LogEntry]:
"""Prometheus doesn't store logs - use Loki integration"""
return []
async def get_trace(self, trace_id: str) -> Optional[Trace]:
"""Prometheus doesn't store traces - use Jaeger/Tempo integration"""
return None
class LokiDataSource(DataSource):
"""Loki log aggregation integration"""
def __init__(self, url: str):
self.url = url.rstrip("/")
self.session = None
async def _get_session(self) -> aiohttp.ClientSession:
if not self.session:
self.session = aiohttp.ClientSession()
return self.session
async def collect_metrics(
self,
query: str,
start_time: datetime,
end_time: datetime
) -> List[Metric]:
"""Loki doesn't store metrics"""
return []
async def query_logs(
self,
query: str,
start_time: datetime,
end_time: datetime,
limit: int = 100
) -> List[LogEntry]:
"""Query Loki for logs"""
session = await self._get_session()
params = {
"query": query,
"start": start_time.isoformat(),
"end": end_time.isoformat(),
"limit": str(limit)
}
url = f"{self.url}/loki/api/v1/query_range"
async with session.get(url, params=params) as response:
data = await response.json()
logs = []
if data["status"] == "success":
result = data["data"]
for series in result["result"]:
stream = series["stream"]
for timestamp, line in series["values"]:
logs.append(LogEntry(
timestamp=datetime.fromtimestamp(float(timestamp) / 1e9),
level=stream.get("level", "info"),
message=line,
service=stream.get("service", "unknown"),
labels=stream
))
return logs
async def get_trace(self, trace_id: str) -> Optional[Trace]:
"""Loki doesn't store traces"""
return None
class JaegerDataSource(DataSource):
"""Jaeger distributed tracing integration"""
def __init__(self, url: str):
self.url = url.rstrip("/")
self.session = None
async def _get_session(self) -> aiohttp.ClientSession:
if not self.session:
self.session = aiohttp.ClientSession()
return self.session
async def collect_metrics(
self,
query: str,
start_time: datetime,
end_time: datetime
) -> List[Metric]:
"""Jaeger doesn't store metrics"""
return []
async def query_logs(
self,
query: str,
start_time: datetime,
end_time: datetime,
limit: int = 100
) -> List[LogEntry]:
"""Jaeger doesn't store logs"""
return []
async def get_trace(self, trace_id: str) -> Optional[Trace]:
"""Get trace from Jaeger"""
session = await self._get_session()
url = f"{self.url}/api/traces/{trace_id}"
async with session.get(url) as response:
data = await response.json()
if data["data"] and data["data"][0]["spans"]:
spans = data["data"][0]["spans"]
service_map = {}
error_count = 0
for span in spans:
service = span["process"]["serviceName"]
if service not in service_map:
service_map[service] = []
service_map[service].append(span["spanID"])
if span.get("tags"):
for tag in span["tags"]:
if tag.get("key") == "error" and tag.get("value"):
error_count += 1
return Trace(
trace_id=trace_id,
spans=spans,
duration=timedelta(
microseconds=data["data"][0]["duration"]
),
service_map=service_map,
error_count=error_count
)
return None
class DatadogDataSource(DataSource):
"""Datadog APM integration"""
def __init__(self, api_key: str, app_key: str, site: str = "datadoghq.com"):
self.api_key = api_key
self.app_key = app_key
self.site = site
self.base_url = f"https://api.{site}"
self.session = None
async def _get_session(self) -> aiohttp.ClientSession:
if not self.session:
headers = {
"DD-API-KEY": self.api_key,
"DD-APPLICATION-KEY": self.app_key
}
self.session = aiohttp.ClientSession(headers=headers)
return self.session
async def collect_metrics(
self,
query: str,
start_time: datetime,
end_time: datetime
) -> List[Metric]:
"""Query Datadog metrics"""
session = await self._get_session()
params = {
"query": query,
"from": int(start_time.timestamp()),
"to": int(end_time.timestamp())
}
url = f"{self.base_url}/api/v1/query"
async with session.get(url, params=params) as response:
data = await response.json()
metrics = []
if "series" in data:
for series in data["series"]:
for point in series["pointlist"]:
metrics.append(Metric(
name=series["metric"],
value=point[1],
timestamp=datetime.fromtimestamp(point[0]),
labels={k: str(v) for k, v in series["tag_set"].items()},
source="datadog",
unit=series.get("unit", "")
))
return metrics
async def query_logs(
self,
query: str,
start_time: datetime,
end_time: datetime,
limit: int = 100
) -> List[LogEntry]:
"""Query Datadog logs"""
session = await self._get_session()
payload = {
"query": query,
"time": {
"from": start_time.isoformat(),
"to": end_time.isoformat()
},
"limit": limit
}
url = f"{self.base_url}/api/v2/logs/events/search"
async with session.post(url, json=payload) as response:
data = await response.json()
logs = []
for log in data.get("data", []):
attributes = log.get("attributes", {})
logs.append(LogEntry(
timestamp=datetime.fromisoformat(attributes["timestamp"]),
level=attributes.get("status", "info"),
message=attributes.get("message", ""),
service=attributes.get("service", "unknown"),
trace_id=attributes.get("trace_id"),
labels=attributes.get("tags", [])
))
return logs
async def get_trace(self, trace_id: str) -> Optional[Trace]:
"""Get trace from Datadog"""
session = await self._get_session()
url = f"{self.base_url}/api/v1/trace/{trace_id}"
async with session.get(url) as response:
data = await response.json()
# Parse Datadog trace format
# Implementation depends on Datadog API response structure
return None
2. Machine Learning for Operations
Anomaly Detection Models
# aiops/ml/anomaly_detection.py
import numpy as np
import pandas as pd
from typing import List, Dict, Tuple, Optional
from datetime import datetime, timedelta
from sklearn.ensemble import IsolationForest
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import joblib
import asyncio
from collections import deque
class AnomalyDetector:
"""Generic anomaly detection for metrics and logs"""
def __init__(self, model_type: str = "isolation_forest"):
self.model_type = model_type
self.models: Dict[str, Any] = {}
self.scalers: Dict[str, StandardScaler] = {}
self.is_trained: Dict[str, bool] = {}
self.feature_history: Dict[str, deque] = {}
async def detect_metric_anomaly(
self,
metric_name: str,
current_value: float,
historical_values: List[float],
window_size: int = 100
) -> Tuple[bool, float]:
"""Detect anomalies in time series metrics"""
if metric_name not in self.models:
await self._train_metric_model(metric_name, historical_values)
# Prepare features
features = self._extract_time_series_features(
current_value,
historical_values,
window_size
)
# Scale features
if metric_name in self.scalers:
features = self.scalers[metric_name].transform([features])
# Predict anomaly
model = self.models[metric_name]
anomaly_score = model.decision_function([features])[0]
is_anomaly = model.predict([features])[0] == -1
return is_anomaly, float(anomaly_score)
async def detect_log_anomaly(
self,
log_entries: List[Dict[str, Any]]
) -> List[Dict[str, Any]]:
"""Detect anomalies in log patterns"""
# Extract log features
features = []
for entry in log_entries:
features.append([
len(entry.get("message", "")),
entry.get("level_numeric", 0),
entry.get("hour_of_day", 0),
entry.get("day_of_week", 0)
])
features = np.array(features)
# Train or use existing model
model_name = "log_patterns"
if model_name not in self.models:
self.models[model_name] = IsolationForest(
contamination=0.1,
random_state=42
)
self.models[model_name].fit(features)
# Predict anomalies
predictions = self.models[model_name].predict(features)
scores = self.models[model_name].decision_function(features)
# Return anomalous logs
anomalies = []
for i, (pred, score) in enumerate(zip(predictions, scores)):
if pred == -1: # Anomaly
anomalies.append({
"log_index": i,
"log_entry": log_entries[i],
"anomaly_score": float(score),
"reason": "Unusual log pattern detected"
})
return anomalies
async def detect_performance_anomaly(
self,
metrics: Dict[str, List[float]],
threshold: float = 0.1
) -> Dict[str, Dict[str, Any]]:
"""Detect performance anomalies across multiple metrics"""
results = {}
for metric_name, values in metrics.items():
if len(values) < 10:
continue
# Calculate statistical anomalies
mean_val = np.mean(values)
std_val = np.std(values)
recent_values = values[-5:]
for i, value in enumerate(recent_values):
z_score = abs(value - mean_val) / (std_val + 1e-8)
if z_score > 3: # Statistical outlier
if metric_name not in results:
results[metric_name] = {
"anomalies": [],
"severity": "medium"
}
results[metric_name]["anomalies"].append({
"value": value,
"z_score": z_score,
"index": i,
"type": "statistical"
})
return results
async def _train_metric_model(
self,
metric_name: str,
values: List[float]
) -> None:
"""Train anomaly detection model for a metric"""
if len(values) < 30:
# Not enough data for training
return
# Prepare training data
training_features = []
for i in range(10, len(values)):
# Create window of previous values
window = values[i-10:i]
features = [
np.mean(window),
np.std(window),
values[i], # Current value
(values[i] - np.mean(window)) / (np.std(window) + 1e-8), # Z-score
max(window) - min(window), # Range
]
training_features.append(features)
training_features = np.array(training_features)
# Scale features
scaler = StandardScaler()
scaled_features = scaler.fit_transform(training_features)
self.scalers[metric_name] = scaler
# Train model
if self.model_type == "isolation_forest":
model = IsolationForest(
contamination=0.05,
random_state=42
)
model.fit(scaled_features)
else:
# Add other model types as needed
model = IsolationForest(contamination=0.05, random_state=42)
model.fit(scaled_features)
self.models[metric_name] = model
self.is_trained[metric_name] = True
def _extract_time_series_features(
self,
current_value: float,
historical_values: List[float],
window_size: int
) -> List[float]:
"""Extract features from time series data"""
if len(historical_values) < window_size:
window = historical_values
else:
window = historical_values[-window_size:]
features = [
np.mean(window),
np.std(window),
min(window),
max(window),
current_value,
(current_value - np.mean(window)) / (np.std(window) + 1e-8),
len([v for v in window if v > np.mean(window)]) / len(window), # Percentage above mean
]
return features
class PredictiveAnalyzer:
"""Predictive analytics for capacity planning and incident prediction"""
def __init__(self):
self.models: Dict[str, Any] = {}
async def predict_capacity_needs(
self,
metric_history: Dict[str, List[float]],
forecast_horizon: int = 7
) -> Dict[str, Dict[str, Any]]:
"""Predict future resource needs"""
predictions = {}
for metric_name, values in metric_history.items():
if len(values) < 30:
continue
# Simple linear trend prediction (use more sophisticated models in production)
x = np.arange(len(values))
coeffs = np.polyfit(x, values, 1)
# Predict future values
future_x = np.arange(len(values), len(values) + forecast_horizon * 24)
future_values = np.polyval(coeffs, future_x)
# Calculate growth rate
growth_rate = (future_values[-1] - values[-1]) / values[-1] * 100
predictions[metric_name] = {
"current": values[-1],
"predicted_peak": float(max(future_values)),
"predicted_average": float(np.mean(future_values)),
"growth_rate": growth_rate,
"recommendation": self._get_capacity_recommendation(growth_rate),
"confidence": 0.75 # Should be calculated based on model accuracy
}
return predictions
async def predict_incidents(
self,
alert_history: List[Dict[str, Any]],
system_metrics: Dict[str, List[float]]
) -> Dict[str, Any]:
"""Predict likelihood of future incidents"""
# Feature engineering
features = self._extract_incident_features(alert_history, system_metrics)
# Simplified risk score calculation
risk_factors = {
"error_rate_trend": self._calculate_trend(
system_metrics.get("error_rate", [])
),
"cpu_utilization_avg": np.mean(
system_metrics.get("cpu_utilization", [0])
),
"memory_utilization_avg": np.mean(
system_metrics.get("memory_utilization", [0])
),
"recent_incident_count": len([
a for a in alert_history[-24:]
if a.get("severity") == "critical"
]),
}
# Calculate risk score (0-100)
risk_score = min(100, max(0, (
risk_factors["error_rate_trend"] * 30 +
risk_factors["cpu_utilization_avg"] * 25 +
risk_factors["memory_utilization_avg"] * 25 +
risk_factors["recent_incident_count"] * 20
)))
return {
"risk_score": risk_score,
"risk_level": self._get_risk_level(risk_score),
"contributing_factors": risk_factors,
"recommendations": self._get_mitigation_recommendations(risk_factors)
}
def _extract_incident_features(
self,
alert_history: List[Dict[str, Any]],
system_metrics: Dict[str, List[float]]
) -> List[float]:
"""Extract features for incident prediction"""
features = []
# Alert patterns
recent_alerts = alert_history[-24:] if len(alert_history) >= 24 else alert_history
features.append(len(recent_alerts))
features.append(len([a for a in recent_alerts if a.get("severity") == "critical"]))
# System metrics
for metric_name in ["cpu", "memory", "disk", "network"]:
values = system_metrics.get(f"{metric_name}_utilization", [0])
features.append(np.mean(values[-12:]) if values else 0)
features.append(np.std(values[-12:]) if values else 0)
return features
def _calculate_trend(self, values: List[float]) -> float:
"""Calculate trend coefficient (positive = increasing)"""
if len(values) < 2:
return 0.0
x = np.arange(len(values))
coeffs = np.polyfit(x, values, 1)
return coeffs[0]
def _get_capacity_recommendation(self, growth_rate: float) -> str:
"""Get capacity recommendation based on growth rate"""
if growth_rate > 50:
return "Immediate scaling required - consider 2x current capacity"
elif growth_rate > 20:
return "Plan for scaling within next week - recommend 1.5x capacity"
elif growth_rate > 0:
return "Monitor growth - consider 25% buffer"
else:
return "Capacity adequate - no immediate action needed"
def _get_risk_level(self, risk_score: float) -> str:
"""Get risk level from risk score"""
if risk_score >= 80:
return "critical"
elif risk_score >= 60:
return "high"
elif risk_score >= 40:
return "medium"
else:
return "low"
def _get_mitigation_recommendations(
self,
risk_factors: Dict[str, float]
) -> List[str]:
"""Get mitigation recommendations based on risk factors"""
recommendations = []
if risk_factors["cpu_utilization_avg"] > 80:
recommendations.append("Scale CPU resources or optimize CPU usage")
if risk_factors["memory_utilization_avg"] > 80:
recommendations.append("Increase memory allocation or check for memory leaks")
if risk_factors["error_rate_trend"] > 0:
recommendations.append("Investigate and fix increasing error rate")
if risk_factors["recent_incident_count"] > 3:
recommendations.append("Review recent incidents for root cause analysis")
return recommendations
class AILogAnalyzer:
"""AI-powered log analysis and pattern detection"""
def __init__(self):
self.patterns: Dict[str, List[str]] = {}
self.embeddings: Dict[str, np.ndarray] = {}
async def analyze_logs(
self,
logs: List[LogEntry]
) -> Dict[str, Any]:
"""Analyze logs for patterns and anomalies"""
analysis = {
"total_logs": len(logs),
"error_rate": 0.0,
"patterns": [],
"anomalies": [],
"trending_topics": [],
"recommendations": []
}
# Calculate error rate
error_count = len([l for l in logs if l.level.lower() in ["error", "critical"]])
analysis["error_rate"] = error_count / len(logs) * 100
# Extract patterns using regex and ML
analysis["patterns"] = await self._extract_patterns(logs)
# Find anomalies
analysis["anomalies"] = await self._detect_log_anomalies(logs)
# Identify trending topics/errors
analysis["trending_topics"] = await self._identify_trending_topics(logs)
# Generate recommendations
analysis["recommendations"] = self._generate_log_recommendations(analysis)
return analysis
async def _extract_patterns(self, logs: List[LogEntry]) -> List[Dict[str, Any]]:
"""Extract common patterns from logs"""
# Simplified pattern extraction
# In production, use more sophisticated NLP techniques
patterns = []
# Group logs by service
service_logs = {}
for log in logs:
if log.service not in service_logs:
service_logs[log.service] = []
service_logs[log.service].append(log)
# Find error patterns
for service, service_log_list in service_logs.items():
error_logs = [l for l in service_log_list if l.level.lower() == "error"]
if len(error_logs) > 0:
# Find common substrings in error messages
common_errors = {}
for log in error_logs:
# Simplified - use actual pattern matching in production
for word in log.message.split():
if len(word) > 5: # Only consider longer words
common_errors[word] = common_errors.get(word, 0) + 1
if common_errors:
most_common = max(common_errors, key=common_errors.get)
patterns.append({
"service": service,
"type": "error_pattern",
"pattern": most_common,
"count": common_errors[most_common],
"percentage": common_errors[most_common] / len(error_logs) * 100
})
return patterns
async def _detect_log_anomalies(self, logs: List[LogEntry]) -> List[Dict[str, Any]]:
"""Detect anomalies in logs"""
anomalies = []
# Check for unusual error spikes
error_by_minute = {}
for log in logs:
if log.level.lower() in ["error", "critical"]:
minute = log.timestamp.replace(second=0, microsecond=0)
error_by_minute[minute] = error_by_minute.get(minute, 0) + 1
if error_by_minute:
avg_errors = np.mean(list(error_by_minute.values()))
for minute, count in error_by_minute.items():
if count > avg_errors * 3: # 3x spike
anomalies.append({
"type": "error_spike",
"timestamp": minute.isoformat(),
"value": count,
"baseline": avg_errors,
"severity": "high"
})
return anomalies
async def _identify_trending_topics(self, logs: List[LogEntry]) -> List[Dict[str, Any]]:
"""Identify trending topics in logs"""
# Simplified trending detection
word_count = {}
for log in logs[-100:]: # Last 100 logs
for word in log.message.lower().split():
if len(word) > 5 and word.isalpha():
word_count[word] = word_count.get(word, 0) + 1
# Get top trending words
trending = sorted(word_count.items(), key=lambda x: x[1], reverse=True)[:10]
return [
{"topic": word, "count": count}
for word, count in trending
]
def _generate_log_recommendations(self, analysis: Dict[str, Any]) -> List[str]:
"""Generate recommendations based on log analysis"""
recommendations = []
if analysis["error_rate"] > 5:
recommendations.append(
f"High error rate ({analysis['error_rate']:.1f}%) detected - investigate immediately"
)
if len(analysis["anomalies"]) > 0:
recommendations.append(
f"Found {len(analysis['anomalies'])} anomalies - review and address"
)
for pattern in analysis["patterns"][:3]:
if pattern["percentage"] > 30:
recommendations.append(
f"Common error pattern in {pattern['service']}: {pattern['pattern']}"
)
return recommendations
3. Automation and Self-Healing
Automation Engine
# aiops/automation/engine.py
import asyncio
import subprocess
from typing import Dict, List, Any, Optional, Callable
from dataclasses import dataclass
from enum import Enum
import logging
from datetime import datetime, timedelta
logger = logging.getLogger(__name__)
class ActionType(str, Enum):
"""Types of automation actions"""
SCALE = "scale"
RESTART = "restart"
PATCH = "patch"
NOTIFY = "notify"
SUPPRESS = "suppress"
ISOLATE = "isolate"
FAILBACK = "failback"
@dataclass
class Action:
"""Automation action definition"""
type: ActionType
target: str
params: Dict[str, Any]
conditions: List[str] = None
timeout: int = 300
retries: int = 3
class AutomationEngine:
"""Automation engine for executing remediation actions"""
def __init__(self):
self.actions: Dict[str, Action] = {}
self.execution_history: List[Dict[str, Any]] = []
self.action_handlers: Dict[ActionType, Callable] = {
ActionType.SCALE: self._handle_scale,
ActionType.RESTART: self._handle_restart,
ActionType.PATCH: self._handle_patch,
ActionType.NOTIFY: self._handle_notify,
ActionType.SUPPRESS: self._handle_suppress,
ActionType.ISOLATE: self._handle_isolate,
ActionType.FAILBACK: self._handle_failback
}
def register_action(self, action: Action) -> None:
"""Register an automation action"""
self.actions[action.target] = action
logger.info(f"Registered action: {action.type} for {action.target}")
async def execute(self, action: Action) -> Dict[str, A
…(truncated)
1---2name: aiops3description: Generic AIOps (AI for IT Operations) patterns and best practices for 2025. Provides comprehensive implementation strategies for intelligent monitoring, automation, incident response, and observability across any infrastructure. Framework-agnostic approach supporting multiple monitoring platforms, cloud providers, and automation tools.4license: MIT5---67# AIOps - AI for IT Operations89This skill provides comprehensive patterns for implementing AIOps strategies in 2025, including intelligent monitoring, automated incident response, predictive analytics, and observability best practices. The patterns are designed to be framework-agnostic and applicable across different infrastructure platforms.1011## When to Use This Skill1213Use this skill when you need to:14- Implement AIOps strategies for modern infrastructure15- Build intelligent monitoring and alerting systems16- Create automated incident response workflows17- Deploy predictive maintenance solutions18- Implement self-healing capabilities19- Build observability platforms with AI/ML20- Optimize multi-cloud operations21- Create chaos engineering practices22- Implement generative AI for operations23- Build digital twins for infrastructure2425## 1. AIOps Architecture Patterns2627### Core AIOps Platform Architecture2829```python30# aiops/core/architecture.py31from abc import ABC, abstractmethod32from typing import Dict, List, Optional, Any, Union33from dataclasses import dataclass, field34from datetime import datetime, timedelta35from enum import Enum36import asyncio37import json38import logging3940logger = logging.getLogger(__name__)4142class AlertSeverity(str, Enum):43 """Alert severity levels"""44 CRITICAL = "critical"45 HIGH = "high"46 MEDIUM = "medium"47 LOW = "low"48 INFO = "info"4950class IncidentStatus(str, Enum):51 """Incident status"""52 OPEN = "open"53 INVESTIGATING = "investigating"54 IDENTIFIED = "identified"55 MONITORING = "monitoring"56 RESOLVED = "resolved"57 CLOSED = "closed"5859@dataclass60class Metric:61 """Metric data point"""62 name: str63 value: float64 timestamp: datetime65 labels: Dict[str, str] = field(default_factory=dict)66 source: str = ""67 unit: str = ""6869@dataclass70class LogEntry:71 """Structured log entry"""72 timestamp: datetime73 level: str74 message: str75 service: str76 trace_id: Optional[str] = None77 span_id: Optional[str] = None78 labels: Dict[str, str] = field(default_factory=dict)79 stack_trace: Optional[str] = None8081@dataclass82class Trace:83 """Distributed trace data"""84 trace_id: str85 spans: List[Dict[str, Any]]86 duration: timedelta87 service_map: Dict[str, List[str]]88 error_count: int = 08990@dataclass91class Alert:92 """Alert representation"""93 id: str94 name: str95 severity: AlertSeverity96 status: IncidentStatus97 description: str98 source: str99 timestamp: datetime100 labels: Dict[str, str] = field(default_factory=dict)101 annotations: Dict[str, str] = field(default_factory=dict)102 fingerprint: str = ""103 related_entities: List[str] = field(default_factory=list)104105class DataSource(ABC):106 """Abstract data source interface"""107108 @abstractmethod109 async def collect_metrics(110 self,111 query: str,112 start_time: datetime,113 end_time: datetime114 ) -> List[Metric]:115 """Collect metrics from data source"""116 pass117118 @abstractmethod119 async def query_logs(120 self,121 query: str,122 start_time: datetime,123 end_time: datetime,124 limit: int = 100125 ) -> List[LogEntry]:126 """Query logs from data source"""127 pass128129 @abstractmethod130 async def get_trace(self, trace_id: str) -> Optional[Trace]:131 """Get trace data"""132 pass133134class AIOpsEngine:135 """Core AIOps processing engine"""136137 def __init__(self):138 self.data_sources: List[DataSource] = []139 self.alert_processors: List[AlertProcessor] = []140 self.ml_models: Dict[str, Any] = {}141 self.knowledge_base: KnowledgeBase = KnowledgeBase()142 self.automation_engine = AutomationEngine()143144 def register_data_source(self, data_source: DataSource) -> None:145 """Register a data source"""146 self.data_sources.append(data_source)147 logger.info(f"Registered data source: {type(data_source).__name__}")148149 def register_alert_processor(self, processor: 'AlertProcessor') -> None:150 """Register an alert processor"""151 self.alert_processors.append(processor)152 logger.info(f"Registered alert processor: {type(processor).__name__}")153154 async def process_alert(self, alert: Alert) -> Dict[str, Any]:155 """Process incoming alert through AIOps pipeline"""156 logger.info(f"Processing alert: {alert.id} - {alert.name}")157158 # 1. Enrich alert with context159 enriched_alert = await self._enrich_alert(alert)160161 # 2. Run through ML models for classification and prediction162 analysis = await self._analyze_alert(enriched_alert)163164 # 3. Determine appropriate response165 response_plan = await self._generate_response_plan(enriched_alert, analysis)166167 # 4. Execute automated actions if applicable168 if response_plan.get("auto_execute", False):169 await self._execute_response(enriched_alert, response_plan)170171 # 5. Update knowledge base172 await self.knowledge_base.update_from_alert(enriched_alert, analysis, response_plan)173174 return {175 "alert_id": alert.id,176 "status": "processed",177 "analysis": analysis,178 "response_plan": response_plan179 }180181 async def _enrich_alert(self, alert: Alert) -> Alert:182 """Enrich alert with additional context"""183 # Get related metrics184 for source in self.data_sources:185 try:186 metrics = await source.collect_metrics(187 query=f"{alert.name}[5m]",188 start_time=alert.timestamp - timedelta(minutes=5),189 end_time=alert.timestamp190 )191192 # Add metrics to alert annotations193 alert.annotations[f"metrics_{type(source).__name__}"] = json.dumps([194 {"name": m.name, "value": m.value} for m in metrics195 ])196 except Exception as e:197 logger.error(f"Failed to enrich alert with metrics: {e}")198199 # Get related logs200 for source in self.data_sources:201 try:202 logs = await source.query_logs(203 query=f"service:{alert.source} level:error",204 start_time=alert.timestamp - timedelta(minutes=5),205 end_time=alert.timestamp,206 limit=10207 )208209 # Add logs to alert context210 alert.annotations["recent_errors"] = json.dumps([211 {"timestamp": l.timestamp.isoformat(), "message": l.message}212 for l in logs213 ])214 except Exception as e:215 logger.error(f"Failed to enrich alert with logs: {e}")216217 return alert218219 async def _analyze_alert(self, alert: Alert) -> Dict[str, Any]:220 """Analyze alert using ML models"""221 analysis = {222 "classification": None,223 "severity_score": 0.0,224 "predicted_impact": "low",225 "recommendations": [],226 "related_incidents": []227 }228229 # Classification model230 if "classification" in self.ml_models:231 features = self._extract_features(alert)232 analysis["classification"] = self.ml_models["classification"].predict([features])[0]233234 # Severity prediction235 if "severity" in self.ml_models:236 features = self._extract_features(alert)237 analysis["severity_score"] = self.ml_models["severity"].predict_proba([features])[0][1]238239 # Impact prediction240 if "impact" in self.ml_models:241 features = self._extract_features(alert)242 analysis["predicted_impact"] = self.ml_models["impact"].predict([features])[0]243244 # Find related incidents from knowledge base245 analysis["related_incidents"] = await self.knowledge_base.find_similar_incidents(alert)246247 return analysis248249 async def _generate_response_plan(250 self,251 alert: Alert,252 analysis: Dict[str, Any]253 ) -> Dict[str, Any]:254 """Generate automated response plan"""255 plan = {256 "priority": alert.severity,257 "actions": [],258 "escalation_rules": [],259 "auto_execute": False,260 "estimated_resolution_time": None261 }262263 # Determine if auto-execution is safe264 if (analysis["classification"] in ["known_issue", "false_positive"] and265 alert.severity in [AlertSeverity.LOW, AlertSeverity.MEDIUM]):266 plan["auto_execute"] = True267268 # Generate actions based on classification269 classification = analysis.get("classification")270271 if classification == "resource_exhaustion":272 plan["actions"].append({273 "type": "scale",274 "target": alert.source,275 "params": {"replicas": "+20%"}276 })277 plan["actions"].append({278 "type": "notify",279 "channel": "devops",280 "message": f"Resource exhaustion detected in {alert.source}"281 })282283 elif classification == "known_issue":284 # Apply known fix285 known_fix = await self.knowledge_base.get_known_fix(alert.name)286 if known_fix:287 plan["actions"].append(known_fix)288289 elif classification == "false_positive":290 plan["actions"].append({291 "type": "suppress",292 "duration": "1h",293 "reason": "False positive detected"294 })295296 # Add escalation rules297 if alert.severity == AlertSeverity.CRITICAL:298 plan["escalation_rules"].append({299 "condition": "no_response_5m",300 "action": "escalate_to_oncall",301 "timeout": 300302 })303304 return plan305306 def _extract_features(self, alert: Alert) -> List[float]:307 """Extract features for ML models"""308 # Simple feature extraction - in production, use more sophisticated methods309 features = [310 float(alert.severity == AlertSeverity.CRITICAL),311 float(alert.severity == AlertSeverity.HIGH),312 float(alert.severity == AlertSeverity.MEDIUM),313 len(alert.description),314 len(alert.labels),315 alert.timestamp.hour / 24.0,316 alert.timestamp.weekday() / 7.0317 ]318 return features319320 async def _execute_response(321 self,322 alert: Alert,323 response_plan: Dict[str, Any]324 ) -> None:325 """Execute automated response actions"""326 for action in response_plan.get("actions", []):327 try:328 await self.automation_engine.execute(action)329 logger.info(f"Executed action for alert {alert.id}: {action['type']}")330 except Exception as e:331 logger.error(f"Failed to execute action: {e}")332```333334### Monitoring Platform Integrations335336```python337# aiops/integrations/monitoring.py338import aiohttp339import asyncio340from typing import List, Dict, Any, Optional341from datetime import datetime342from ..core.architecture import DataSource, Metric, LogEntry, Trace, Alert343344class PrometheusDataSource(DataSource):345 """Prometheus metrics integration"""346347 def __init__(self, url: str):348 self.url = url.rstrip("/")349 self.session = None350351 async def _get_session(self) -> aiohttp.ClientSession:352 if not self.session:353 self.session = aiohttp.ClientSession()354 return self.session355356 async def collect_metrics(357 self,358 query: str,359 start_time: datetime,360 end_time: datetime361 ) -> List[Metric]:362 """Query Prometheus for metrics"""363 session = await self._get_session()364365 params = {366 "query": query,367 "start": start_time.timestamp(),368 "end": end_time.timestamp(),369 "step": "15s"370 }371372 url = f"{self.url}/api/v1/query_range"373374 async with session.get(url, params=params) as response:375 data = await response.json()376 metrics = []377378 if data["status"] == "success":379 result = data["data"]380 if result["resultType"] == "matrix":381 for series in result["result"]:382 labels = series["metric"]383 values = series["values"]384385 for timestamp, value in values:386 metrics.append(Metric(387 name=query,388 value=float(value),389 timestamp=datetime.fromtimestamp(float(timestamp)),390 labels=labels,391 source="prometheus"392 ))393394 return metrics395396 async def query_logs(397 self,398 query: str,399 start_time: datetime,400 end_time: datetime,401 limit: int = 100402 ) -> List[LogEntry]:403 """Prometheus doesn't store logs - use Loki integration"""404 return []405406 async def get_trace(self, trace_id: str) -> Optional[Trace]:407 """Prometheus doesn't store traces - use Jaeger/Tempo integration"""408 return None409410class LokiDataSource(DataSource):411 """Loki log aggregation integration"""412413 def __init__(self, url: str):414 self.url = url.rstrip("/")415 self.session = None416417 async def _get_session(self) -> aiohttp.ClientSession:418 if not self.session:419 self.session = aiohttp.ClientSession()420 return self.session421422 async def collect_metrics(423 self,424 query: str,425 start_time: datetime,426 end_time: datetime427 ) -> List[Metric]:428 """Loki doesn't store metrics"""429 return []430431 async def query_logs(432 self,433 query: str,434 start_time: datetime,435 end_time: datetime,436 limit: int = 100437 ) -> List[LogEntry]:438 """Query Loki for logs"""439 session = await self._get_session()440441 params = {442 "query": query,443 "start": start_time.isoformat(),444 "end": end_time.isoformat(),445 "limit": str(limit)446 }447448 url = f"{self.url}/loki/api/v1/query_range"449450 async with session.get(url, params=params) as response:451 data = await response.json()452 logs = []453454 if data["status"] == "success":455 result = data["data"]456 for series in result["result"]:457 stream = series["stream"]458 for timestamp, line in series["values"]:459 logs.append(LogEntry(460 timestamp=datetime.fromtimestamp(float(timestamp) / 1e9),461 level=stream.get("level", "info"),462 message=line,463 service=stream.get("service", "unknown"),464 labels=stream465 ))466467 return logs468469 async def get_trace(self, trace_id: str) -> Optional[Trace]:470 """Loki doesn't store traces"""471 return None472473class JaegerDataSource(DataSource):474 """Jaeger distributed tracing integration"""475476 def __init__(self, url: str):477 self.url = url.rstrip("/")478 self.session = None479480 async def _get_session(self) -> aiohttp.ClientSession:481 if not self.session:482 self.session = aiohttp.ClientSession()483 return self.session484485 async def collect_metrics(486 self,487 query: str,488 start_time: datetime,489 end_time: datetime490 ) -> List[Metric]:491 """Jaeger doesn't store metrics"""492 return []493494 async def query_logs(495 self,496 query: str,497 start_time: datetime,498 end_time: datetime,499 limit: int = 100500 ) -> List[LogEntry]:501 """Jaeger doesn't store logs"""502 return []503504 async def get_trace(self, trace_id: str) -> Optional[Trace]:505 """Get trace from Jaeger"""506 session = await self._get_session()507508 url = f"{self.url}/api/traces/{trace_id}"509510 async with session.get(url) as response:511 data = await response.json()512513 if data["data"] and data["data"][0]["spans"]:514 spans = data["data"][0]["spans"]515 service_map = {}516 error_count = 0517518 for span in spans:519 service = span["process"]["serviceName"]520 if service not in service_map:521 service_map[service] = []522 service_map[service].append(span["spanID"])523524 if span.get("tags"):525 for tag in span["tags"]:526 if tag.get("key") == "error" and tag.get("value"):527 error_count += 1528529 return Trace(530 trace_id=trace_id,531 spans=spans,532 duration=timedelta(533 microseconds=data["data"][0]["duration"]534 ),535 service_map=service_map,536 error_count=error_count537 )538539 return None540541class DatadogDataSource(DataSource):542 """Datadog APM integration"""543544 def __init__(self, api_key: str, app_key: str, site: str = "datadoghq.com"):545 self.api_key = api_key546 self.app_key = app_key547 self.site = site548 self.base_url = f"https://api.{site}"549 self.session = None550551 async def _get_session(self) -> aiohttp.ClientSession:552 if not self.session:553 headers = {554 "DD-API-KEY": self.api_key,555 "DD-APPLICATION-KEY": self.app_key556 }557 self.session = aiohttp.ClientSession(headers=headers)558 return self.session559560 async def collect_metrics(561 self,562 query: str,563 start_time: datetime,564 end_time: datetime565 ) -> List[Metric]:566 """Query Datadog metrics"""567 session = await self._get_session()568569 params = {570 "query": query,571 "from": int(start_time.timestamp()),572 "to": int(end_time.timestamp())573 }574575 url = f"{self.base_url}/api/v1/query"576577 async with session.get(url, params=params) as response:578 data = await response.json()579 metrics = []580581 if "series" in data:582 for series in data["series"]:583 for point in series["pointlist"]:584 metrics.append(Metric(585 name=series["metric"],586 value=point[1],587 timestamp=datetime.fromtimestamp(point[0]),588 labels={k: str(v) for k, v in series["tag_set"].items()},589 source="datadog",590 unit=series.get("unit", "")591 ))592593 return metrics594595 async def query_logs(596 self,597 query: str,598 start_time: datetime,599 end_time: datetime,600 limit: int = 100601 ) -> List[LogEntry]:602 """Query Datadog logs"""603 session = await self._get_session()604605 payload = {606 "query": query,607 "time": {608 "from": start_time.isoformat(),609 "to": end_time.isoformat()610 },611 "limit": limit612 }613614 url = f"{self.base_url}/api/v2/logs/events/search"615616 async with session.post(url, json=payload) as response:617 data = await response.json()618 logs = []619620 for log in data.get("data", []):621 attributes = log.get("attributes", {})622623 logs.append(LogEntry(624 timestamp=datetime.fromisoformat(attributes["timestamp"]),625 level=attributes.get("status", "info"),626 message=attributes.get("message", ""),627 service=attributes.get("service", "unknown"),628 trace_id=attributes.get("trace_id"),629 labels=attributes.get("tags", [])630 ))631632 return logs633634 async def get_trace(self, trace_id: str) -> Optional[Trace]:635 """Get trace from Datadog"""636 session = await self._get_session()637638 url = f"{self.base_url}/api/v1/trace/{trace_id}"639640 async with session.get(url) as response:641 data = await response.json()642643 # Parse Datadog trace format644 # Implementation depends on Datadog API response structure645 return None646```647648## 2. Machine Learning for Operations649650### Anomaly Detection Models651652```python653# aiops/ml/anomaly_detection.py654import numpy as np655import pandas as pd656from typing import List, Dict, Tuple, Optional657from datetime import datetime, timedelta658from sklearn.ensemble import IsolationForest659from sklearn.preprocessing import StandardScaler660from sklearn.decomposition import PCA661import joblib662import asyncio663from collections import deque664665class AnomalyDetector:666 """Generic anomaly detection for metrics and logs"""667668 def __init__(self, model_type: str = "isolation_forest"):669 self.model_type = model_type670 self.models: Dict[str, Any] = {}671 self.scalers: Dict[str, StandardScaler] = {}672 self.is_trained: Dict[str, bool] = {}673 self.feature_history: Dict[str, deque] = {}674675 async def detect_metric_anomaly(676 self,677 metric_name: str,678 current_value: float,679 historical_values: List[float],680 window_size: int = 100681 ) -> Tuple[bool, float]:682 """Detect anomalies in time series metrics"""683 if metric_name not in self.models:684 await self._train_metric_model(metric_name, historical_values)685686 # Prepare features687 features = self._extract_time_series_features(688 current_value,689 historical_values,690 window_size691 )692693 # Scale features694 if metric_name in self.scalers:695 features = self.scalers[metric_name].transform([features])696697 # Predict anomaly698 model = self.models[metric_name]699 anomaly_score = model.decision_function([features])[0]700 is_anomaly = model.predict([features])[0] == -1701702 return is_anomaly, float(anomaly_score)703704 async def detect_log_anomaly(705 self,706 log_entries: List[Dict[str, Any]]707 ) -> List[Dict[str, Any]]:708 """Detect anomalies in log patterns"""709 # Extract log features710 features = []711 for entry in log_entries:712 features.append([713 len(entry.get("message", "")),714 entry.get("level_numeric", 0),715 entry.get("hour_of_day", 0),716 entry.get("day_of_week", 0)717 ])718719 features = np.array(features)720721 # Train or use existing model722 model_name = "log_patterns"723 if model_name not in self.models:724 self.models[model_name] = IsolationForest(725 contamination=0.1,726 random_state=42727 )728 self.models[model_name].fit(features)729730 # Predict anomalies731 predictions = self.models[model_name].predict(features)732 scores = self.models[model_name].decision_function(features)733734 # Return anomalous logs735 anomalies = []736 for i, (pred, score) in enumerate(zip(predictions, scores)):737 if pred == -1: # Anomaly738 anomalies.append({739 "log_index": i,740 "log_entry": log_entries[i],741 "anomaly_score": float(score),742 "reason": "Unusual log pattern detected"743 })744745 return anomalies746747 async def detect_performance_anomaly(748 self,749 metrics: Dict[str, List[float]],750 threshold: float = 0.1751 ) -> Dict[str, Dict[str, Any]]:752 """Detect performance anomalies across multiple metrics"""753 results = {}754755 for metric_name, values in metrics.items():756 if len(values) < 10:757 continue758759 # Calculate statistical anomalies760 mean_val = np.mean(values)761 std_val = np.std(values)762 recent_values = values[-5:]763764 for i, value in enumerate(recent_values):765 z_score = abs(value - mean_val) / (std_val + 1e-8)766767 if z_score > 3: # Statistical outlier768 if metric_name not in results:769 results[metric_name] = {770 "anomalies": [],771 "severity": "medium"772 }773774 results[metric_name]["anomalies"].append({775 "value": value,776 "z_score": z_score,777 "index": i,778 "type": "statistical"779 })780781 return results782783 async def _train_metric_model(784 self,785 metric_name: str,786 values: List[float]787 ) -> None:788 """Train anomaly detection model for a metric"""789 if len(values) < 30:790 # Not enough data for training791 return792793 # Prepare training data794 training_features = []795 for i in range(10, len(values)):796 # Create window of previous values797 window = values[i-10:i]798 features = [799 np.mean(window),800 np.std(window),801 values[i], # Current value802 (values[i] - np.mean(window)) / (np.std(window) + 1e-8), # Z-score803 max(window) - min(window), # Range804 ]805 training_features.append(features)806807 training_features = np.array(training_features)808809 # Scale features810 scaler = StandardScaler()811 scaled_features = scaler.fit_transform(training_features)812 self.scalers[metric_name] = scaler813814 # Train model815 if self.model_type == "isolation_forest":816 model = IsolationForest(817 contamination=0.05,818 random_state=42819 )820 model.fit(scaled_features)821 else:822 # Add other model types as needed823 model = IsolationForest(contamination=0.05, random_state=42)824 model.fit(scaled_features)825826 self.models[metric_name] = model827 self.is_trained[metric_name] = True828829 def _extract_time_series_features(830 self,831 current_value: float,832 historical_values: List[float],833 window_size: int834 ) -> List[float]:835 """Extract features from time series data"""836 if len(historical_values) < window_size:837 window = historical_values838 else:839 window = historical_values[-window_size:]840841 features = [842 np.mean(window),843 np.std(window),844 min(window),845 max(window),846 current_value,847 (current_value - np.mean(window)) / (np.std(window) + 1e-8),848 len([v for v in window if v > np.mean(window)]) / len(window), # Percentage above mean849 ]850851 return features852853class PredictiveAnalyzer:854 """Predictive analytics for capacity planning and incident prediction"""855856 def __init__(self):857 self.models: Dict[str, Any] = {}858859 async def predict_capacity_needs(860 self,861 metric_history: Dict[str, List[float]],862 forecast_horizon: int = 7863 ) -> Dict[str, Dict[str, Any]]:864 """Predict future resource needs"""865 predictions = {}866867 for metric_name, values in metric_history.items():868 if len(values) < 30:869 continue870871 # Simple linear trend prediction (use more sophisticated models in production)872 x = np.arange(len(values))873 coeffs = np.polyfit(x, values, 1)874875 # Predict future values876 future_x = np.arange(len(values), len(values) + forecast_horizon * 24)877 future_values = np.polyval(coeffs, future_x)878879 # Calculate growth rate880 growth_rate = (future_values[-1] - values[-1]) / values[-1] * 100881882 predictions[metric_name] = {883 "current": values[-1],884 "predicted_peak": float(max(future_values)),885 "predicted_average": float(np.mean(future_values)),886 "growth_rate": growth_rate,887 "recommendation": self._get_capacity_recommendation(growth_rate),888 "confidence": 0.75 # Should be calculated based on model accuracy889 }890891 return predictions892893 async def predict_incidents(894 self,895 alert_history: List[Dict[str, Any]],896 system_metrics: Dict[str, List[float]]897 ) -> Dict[str, Any]:898 """Predict likelihood of future incidents"""899 # Feature engineering900 features = self._extract_incident_features(alert_history, system_metrics)901902 # Simplified risk score calculation903 risk_factors = {904 "error_rate_trend": self._calculate_trend(905 system_metrics.get("error_rate", [])906 ),907 "cpu_utilization_avg": np.mean(908 system_metrics.get("cpu_utilization", [0])909 ),910 "memory_utilization_avg": np.mean(911 system_metrics.get("memory_utilization", [0])912 ),913 "recent_incident_count": len([914 a for a in alert_history[-24:]915 if a.get("severity") == "critical"916 ]),917 }918919 # Calculate risk score (0-100)920 risk_score = min(100, max(0, (921 risk_factors["error_rate_trend"] * 30 +922 risk_factors["cpu_utilization_avg"] * 25 +923 risk_factors["memory_utilization_avg"] * 25 +924 risk_factors["recent_incident_count"] * 20925 )))926927 return {928 "risk_score": risk_score,929 "risk_level": self._get_risk_level(risk_score),930 "contributing_factors": risk_factors,931 "recommendations": self._get_mitigation_recommendations(risk_factors)932 }933934 def _extract_incident_features(935 self,936 alert_history: List[Dict[str, Any]],937 system_metrics: Dict[str, List[float]]938 ) -> List[float]:939 """Extract features for incident prediction"""940 features = []941942 # Alert patterns943 recent_alerts = alert_history[-24:] if len(alert_history) >= 24 else alert_history944 features.append(len(recent_alerts))945 features.append(len([a for a in recent_alerts if a.get("severity") == "critical"]))946947 # System metrics948 for metric_name in ["cpu", "memory", "disk", "network"]:949 values = system_metrics.get(f"{metric_name}_utilization", [0])950 features.append(np.mean(values[-12:]) if values else 0)951 features.append(np.std(values[-12:]) if values else 0)952953 return features954955 def _calculate_trend(self, values: List[float]) -> float:956 """Calculate trend coefficient (positive = increasing)"""957 if len(values) < 2:958 return 0.0959960 x = np.arange(len(values))961 coeffs = np.polyfit(x, values, 1)962 return coeffs[0]963964 def _get_capacity_recommendation(self, growth_rate: float) -> str:965 """Get capacity recommendation based on growth rate"""966 if growth_rate > 50:967 return "Immediate scaling required - consider 2x current capacity"968 elif growth_rate > 20:969 return "Plan for scaling within next week - recommend 1.5x capacity"970 elif growth_rate > 0:971 return "Monitor growth - consider 25% buffer"972 else:973 return "Capacity adequate - no immediate action needed"974975 def _get_risk_level(self, risk_score: float) -> str:976 """Get risk level from risk score"""977 if risk_score >= 80:978 return "critical"979 elif risk_score >= 60:980 return "high"981 elif risk_score >= 40:982 return "medium"983 else:984 return "low"985986 def _get_mitigation_recommendations(987 self,988 risk_factors: Dict[str, float]989 ) -> List[str]:990 """Get mitigation recommendations based on risk factors"""991 recommendations = []992993 if risk_factors["cpu_utilization_avg"] > 80:994 recommendations.append("Scale CPU resources or optimize CPU usage")995996 if risk_factors["memory_utilization_avg"] > 80:997 recommendations.append("Increase memory allocation or check for memory leaks")998999 if risk_factors["error_rate_trend"] > 0:1000 recommendations.append("Investigate and fix increasing error rate")10011002 if risk_factors["recent_incident_count"] > 3:1003 recommendations.append("Review recent incidents for root cause analysis")10041005 return recommendations10061007class AILogAnalyzer:1008 """AI-powered log analysis and pattern detection"""10091010 def __init__(self):1011 self.patterns: Dict[str, List[str]] = {}1012 self.embeddings: Dict[str, np.ndarray] = {}10131014 async def analyze_logs(1015 self,1016 logs: List[LogEntry]1017 ) -> Dict[str, Any]:1018 """Analyze logs for patterns and anomalies"""1019 analysis = {1020 "total_logs": len(logs),1021 "error_rate": 0.0,1022 "patterns": [],1023 "anomalies": [],1024 "trending_topics": [],1025 "recommendations": []1026 }10271028 # Calculate error rate1029 error_count = len([l for l in logs if l.level.lower() in ["error", "critical"]])1030 analysis["error_rate"] = error_count / len(logs) * 10010311032 # Extract patterns using regex and ML1033 analysis["patterns"] = await self._extract_patterns(logs)10341035 # Find anomalies1036 analysis["anomalies"] = await self._detect_log_anomalies(logs)10371038 # Identify trending topics/errors1039 analysis["trending_topics"] = await self._identify_trending_topics(logs)10401041 # Generate recommendations1042 analysis["recommendations"] = self._generate_log_recommendations(analysis)10431044 return analysis10451046 async def _extract_patterns(self, logs: List[LogEntry]) -> List[Dict[str, Any]]:1047 """Extract common patterns from logs"""1048 # Simplified pattern extraction1049 # In production, use more sophisticated NLP techniques1050 patterns = []10511052 # Group logs by service1053 service_logs = {}1054 for log in logs:1055 if log.service not in service_logs:1056 service_logs[log.service] = []1057 service_logs[log.service].append(log)10581059 # Find error patterns1060 for service, service_log_list in service_logs.items():1061 error_logs = [l for l in service_log_list if l.level.lower() == "error"]1062 if len(error_logs) > 0:1063 # Find common substrings in error messages1064 common_errors = {}1065 for log in error_logs:1066 # Simplified - use actual pattern matching in production1067 for word in log.message.split():1068 if len(word) > 5: # Only consider longer words1069 common_errors[word] = common_errors.get(word, 0) + 110701071 if common_errors:1072 most_common = max(common_errors, key=common_errors.get)1073 patterns.append({1074 "service": service,1075 "type": "error_pattern",1076 "pattern": most_common,1077 "count": common_errors[most_common],1078 "percentage": common_errors[most_common] / len(error_logs) * 1001079 })10801081 return patterns10821083 async def _detect_log_anomalies(self, logs: List[LogEntry]) -> List[Dict[str, Any]]:1084 """Detect anomalies in logs"""1085 anomalies = []10861087 # Check for unusual error spikes1088 error_by_minute = {}1089 for log in logs:1090 if log.level.lower() in ["error", "critical"]:1091 minute = log.timestamp.replace(second=0, microsecond=0)1092 error_by_minute[minute] = error_by_minute.get(minute, 0) + 110931094 if error_by_minute:1095 avg_errors = np.mean(list(error_by_minute.values()))1096 for minute, count in error_by_minute.items():1097 if count > avg_errors * 3: # 3x spike1098 anomalies.append({1099 "type": "error_spike",1100 "timestamp": minute.isoformat(),1101 "value": count,1102 "baseline": avg_errors,1103 "severity": "high"1104 })11051106 return anomalies11071108 async def _identify_trending_topics(self, logs: List[LogEntry]) -> List[Dict[str, Any]]:1109 """Identify trending topics in logs"""1110 # Simplified trending detection1111 word_count = {}1112 for log in logs[-100:]: # Last 100 logs1113 for word in log.message.lower().split():1114 if len(word) > 5 and word.isalpha():1115 word_count[word] = word_count.get(word, 0) + 111161117 # Get top trending words1118 trending = sorted(word_count.items(), key=lambda x: x[1], reverse=True)[:10]11191120 return [1121 {"topic": word, "count": count}1122 for word, count in trending1123 ]11241125 def _generate_log_recommendations(self, analysis: Dict[str, Any]) -> List[str]:1126 """Generate recommendations based on log analysis"""1127 recommendations = []11281129 if analysis["error_rate"] > 5:1130 recommendations.append(1131 f"High error rate ({analysis['error_rate']:.1f}%) detected - investigate immediately"1132 )11331134 if len(analysis["anomalies"]) > 0:1135 recommendations.append(1136 f"Found {len(analysis['anomalies'])} anomalies - review and address"1137 )11381139 for pattern in analysis["patterns"][:3]:1140 if pattern["percentage"] > 30:1141 recommendations.append(1142 f"Common error pattern in {pattern['service']}: {pattern['pattern']}"1143 )11441145 return recommendations1146```11471148## 3. Automation and Self-Healing11491150### Automation Engine11511152```python1153# aiops/automation/engine.py1154import asyncio1155import subprocess1156from typing import Dict, List, Any, Optional, Callable1157from dataclasses import dataclass1158from enum import Enum1159import logging1160from datetime import datetime, timedelta11611162logger = logging.getLogger(__name__)11631164class ActionType(str, Enum):1165 """Types of automation actions"""1166 SCALE = "scale"1167 RESTART = "restart"1168 PATCH = "patch"1169 NOTIFY = "notify"1170 SUPPRESS = "suppress"1171 ISOLATE = "isolate"1172 FAILBACK = "failback"11731174@dataclass1175class Action:1176 """Automation action definition"""1177 type: ActionType1178 target: str1179 params: Dict[str, Any]1180 conditions: List[str] = None1181 timeout: int = 3001182 retries: int = 311831184class AutomationEngine:1185 """Automation engine for executing remediation actions"""11861187 def __init__(self):1188 self.actions: Dict[str, Action] = {}1189 self.execution_history: List[Dict[str, Any]] = []1190 self.action_handlers: Dict[ActionType, Callable] = {1191 ActionType.SCALE: self._handle_scale,1192 ActionType.RESTART: self._handle_restart,1193 ActionType.PATCH: self._handle_patch,1194 ActionType.NOTIFY: self._handle_notify,1195 ActionType.SUPPRESS: self._handle_suppress,1196 ActionType.ISOLATE: self._handle_isolate,1197 ActionType.FAILBACK: self._handle_failback1198 }11991200 def register_action(self, action: Action) -> None:1201 """Register an automation action"""1202 self.actions[action.target] = action1203 logger.info(f"Registered action: {action.type} for {action.target}")12041205 async def execute(self, action: Action) -> Dict[str, Any]:1206 """Execute an automation action"""1207 execution_id = f"{action.type}_{action.target}_{int(datetime.utcnow().timestamp())}"12081209 logger.info(f"Executing action {execution_id}: {action.type} on {action.target}")12101211 execution = {1212 "id": execution_id,1213 "action": action,1214 "status": "running",1215 "started_at": datetime.utcnow(),1216 "result": None,1217 "error": None1218 }12191220 try:1221 # Check conditions1222 if action.conditions and not await self._check_conditions(action.conditions):1223 execution["status"] = "skipped"1224 execution["error"] = "Conditions not met"1225 return execution12261227 # Execute action with retries1228 result = await self._execute_with_retries(action)12291230 execution["status"] = "success"1231 execution["result"] = result1232 logger.info(f"Action {execution_id} completed successfully")12331234 except Exception as e:1235 execution["status"] = "failed"1236 execution["error"] = str(e)1237 logger.error(f"Action {execution_id} failed: {e}")12381239 finally:1240 execution["completed_at"] = datetime.utcnow()1241 execution["duration"] = (execution["completed_at"] - execution["started_at"]).total_seconds()1242 self.execution_history.append(execution)12431244 return execution12451246 async def _execute_with_retries(self, action: Action) -> Any:1247 """Execute action with retry logic"""1248 last_exception = None12491250 for attempt in range(action.retries + 1):1251 try:1252 handler = self.action_handlers.get(action.type)1253 if not handler:1254 raise ValueError(f"No handler for action type: {action.type}")12551256 # Execute with timeout1257 return await asyncio.wait_for(1258 handler(action),1259 timeout=action.timeout1260 )12611262 except asyncio.TimeoutError:1263 last_exception = TimeoutError(f"Action timed out after {action.timeout}s")1264 if attempt < action.retries:1265 await asyncio.sleep(2 ** attempt) # Exponential backoff1266 continue1267 raise last_exception12681269 except Exception as e:1270 last_exception = e1271 if attempt < action.retries:1272 await asyncio.sleep(2 ** attempt) # Exponential backoff1273 continue1274 raise last_exception12751276 async def _check_conditions(self, conditions: List[str]) -> bool:1277 """Check if action conditions are met"""1278 # Implement condition checking logic1279 # For example, check cluster health, time windows, etc.1280 return True12811282 async def _handle_scale(self, action: Action) -> Dict[str, Any]:1283 """Handle scale action"""1284 params = action.params1285 command = [1286 "kubectl", "scale",1287 f"--replicas={params.get('replicas', '+1')}",1288 f"deployment/{action.target}"1289 ]12901291 if "namespace" in params:1292 command.insert(1, f"-n={params['namespace']}")12931294 result = await self._run_command(command)1295 return {"scaled": True, "result": result}12961297 async def _handle_restart(self, action: Action) -> Dict[str, Any]:1298 """Handle restart action"""1299 params = action.params1300 command = ["kubectl", "rollout", "restart", f"deployment/{action.target}"]13011302 if "namespace" in params:1303 command.insert(2, f"-n={params['namespace']}")13041305 result = await self._run_command(command)1306 return {"restarted": True, "result": result}13071308 async def _handle_patch(self, action: Action) -> Dict[str, Any]:1309 """Handle patch action"""1310 params = action.params13111312 # Build patch command1313 command = ["kubectl", "patch"]13141315 if "namespace" in params:1316 command.extend(["-n", params["namespace"]])13171318 resource_type = params.get("type", "deployment")1319 command.extend([f"{resource_type}/{action.target}"])13201321 patch_type = params.get("patch_type", "strategic")1322 command.extend(["--type", patch_type])13231324 patch_data = params.get("patch", {})1325 command.extend(["-p", json.dumps(patch_data)])13261327 result = await self._run_command(command)1328 return {"patched": True, "result": result}13291330 async def _handle_notify(self, action: Action) -> Dict[str, Any]:1331 """Handle notification action"""1332 params = action.params1333 channel = params.get("channel", "default")1334 message = params.get("message", f"AAction executed: {action.type} on {action.target}")13351336 # Implement notification logic (Slack, Teams, Email, etc.)1337 # This is a placeholder for actual notification implementation1338 notification = {1339 "channel": channel,1340 "message": message,1341 "timestamp": datetime.utcnow().isoformat(),1342 "sent": True1343 }13441345 # Example: Send to Slack1346 if channel == "slack":1347 webhook_url = params.get("webhook_url")1348 if webhook_url:1349 slack_payload = {1350 "text": message,1351 "attachments": [{1352 "color": "warning",1353 "fields": [{1354 "title": "Action",1355 "value": f"{action.type} on {action.target}",1356 "short": True1357 }, {1358 "title": "Timestamp",1359 "value": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),1360 "short": True1361 }]1362 }]1363 }13641365 async with aiohttp.ClientSession() as session:1366 async with session.post(webhook_url, json=slack_payload) as response:1367 if response.status != 200:1368 raise Exception(f"Slack notification failed: {response.status}")13691370 return notification13711372 async def _handle_suppress(self, action: Action) -> Dict[str, Any]:1373 """Handle alert suppression"""1374 params = action.params1375 duration = params.get("duration", "1h")1376 reason = params.get("reason", "Automated suppression")13771378 # Implement alert suppression logic1379 # This depends on your alerting system (Prometheus, AlertManager, etc.)1380 suppression = {1381 "target": action.target,1382 "duration": duration,1383 "reason": reason,1384 "timestamp": datetime.utcnow().isoformat()1385 }13861387 return {"suppressed": True, "suppression": suppression}13881389 async def _handle_isolate(self, action: Action) -> Dict[str, Any]:1390 """Handle service isolation"""1391 params = action.params1392 namespace = params.get("namespace", "default")13931394 # Implement isolation logic1395 # For example, update service to point to maintenance page1396 command = [1397 "kubectl", "patch", "service", action.target,1398 "-n", namespace,1399 "-p", '{"spec": {"selector": {"app": "maintenance"}}}'1400 ]14011402 result = await self._run_command(command)1403 return {"isolated": True, "result": result}14041405 async def _handle_failback(self, action: Action) -> Dict[str, Any]:1406 """Handle failback to primary"""1407 params = action.params1408 namespace = params.get("namespace", "default")14091410 # Implement failback logic1411 # Restore traffic to primary service1412 command = [1413 "kubectl", "patch", "service", action.target,1414 "-n", namespace,1415 "-p", '{"spec": {"selector": {"app": "' + action.target + '"}}}'1416 ]14171418 result = await self._run_command(command)1419 return {"failed_back": True, "result": result}14201421 async def _run_command(self, command: List[str]) -> str:1422 """Run shell command"""1423 process = await asyncio.create_subprocess_exec(1424 *command,1425 stdout=asyncio.subprocess.PIPE,1426 stderr=asyncio.subprocess.PIPE1427 )14281429 stdout, stderr = await process.communicate()14301431 if process.returncode != 0:1432 raise Exception(f"Command failed: {stderr.decode()}")14331434 return stdout.decode()14351436class SelfHealingManager:1437 """Manages self-healing policies and execution"""14381439 def __init__(self, automation_engine: AutomationEngine):1440 self.automation_engine = automation_engine1441 self.healing_policies: Dict[str, Dict[str, Any]] = {}1442 self.active_healings: Dict[str, Dict[str, Any]] = {}14431444 def register_healing_policy(1445 self,1446 service_name: str,1447 policy: Dict[str, Any]1448 ) -> None:1449 """Register a self-healing policy for a service"""1450 self.healing_policies[service_name] = policy1451 logger.info(f"Registered healing policy for {service_name}")14521453 async def trigger_healing(1454 self,1455 service_name: str,1456 incident: Dict[str, Any]1457 ) -> Dict[str, Any]:1458 """Trigger self-healing for a service"""1459 if service_name not in self.healing_policies:1460 return {"error": "No healing policy registered"}14611462 policy = self.healing_policies[service_name]1463 healing_id = f"healing_{service_name}_{int(datetime.utcnow().timestamp())}"14641465 logger.info(f"Triggering self-healing {healing_id} for {service_name}")14661467 healing_record = {1468 "id": healing_id,1469 "service": service_name,1470 "incident": incident,1471 "policy": policy,1472 "status": "running",1473 "actions": [],1474 "started_at": datetime.utcnow()1475 }14761477 self.active_healings[healing_id] = healing_record14781479 try:1480 # Execute healing actions based on policy1481 for action_def in policy.get("actions", []):1482 action = Action(1483 type=ActionType(action_def["type"]),1484 target=action_def.get("target", service_name),1485 params=action_def.get("params", {}),1486 timeout=action_def.get("timeout", 300)1487 )14881489 result = await self.automation_engine.execute(action)1490 healing_record["actions"].append({1491 "action": action_def,1492 "result": result1493 })14941495 # Check if healing was successful1496 if result["status"] != "success":1497 healing_record["status"] = "failed"1498 break1499 else:1500 healing_record["status"] = "success"15011502 except Exception as e:1503 healing_record["status"] = "error"1504 healing_record["error"] = str(e)1505 logger.error(f"Self-healing failed: {e}")15061507 finally:1508 healing_record["completed_at"] = datetime.utcnow()1509 healing_record["duration"] = (1510 healing_record["completed_at"] - healing_record["started_at"]1511 ).total_seconds()15121513 return healing_record15141515 async def check_healing_status(self, healing_id: str) -> Optional[Dict[str, Any]]:1516 """Get status of an active healing process"""1517 return self.active_healings.get(healing_id)1518```15191520## 4. Observability and Monitoring Best Practices15211522### Unified Observability Platform15231524```python1525# aiops/observability/platform.py1526import asyncio1527from typing import Dict, List, Any, Optional1528from datetime import datetime, timedelta1529from dataclasses import dataclass, field1530import json1531import logging15321533logger = logging.getLogger(__name__)15341535@dataclass1536class ServiceHealth:1537 """Service health status"""1538 service_name: str1539 status: str # healthy, degraded, unhealthy1540 latency_p99: float1541 error_rate: float1542 throughput: float1543 last_check: datetime1544 dependencies: List[str] = field(default_factory=list)1545 sla_status: str = "within_sla"15461547class ObservabilityPlatform:1548 """Unified observability platform for AIOps"""15491550 def __init__(self, data_sources: List[DataSource]):1551 self.data_sources = data_sources1552 self.service_health: Dict[str, ServiceHealth] = {}1553 self.slo_compliance: Dict[str, Dict[str, Any]] = {}1554 self.dashboard_configs: Dict[str, Dict[str, Any]] = {}15551556 async def get_service_overview(self) -> Dict[str, Any]:1557 """Get comprehensive service overview"""1558 overview = {1559 "total_services": len(self.service_health),1560 "healthy_services": 0,1561 "degraded_services": 0,1562 "unhealthy_services": 0,1563 "services": {}1564 }15651566 for service_name, health in self.service_health.items():1567 overview["services"][service_name] = {1568 "status": health.status,1569 "latency_p99": health.latency_p99,1570 "error_rate": health.error_rate,1571 "throughput": health.throughput,1572 "sla_status": health.sla_status1573 }15741575 if health.status == "healthy":1576 overview["healthy_services"] += 11577 elif health.status == "degraded":1578 overview["degraded_services"] += 11579 else:1580 overview["unhealthy_services"] += 115811582 return overview15831584 async def check_slo_compliance(1585 self,1586 service_name: str,1587 slo_config: Dict[str, Any]1588 ) -> Dict[str, Any]:1589 """Check SLO compliance for a service"""1590 now = datetime.utcnow()1591 window = timedelta(days=30) # 30-day rolling window15921593 # Collect metrics for SLO calculation1594 metrics = []1595 for source in self.data_sources:1596 try:1597 source_metrics = await source.collect_metrics(1598 query=slo_config["metric_query"],1599 start_time=now - window,1600 end_time=now1601 )1602 metrics.extend(source_metrics)1603 except Exception as e:1604 logger.error(f"Failed to collect metrics from {type(source).__name__}: {e}")16051606 if not metrics:1607 return {"error": "No metrics available"}16081609 # Calculate SLO compliance1610 total_requests = sum(m.value for m in metrics if m.name.endswith("_total"))1611 good_requests = sum(m.value for m in metrics if m.name.endswith("_success"))16121613 if total_requests == 0:1614 return {"error": "No requests in time window"}16151616 actual_availability = (good_requests / total_requests) * 1001617 target_availability = slo_config["target"]16181619 compliance = {1620 "service": service_name,1621 "slo_name": slo_config["name"],1622 "target_availability": target_availability,1623 "actual_availability": actual_availability,1624 "compliance": actual_availability >= target_availability,1625 "error_budget": target_availability - actual_availability,1626 "time_window": window.days,1627 "total_requests": total_requests,1628 "good_requests": good_requests,1629 "calculated_at": now.isoformat()1630 }16311632 self.slo_compliance[f"{service_name}_{slo_config['name']}"] = compliance1633 return compliance16341635 async def generate_incident_report(1636 self,1637 incident_id: str,1638 start_time: datetime,1639 end_time: Optional[datetime] = None1640 ) -> Dict[str, Any]:1641 """Generate comprehensive incident report"""1642 if not end_time:1643 end_time = datetime.utcnow()16441645 report = {1646 "incident_id": incident_id,1647 "start_time": start_time.isoformat(),1648 "end_time": end_time.isoformat(),1649 "duration_hours": (end_time - start_time).total_seconds() / 3600,1650 "affected_services": [],1651 "metrics_impact": {},1652 "error_rate_impact": {},1653 "user_impact": {},1654 "timeline": [],1655 "root_cause_analysis": {},1656 "action_items": []1657 }16581659 # Collect data for affected services1660 for service_name, health in self.service_health.items():1661 if health.last_check >= start_time and health.last_check <= end_time:1662 report["affected_services"].append(service_name)16631664 # Collect metrics impact1665 for source in self.data_sources:1666 try:1667 metrics = await source.collect_metrics(1668 query=f"rate(http_requests_total[5m])",1669 start_time=start_time,1670 end_time=end_time1671 )1672 if metrics:1673 report["metrics_impact"][service_name] = [1674 {"timestamp": m.timestamp.isoformat(), "value": m.value}1675 for m in metrics1676 ]1677 except Exception as e:1678 logger.error(f"Failed to collect metrics for {service_name}: {e}")16791680 return report16811682 async def create_dashboard(1683 self,1684 dashboard_name: str,1685 config: Dict[str, Any]1686 ) -> Dict[str, Any]:1687 """Create a new observability dashboard"""1688 dashboard = {1689 "name": dashboard_name,1690 "description": config.get("description", ""),1691 "panels": config.get("panels", []),1692 "time_range": config.get("time_range", "1h"),1693 "refresh_interval": config.get("refresh_interval", "5m"),1694 "created_at": datetime.utcnow().isoformat()1695 }16961697 self.dashboard_configs[dashboard_name] = dashboard1698 return dashboard16991700 async def get_dashboard_data(1701 self,1702 dashboard_name: str,1703 time_range: Optional[str] = None1704 ) -> Dict[str, Any]:1705 """Get data for a specific dashboard"""1706 if dashboard_name not in self.dashboard_configs:1707 return {"error": "Dashboard not found"}17081709 dashboard = self.dashboard_configs[dashboard_name]1710 now = datetime.utcnow()17111712 # Parse time range1713 if time_range:1714 end_time = now1715 if time_range.endswith("h"):1716 start_time = now - timedelta(hours=int(time_range[:-1]))1717 elif time_range.endswith("d"):1718 start_time = now - timedelta(days=int(time_range[:-1]))1719 else:1720 start_time = now - timedelta(hours=1)1721 else:1722 start_time = now - timedelta(hours=1)1723 end_time = now17241725 dashboard_data = {1726 "name": dashboard_name,1727 "time_range": {"start": start_time.isoformat(), "end": end_time.isoformat()},1728 "panels": []1729 }17301731 # Collect data for each panel1732 for panel in dashboard["panels"]:1733 panel_data = {1734 "title": panel["title"],1735 "type": panel["type"],1736 "data": []1737 }17381739 try:1740 # Collect metrics based on panel query1741 for source in self.data_sources:1742 metrics = await source.collect_metrics(1743 query=panel["query"],1744 start_time=start_time,1745 end_time=end_time1746 )1747 panel_data["data"].extend([1748 {"timestamp": m.timestamp.isoformat(), "value": m.value}1749 for m in metrics1750 ])1751 except Exception as e:1752 panel_data["error"] = str(e)17531754 dashboard_data["panels"].append(panel_data)17551756 return dashboard_data17571758# SLO and SLA Management1759class SLOManager:1760 """Manages Service Level Objectives and Service Level Agreements"""17611762 def __init__(self):1763 self.slos: Dict[str, Dict[str, Any]] = {}1764 self.slas: Dict[str, Dict[str, Any]] = {}17651766 def define_slo(1767 self,1768 service_name: str,1769 slo_name: str,1770 target: float,1771 time_window: str,1772 alerting_burn_rate: float = 2.01773 ) -> Dict[str, Any]:1774 """Define a Service Level Objective"""1775 slo = {1776 "service_name": service_name,1777 "slo_name": slo_name,1778 "target": target,1779 "time_window": time_window,1780 "alerting_burn_rate": alerting_burn_rate,1781 "created_at": datetime.utcnow().isoformat(),1782 "status": "active"1783 }17841785 self.slos[f"{service_name}_{slo_name}"] = slo1786 return slo17871788 def define_sla(1789 self,1790 service_name: str,1791 sla_name: str,1792 availability_target: float,1793 performance_targets: Dict[str, float],1794 penalties: Dict[str, Any] = None1795 ) -> Dict[str, Any]:1796 """Define a Service Level Agreement"""1797 sla = {1798 "service_name": service_name,1799 "sla_name": sla_name,1800 "availability_target": availability_target,1801 "performance_targets": performance_targets,1802 "penalties": penalties or {},1803 "created_at": datetime.utcnow().isoformat(),1804 "status": "active"1805 }18061807 self.slas[f"{service_name}_{sla_name}"] = sla1808 return sla18091810 def calculate_error_budget(1811 self,1812 service_name: str,1813 slo_name: str,1814 period_days: int = 301815 ) -> Dict[str, Any]:1816 """Calculate error budget for an SLO"""1817 slo_key = f"{service_name}_{slo_name}"1818 if slo_key not in self.slos:1819 return {"error": "SLO not found"}18201821 slo = self.slos[slo_key]1822 target_availability = slo["target"]18231824 # Calculate error budget1825 period_hours = period_days * 241826 error_budget = (100 - target_availability) / 100 * period_hours18271828 return {1829 "service": service_name,1830 "slo": slo_name,1831 "period_days": period_days,1832 "target_availability": target_availability,1833 "error_budget_hours": error_budget,1834 "error_budget_percentage": 100 - target_availability,1835 "remaining_error_budget": error_budget, # Would be calculated from actual metrics1836 "burn_rate": 0.0 # Would be calculated from actual metrics1837 }1838```18391840This comprehensive AIOps skill provides production-ready patterns for implementing AI-powered operations in 2025, including intelligent monitoring, anomaly detection, predictive analytics, automation, and self-healing capabilities.18411842`★ Insight ─────────────────────────────────────`1843The AIOps patterns shown here emphasize several key 2025 best practices:18441. **Data Source Abstraction**: Generic interfaces allow integration with any monitoring platform (Prometheus, Datadog, New Relic, etc.)18452. **ML-Driven Operations**: Anomaly detection, predictive analytics, and pattern recognition using proven ML models18463. **Automation with Safety**: Retry logic, timeout handling, and condition checking ensure safe automated remediation18474. **Observability First**: Unified platform approach to metrics, logs, and traces for comprehensive visibility18485. **SLO-Driven**: Focus on business outcomes through Service Level Objectives and error budget management18491850These patterns ensure your AIOps implementation is intelligent, automated, and aligned with business objectives.1851`─────────────────────────────────────────────────`