Spaces:
Sleeping
Sleeping
File size: 8,926 Bytes
1ea26af |
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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
#!/usr/bin/env python3
"""
CognitiveKernel-Pro 日志管理系统
自动生成控制台输出日志到本地文件夹
"""
import os
import sys
import time
import json
from datetime import datetime
from typing import Optional, TextIO
from pathlib import Path
class ConsoleLogger:
"""
控制台输出日志记录器
自动将控制台输出同时写入日志文件
"""
def __init__(self, log_dir: str = "logs", task_name: str = None):
"""
初始化日志记录器
Args:
log_dir: 日志目录
task_name: 任务名称,用于生成日志文件名
"""
self.log_dir = Path(log_dir)
self.task_name = task_name or "cognitive_kernel"
self.log_file = None
self.original_stdout = None
self.original_stderr = None
self.start_time = time.time()
# 创建日志目录
self.log_dir.mkdir(exist_ok=True)
# 生成日志文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
self.log_filename = f"{self.task_name}_console_{timestamp}.log"
self.log_filepath = self.log_dir / self.log_filename
print(f"📁 日志将保存到: {self.log_filepath}")
def start_logging(self):
"""
开始记录控制台输出
"""
try:
# 保存原始的stdout和stderr
self.original_stdout = sys.stdout
self.original_stderr = sys.stderr
# 打开日志文件
self.log_file = open(self.log_filepath, 'w', encoding='utf-8')
# 写入日志头部信息
self._write_log_header()
# 替换stdout和stderr
sys.stdout = TeeOutput(self.original_stdout, self.log_file)
sys.stderr = TeeOutput(self.original_stderr, self.log_file)
print(f"✅ 控制台日志记录已启动")
print(f"📝 日志文件: {self.log_filepath}")
except Exception as e:
print(f"❌ 启动日志记录失败: {e}")
self.stop_logging()
def stop_logging(self):
"""
停止记录控制台输出
"""
try:
if self.original_stdout:
sys.stdout = self.original_stdout
if self.original_stderr:
sys.stderr = self.original_stderr
if self.log_file:
# 写入日志尾部信息
self._write_log_footer()
self.log_file.close()
self.log_file = None
print(f"✅ 控制台日志记录已停止")
print(f"📁 日志已保存到: {self.log_filepath}")
except Exception as e:
print(f"❌ 停止日志记录失败: {e}")
def _write_log_header(self):
"""
写入日志头部信息
"""
header = f"""
{'='*80}
CognitiveKernel-Pro 控制台输出日志
{'='*80}
任务名称: {self.task_name}
开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
日志文件: {self.log_filename}
Python版本: {sys.version}
工作目录: {os.getcwd()}
{'='*80}
"""
self.log_file.write(header)
self.log_file.flush()
def _write_log_footer(self):
"""
写入日志尾部信息
"""
end_time = time.time()
duration = end_time - self.start_time
footer = f"""
{'='*80}
日志记录结束
{'='*80}
结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
总执行时间: {duration:.2f} 秒
日志文件大小: {self.log_filepath.stat().st_size} 字节
{'='*80}
"""
self.log_file.write(footer)
self.log_file.flush()
def __enter__(self):
"""
上下文管理器入口
"""
self.start_logging()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""
上下文管理器出口
"""
self.stop_logging()
class TeeOutput:
"""
同时输出到控制台和文件的包装器
"""
def __init__(self, console: TextIO, file: TextIO):
self.console = console
self.file = file
def write(self, text: str):
"""
同时写入控制台和文件
"""
# 写入控制台
self.console.write(text)
self.console.flush()
# 写入文件,添加时间戳
if text.strip(): # 只对非空行添加时间戳
timestamp = datetime.now().strftime('[%H:%M:%S] ')
# 如果文本不是以换行符开始,添加时间戳
if not text.startswith('\n'):
self.file.write(timestamp)
self.file.write(text)
self.file.flush()
def flush(self):
"""
刷新缓冲区
"""
self.console.flush()
self.file.flush()
def __getattr__(self, name):
"""
代理其他属性到控制台
"""
return getattr(self.console, name)
class SessionLogger:
"""
会话详细日志记录器
记录完整的会话数据
"""
def __init__(self, log_dir: str = "logs"):
self.log_dir = Path(log_dir)
self.log_dir.mkdir(exist_ok=True)
def save_session_log(self, session, task_name: str = None) -> str:
"""
保存会话详细日志
Args:
session: AgentSession对象
task_name: 任务名称
Returns:
日志文件路径
"""
try:
# 生成文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
task_name = task_name or "session"
filename = f"{task_name}_detailed_{timestamp}.json"
filepath = self.log_dir / filename
# 转换会话数据
session_data = session.to_dict()
# 添加元数据
session_data['_metadata'] = {
'log_created_at': datetime.now().isoformat(),
'log_filename': filename,
'total_steps': len(session_data.get('steps', [])),
'task_summary': session_data.get('task', '')[:100] + '...' if len(session_data.get('task', '')) > 100 else session_data.get('task', '')
}
# 保存到文件
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(session_data, f, ensure_ascii=False, indent=2, default=str)
print(f"📁 会话详细日志已保存: {filepath}")
return str(filepath)
except Exception as e:
print(f"❌ 保存会话日志失败: {e}")
return None
def setup_logging_environment():
"""
设置日志环境
创建日志目录并更新gitignore
"""
# 创建logs目录
logs_dir = Path("logs")
logs_dir.mkdir(exist_ok=True)
# 创建子目录
(logs_dir / "console").mkdir(exist_ok=True)
(logs_dir / "sessions").mkdir(exist_ok=True)
(logs_dir / "api_calls").mkdir(exist_ok=True)
# 创建README文件
readme_content = """# CognitiveKernel-Pro 日志目录
这个目录包含了CognitiveKernel-Pro运行时生成的各种日志文件。
## 目录结构
- `console/`: 控制台输出日志
- `sessions/`: 详细会话日志
- `api_calls/`: API调用日志
## 日志文件类型
### 控制台日志 (`*_console_*.log`)
- 完整的控制台输出
- 包含时间戳
- 实时执行过程记录
### 会话日志 (`*_detailed_*.json`)
- 完整的会话数据
- 每个步骤的详细信息
- Progress State历史
### API调用日志 (`*_api_*.log`)
- LLM API调用记录
- 请求和响应数据
- 性能统计
## 注意事项
- 这些日志文件已添加到 .gitignore 中
- 日志文件可能包含敏感信息,请勿提交到版本控制
- 定期清理旧的日志文件以节省磁盘空间
"""
with open(logs_dir / "README.md", 'w', encoding='utf-8') as f:
f.write(readme_content)
print(f"✅ 日志环境设置完成")
print(f"📁 日志目录: {logs_dir.absolute()}")
# 便捷函数
def start_console_logging(task_name: str = None) -> ConsoleLogger:
"""
启动控制台日志记录
Args:
task_name: 任务名称
Returns:
ConsoleLogger实例
"""
logger = ConsoleLogger(task_name=task_name)
logger.start_logging()
return logger
def save_session_log(session, task_name: str = None) -> str:
"""
保存会话详细日志
Args:
session: AgentSession对象
task_name: 任务名称
Returns:
日志文件路径
"""
logger = SessionLogger()
return logger.save_session_log(session, task_name)
|