charSLee013
feat: complete Hugging Face Spaces deployment with production-ready CognitiveKernel-Launchpad
1ea26af
#!/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)