log更新

This commit is contained in:
2025-08-06 09:27:44 +08:00
parent fad2b2d1c8
commit c2a941d4f5
2 changed files with 142 additions and 129 deletions
+66 -22
View File
@@ -3,28 +3,72 @@
### 程序框架 ### 程序框架
```angular2html ```angular2html
intelligence_system/ intelligence_system/
├── config/ # 配置管理 ├── config/ # 系统配置中心
│ ├── __init__.py │ ├── __init__.py # 配置包初始化
│ ├── settings.py # 全局参数 │ ├── settings.py # 主配置文件(数据库连接、API密钥等)
│ └── logging.conf # 日志配置 │ └── scheduler_rules.yaml # 任务调度规则
├── collectors/ # 数据采集
│ ├── news_api.py ├── data_collection/ # 数据采集层
── complaint_spider.py ── spiders/ # 网络爬虫子系统
├── processors/ # 数据处理 │ │ ├── weibo_spider.py # 黑猫爬虫
├── text_processor.py
── image_processor.py ── api_integration/ # API接口子系统
├── storage/ # 数据存储 │ │ ├── news_api.py # 新闻接口
├── database.py
│ └── cache_manager.py │ └── internal/ # 内部数据收集
├── applications/ # 应用层 │ ├── jian_dao_cloud.py # 简道云表单收集器
│ ├── reporter/
│ │ ├── daily.py ├── data_processing/ # 数据处理层
│ └── monthly.py ├── structured/ # 结构化数据处理
└── alert.py │ ├── data_cleaner.py # 数据清洗(去重/标准化)
├── utils/ # 工具类 └── schema_mapper.py # 数据结构转换器
├── logger.py
── network.py ── unstructured/ # 非结构化数据处理
└── main.py # 调度入口 │ │ ├── text_parser.py # 文本解析(PDF/HTML等)
│ │ ├── image_analyzer.py # 图像识别(OpenCV集成)
│ │ └── video_processor.py # 音视频分离分析
│ │
│ └── ai_engine/ # AI分析核心
│ ├── nlp_processor.py # 自然语言处理引擎
│ ├── sentiment_analyzer.py # 情感分析模型
│ └── topic_modeler.py # LDA主题建模工具
├── storage/ # 数据存储层
│ ├── mysql_agent.py # MySQL读写管理器
│ └── query_builder.py # SQL动态构建器
├── services/ # 应用服务层
│ ├── monitoring/ # 舆情监控
│ │ ├── opinion_monitor.py # 实时舆情追踪
│ │ └── brand_reputation.py # 品牌口碑分析
│ │
│ ├── analysis/ # 竞品分析
│ │ ├── competitor_tracker.py # 竞品动态监控
│ │ └── swot_generator.py # SWOT分析报告
│ │
│ ├── reporting/ # 报告服务
│ │ ├── daily_reporter.py # 自动化日报生成
│ │ └── weekly_digest.py # 周报汇编系统
│ │
│ └── alert/ # 预警服务
│ ├── alert_trigger.py # 动态阈值告警
│ └── notification_center.py # 邮件/短信通知
├── system_management/ # 系统管理层
│ ├── scheduler/ # 任务调度
│ │ ├── task_scheduler.py # 分布式任务调度器
│ │ └── cron_manager.py # 定时规则配置
│ │
│ └── monitor/ # 系统监控
│ ├── health_monitor.py # 服务健康检测
│ └── performance_watcher.py # 资源占用监控
├── utils/ # 工具库
│ ├── file_handler.py # 通用文件操作
│ ├── logger.py # 日志系统
│ └── datetime_parser.py # 时间格式处理
└── main.py # 系统入口(启动所有服务)
``` ```
### 程序设计原则 ### 程序设计原则
1. 所有程序尽可能在py文件中运行,尽量避免使用命令行执行 1. 所有程序尽可能在py文件中运行,尽量避免使用命令行执行
+76 -107
View File
@@ -1,129 +1,98 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
跨平台日志工具模块
功能:
1. 自动适配不同操作系统的日志路径
2. 支持中文等非ASCII字符
3. 日志文件自动按日期分割
4. 控制台与文件双输出
"""
import os import os
import sys import sys
import logging from pathlib import Path
from logging.handlers import TimedRotatingFileHandler from loguru import logger
from datetime import datetime
import platform import platform
from datetime import datetime
import zipfile
class CrossPlatformLog:
"""跨平台日志系统(支持Linux/Windows/Mac"""
class CrossPlatformLogger: def __init__(self):
def __init__(self, name="intelligence_system"): self.log_dir = self._get_log_dir()
""" self._setup_logger()
初始化跨平台日志系统
参数: def _get_log_dir(self):
name: 日志名称(用于创建日志文件夹) """获取跨平台日志目录(相对路径)"""
""" base_dir = Path(__file__).parent.parent # 项目根目录
self.system = platform.system().lower() log_dir = base_dir / "logs"
self.logger = logging.getLogger(name)
self.logger.setLevel(logging.INFO)
# 确保日志目录存在 # 自动创建日志目录
self.log_dir = self._get_log_dir(name) log_dir.mkdir(exist_ok=True)
os.makedirs(self.log_dir, exist_ok=True)
# 配置日志格式 # Windows特殊权限处理
formatter = logging.Formatter( if platform.system() == "Windows":
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 控制台处理器
self._setup_console_handler(formatter)
# 文件处理器(按天分割)
self._setup_file_handler(formatter)
# 处理未捕获的异常
sys.excepthook = self.handle_uncaught_exception
def _get_log_dir(self, name: str) -> str:
"""获取适合当前平台的日志目录路径"""
if self.system == 'windows':
base_dir = os.path.join(os.environ['APPDATA'], name)
elif self.system == 'darwin': # macOS
base_dir = os.path.expanduser(f"~/Library/Logs/{name}")
else: # Linux及其他Unix-like系统
base_dir = f"/var/log/{name}" if os.access("/var/log", os.W_OK) \
else os.path.expanduser(f"~/.local/share/{name}")
return base_dir
def _setup_console_handler(self, formatter: logging.Formatter):
"""配置控制台输出(兼容不同终端的编码)"""
console = logging.StreamHandler()
# Windows终端特殊处理
if self.system == 'windows' and not sys.stdout.isatty():
import colorama
try: try:
colorama.init() os.chmod(log_dir, 0o777) # 确保写入权限
except ImportError: except:
pass pass
# 解决Windows控制台编码问题 return log_dir
if sys.stdout.encoding != 'utf-8':
import io
sys.stdout = io.TextIOWrapper(
sys.stdout.buffer,
encoding='utf-8',
errors='replace'
)
console.setFormatter(formatter) def _setup_logger(self):
self.logger.addHandler(console) """配置跨平台日志处理器"""
logger.remove() # 清除默认配置
def _setup_file_handler(self, formatter: logging.Formatter): # 统一控制台输出格式
"""配置日志文件输出(UTF-8编码)""" logger.add(
log_file = os.path.join( sys.stdout,
self.log_dir, level="INFO",
f"{datetime.now().strftime('%Y%m%d')}.log" format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{module}</cyan> - <level>{message}</level>",
filter=lambda record: record["level"].no >= 20 # INFO及以上级别
) )
# 使用TimedRotatingFileHandler实现日志分割 # 主日志文件(兼容所有平台路径)
file_handler = TimedRotatingFileHandler( self._add_main_log()
filename=log_file,
when='midnight', # 每天午夜分割
encoding='utf-8',
backupCount=30 # 保留30天日志
)
file_handler.setFormatter(formatter)
self.logger.addHandler(file_handler)
def handle_uncaught_exception(self, exc_type, exc_value, exc_traceback): # 错误日志单独存储
"""全局异常捕获""" self._add_error_log()
self.logger.error(
"未捕获的异常:", def _add_main_log(self):
exc_info=(exc_type, exc_value, exc_traceback) """主日志文件配置"""
main_log = self.log_dir / "application.log"
logger.add(
str(main_log),
rotation="20 MB",
compression=self._compress_log,
encoding="utf-8",
level="DEBUG",
format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {module}:{line} - {message}",
retention="30 days",
enqueue=True # 线程安全
)
def _add_error_log(self):
"""错误日志专用配置"""
error_log = self.log_dir / "errors.log"
logger.add(
str(error_log),
level="ERROR",
format="{time:YYYY-MM-DD HH:mm:ss.SSS} | ERROR | {module}:{line} - {message}\n{exception}",
rotation="10 MB",
retention="90 days"
) )
@staticmethod @staticmethod
def get_logger(name: str = None) -> logging.Logger: def _compress_log(log_path):
"""获取配置好的日志实例""" """通用日志压缩方法(兼容所有平台)"""
return CrossPlatformLogger(name).logger if not os.path.exists(log_path):
return
try:
zip_path = f"{log_path}.{datetime.now().strftime('%Y%m%d')}.zip"
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
zipf.write(log_path, arcname=os.path.basename(log_path))
os.remove(log_path)
return zip_path
except Exception as e:
print(f"日志压缩失败: {str(e)}")
return log_path # 返回原文件路径继续使用
def setup_logging(name: str = "intelligence_system"): @classmethod
"""快速配置日志(兼容旧代码)""" def get_logger(cls, module_name=None):
return CrossPlatformLogger(name).logger """获取模块专属日志器"""
return logger.bind(module=module_name or "__main__")
# 初始化全局日志器
# 测试代码 log = CrossPlatformLog().get_logger()
if __name__ == "__main__":
logger = CrossPlatformLogger().logger
logger.info("这是一条info日志(包含中文测试)")
try:
1 / 0
except Exception as e:
logger.error("除零错误示例", exc_info=True)