1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
| import docker import re import json from datetime import datetime, timedelta from collections import defaultdict, Counter import matplotlib.pyplot as plt import pandas as pd
class DockerLogAnalyzer: def __init__(self): self.client = docker.from_env() def get_container_logs(self, container_name: str, hours: int = 24) -> list: """获取容器日志""" try: container = self.client.containers.get(container_name) since = datetime.now() - timedelta(hours=hours) logs = container.logs( since=since, timestamps=True, stdout=True, stderr=True ).decode('utf-8') return logs.split('\n') except Exception as e: print(f"获取日志失败: {e}") return [] def parse_log_levels(self, logs: list) -> dict: """解析日志级别分布""" levels = Counter() level_patterns = { 'ERROR': r'\b(ERROR|error|Error)\b', 'WARN': r'\b(WARN|warn|Warn|WARNING|warning|Warning)\b', 'INFO': r'\b(INFO|info|Info)\b', 'DEBUG': r'\b(DEBUG|debug|Debug)\b' } for log in logs: for level, pattern in level_patterns.items(): if re.search(pattern, log): levels[level] += 1 break else: levels['OTHER'] += 1 return dict(levels) def find_error_patterns(self, logs: list) -> dict: """查找错误模式""" error_patterns = defaultdict(int) error_keywords = [ r'connection.*refused', r'timeout', r'out of memory', r'permission denied', r'file not found', r'database.*error', r'authentication.*failed', r'ssl.*error' ] for log in logs: if re.search(r'\b(ERROR|error|Error)\b', log): for pattern in error_keywords: if re.search(pattern, log, re.IGNORECASE): error_patterns[pattern] += 1 return dict(error_patterns) def analyze_response_times(self, logs: list) -> dict: """分析响应时间""" response_times = [] time_pattern = r'(\d+(?:\.\d+)?)\s*ms' for log in logs: matches = re.findall(time_pattern, log) for match in matches: response_times.append(float(match)) if response_times: return { 'count': len(response_times), 'avg': sum(response_times) / len(response_times), 'min': min(response_times), 'max': max(response_times), 'p95': sorted(response_times)[int(len(response_times) * 0.95)] } return {} def generate_report(self, container_name: str, hours: int = 24) -> dict: """生成分析报告""" logs = self.get_container_logs(container_name, hours) if not logs: return {'error': '无法获取日志'} report = { 'container': container_name, 'analysis_period': f'{hours} hours', 'total_logs': len(logs), 'log_levels': self.parse_log_levels(logs), 'error_patterns': self.find_error_patterns(logs), 'response_times': self.analyze_response_times(logs), 'timestamp': datetime.now().isoformat() } return report def visualize_log_levels(self, report: dict): """可视化日志级别分布""" levels = report['log_levels'] plt.figure(figsize=(10, 6)) plt.bar(levels.keys(), levels.values()) plt.title(f'Log Levels Distribution - {report["container"]}') plt.xlabel('Log Level') plt.ylabel('Count') plt.xticks(rotation=45) plt.tight_layout() plt.show() def export_report(self, report: dict, filename: str = None): """导出报告""" if not filename: filename = f"log_analysis_{report['container']}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(filename, 'w', encoding='utf-8') as f: json.dump(report, f, indent=2, ensure_ascii=False) print(f"报告已导出到: {filename}")
analyzer = DockerLogAnalyzer()
report = analyzer.generate_report('my_app_container', hours=24) print(json.dumps(report, indent=2))
|