analyze_performance.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #!/usr/bin/env python3
  2. """
  3. 性能日志分析工具
  4. 分析后端日志,统计STT、LLM、TTS各阶段耗时
  5. """
  6. import re
  7. import sys
  8. from typing import Dict, List
  9. from dataclasses import dataclass, field
  10. from statistics import mean, median
  11. @dataclass
  12. class RequestStats:
  13. """单个请求的统计数据"""
  14. request_id: str
  15. stt_duration: float = 0.0
  16. llm_duration: float = 0.0
  17. tts_duration: float = 0.0
  18. total_duration: float = 0.0
  19. user_input: str = ""
  20. response_text: str = ""
  21. emotion: str = ""
  22. def is_complete(self) -> bool:
  23. """检查是否有完整的统计数据"""
  24. return self.total_duration > 0
  25. @dataclass
  26. class PerformanceStats:
  27. """性能统计汇总"""
  28. total_requests: int = 0
  29. completed_requests: int = 0
  30. stt_times: List[float] = field(default_factory=list)
  31. llm_times: List[float] = field(default_factory=list)
  32. tts_times: List[float] = field(default_factory=list)
  33. total_times: List[float] = field(default_factory=list)
  34. def add_request(self, req: RequestStats):
  35. """添加一个请求的统计数据"""
  36. self.total_requests += 1
  37. if req.is_complete():
  38. self.completed_requests += 1
  39. self.stt_times.append(req.stt_duration)
  40. self.llm_times.append(req.llm_duration)
  41. self.tts_times.append(req.tts_duration)
  42. self.total_times.append(req.total_duration)
  43. def print_summary(self):
  44. """打印统计摘要(已禁用)"""
  45. pass
  46. def _print_stats(self, name: str, times: List[float]):
  47. """打印单个阶段的统计信息(已禁用)"""
  48. pass
  49. def analyze_log(log_content: str) -> PerformanceStats:
  50. """分析日志内容"""
  51. stats = PerformanceStats()
  52. requests: Dict[str, RequestStats] = {}
  53. lines = log_content.split('\n')
  54. for line in lines:
  55. # 提取 request_id
  56. request_id_match = re.search(r'\[([a-f0-9\-]{36})\]', line)
  57. if not request_id_match:
  58. continue
  59. request_id = request_id_match.group(1)
  60. # 确保有这个请求的记录
  61. if request_id not in requests:
  62. requests[request_id] = RequestStats(request_id=request_id)
  63. req = requests[request_id]
  64. # 提取STT耗时
  65. stt_match = re.search(r'⏱️\s+STT耗时:\s+([\d.]+)秒', line)
  66. if stt_match:
  67. req.stt_duration = float(stt_match.group(1))
  68. # 提取LLM耗时
  69. llm_match = re.search(r'⏱️\s+LLM耗时:\s+([\d.]+)秒', line)
  70. if llm_match:
  71. req.llm_duration = float(llm_match.group(1))
  72. # 提取TTS耗时
  73. tts_match = re.search(r'⏱️\s+TTS耗时:\s+([\d.]+)秒', line)
  74. if tts_match:
  75. req.tts_duration = float(tts_match.group(1))
  76. # 提取总耗时
  77. total_match = re.search(r'⏱️\s+总耗时:\s+([\d.]+)秒', line)
  78. if total_match:
  79. req.total_duration = float(total_match.group(1))
  80. # 提取用户输入
  81. if 'STT识别结果:' in line:
  82. text_match = re.search(r'STT识别结果:\s*(.+)$', line)
  83. if text_match:
  84. req.user_input = text_match.group(1).strip()
  85. # 提取回复文本
  86. if '回复文本:' in line:
  87. text_match = re.search(r'回复文本:\s*(.+)$', line)
  88. if text_match:
  89. req.response_text = text_match.group(1).strip()
  90. # 提取情感
  91. if re.search(r'^情感:', line):
  92. emotion_match = re.search(r'情感:\s*(\w+)', line)
  93. if emotion_match:
  94. req.emotion = emotion_match.group(1)
  95. # 添加所有请求到统计
  96. for req in requests.values():
  97. stats.add_request(req)
  98. return stats
  99. def main():
  100. """主函数"""
  101. if len(sys.argv) > 1:
  102. # 从文件读取
  103. log_file = sys.argv[1]
  104. try:
  105. with open(log_file, 'r', encoding='utf-8') as f:
  106. log_content = f.read()
  107. except Exception as e:
  108. sys.exit(1)
  109. else:
  110. # 从标准输入读取
  111. log_content = sys.stdin.read()
  112. # 分析日志
  113. stats = analyze_log(log_content)
  114. # 打印统计
  115. stats.print_summary()
  116. if __name__ == "__main__":
  117. main()