chore: initialize insar management system v2

This commit is contained in:
2026-04-14 13:16:01 +08:00
commit ecc72ec9cd
361 changed files with 2142522 additions and 0 deletions
@@ -0,0 +1,510 @@
# 系统日志管理分析与优化方案(2026-03-05)
## 当前日志分布情况
### 1. 根目录日志(❌ 不规范)
```
Z:\Code\Insar_management_system_v2\
├── unpacker_activity.log (34KB) - 解包活动日志
└── unpacker_log.json (8.6KB) - 解包结构化日志
```
**来源**`scripts/unpack_archives.py`
**问题**
- 直接保存在项目根目录,不专业
- 与代码文件混在一起
- 不便于管理和清理
- 可能被误提交到 Git
---
### 2. IDL/ENVI 工作日志
```
backend/runtime/idl_worker/
├── 20260225_022409_dinsar_custom.log
├── 20260225_051527_dinsar_custom.log
├── 20260304_091723_import.log
├── 20260304_091854_import.log
└── dinsar_custom_progress.log
```
**来源**ENVI 工作流执行日志
**状态**:✅ 已规范化(在 `backend/runtime/` 下)
---
### 3. SARscape 工作日志
```
.idl/sarmap/sarscape-3-6_1_0-idl_8_8/
├── hwConfig.log
└── sarscape_work/
├── Process.log
├── Process_20260226165004.log
├── Process_20260226210207.log
└── Process_20260227091802.log
```
**来源**SARscape 软件自动生成
**状态**:✅ 可接受(第三方软件日志)
---
### 4. 应用日志(缺失)
**问题**
- ❌ 没有统一的应用日志目录
- ❌ 没有日志轮转机制
- ❌ 没有日志级别配置
- ❌ 没有结构化日志
---
## 日志用途分析
### unpacker_activity.log
**用途**:记录解包脚本的活动日志(文本格式)
**内容示例**
```
2026-03-04 20:53:15 - INFO - 开始扫描归档文件...
2026-03-04 20:53:15 - INFO - 找到 5 个归档文件
2026-03-04 20:53:16 - INFO - 解包完成: archive1.zip
```
**问题**
- 保存在根目录
- 无日志轮转(会无限增长)
- 无日志级别控制
---
### unpacker_log.json
**用途**:记录解包脚本的结构化日志(JSON 格式)
**内容示例**
```json
{
"timestamp": "2026-03-04T20:53:15",
"level": "INFO",
"message": "解包完成",
"archive": "archive1.zip",
"files_extracted": 123,
"duration_seconds": 5.2
}
```
**问题**
- 保存在根目录
- 与 activity.log 重复
- 无清理机制
---
## 系统中的其他日志
### 1. 数据库日志
- **位置**PostgreSQL 数据目录
- **管理**:由 PostgreSQL 管理
### 2. Nginx 日志
- **位置**`nginx/logs/` (如果配置了)
- **管理**:由 Nginx 管理
### 3. 任务日志
- **位置**:数据库 `system_task` 表的 `logs` 字段
- **管理**:通过 API 查询
### 4. 进度文件
- **位置**`backend/runtime/idl_worker/job_{job_id}_progress.json`
- **管理**:任务完成后自动清理
---
## 日志管理问题
### 问题 1:日志分散
**现状**
- 根目录:unpacker 日志
- backend/runtime/ENVI 日志
- .idl/SARscape 日志
- 数据库:任务日志
**影响**
- 难以统一查看
- 难以统一清理
- 难以统一备份
---
### 问题 2:无日志轮转
**现状**
- unpacker_activity.log 会无限增长
- ENVI 日志会累积(每次执行生成新文件)
**影响**
- 磁盘空间浪费
- 日志文件过大影响性能
---
### 问题 3:无统一日志框架
**现状**
- unpacker 使用自定义日志
- 后端使用 print() 输出
- 没有统一的日志级别
**影响**
- 日志格式不一致
- 难以过滤和搜索
- 难以集成日志分析工具
---
## 优化方案
### 方案 A:统一日志目录结构(推荐)
```
Z:\Code\Insar_management_system_v2\
├── logs/ # 统一日志目录
│ ├── app/ # 应用日志
│ │ ├── backend.log # 后端主日志
│ │ ├── backend.log.1 # 轮转日志
│ │ ├── backend.log.2
│ │ └── ...
│ ├── tasks/ # 任务日志
│ │ ├── envi/ # ENVI 工作流日志
│ │ │ ├── 20260304_091723_import.log
│ │ │ └── ...
│ │ └── unpacker/ # 解包任务日志
│ │ ├── unpacker_20260304.log
│ │ └── ...
│ ├── access/ # 访问日志
│ │ ├── nginx_access.log
│ │ └── api_access.log
│ └── error/ # 错误日志
│ ├── nginx_error.log
│ └── api_error.log
├── backend/
└── frontend/
```
**优点**
- 所有日志集中管理
- 便于备份和清理
- 便于配置 .gitignore
---
### 方案 B:使用 Python logging 模块
**配置文件**`backend/app/logging_config.py`
```python
import logging
import logging.handlers
import os
from pathlib import Path
# 日志根目录
LOG_ROOT = Path(__file__).parent.parent.parent / "logs"
LOG_ROOT.mkdir(exist_ok=True)
# 应用日志目录
APP_LOG_DIR = LOG_ROOT / "app"
APP_LOG_DIR.mkdir(exist_ok=True)
# 任务日志目录
TASK_LOG_DIR = LOG_ROOT / "tasks"
TASK_LOG_DIR.mkdir(exist_ok=True)
# 日志配置
LOGGING_CONFIG = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
"datefmt": "%Y-%m-%d %H:%M:%S",
},
"detailed": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s",
"datefmt": "%Y-%m-%d %H:%M:%S",
},
"json": {
"()": "pythonjsonlogger.jsonlogger.JsonFormatter",
"format": "%(asctime)s %(name)s %(levelname)s %(message)s",
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "INFO",
"formatter": "default",
"stream": "ext://sys.stdout",
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "DEBUG",
"formatter": "detailed",
"filename": str(APP_LOG_DIR / "backend.log"),
"maxBytes": 10 * 1024 * 1024, # 10MB
"backupCount": 5,
"encoding": "utf-8",
},
"error_file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "ERROR",
"formatter": "detailed",
"filename": str(APP_LOG_DIR / "error.log"),
"maxBytes": 10 * 1024 * 1024, # 10MB
"backupCount": 5,
"encoding": "utf-8",
},
},
"loggers": {
"": { # root logger
"level": "INFO",
"handlers": ["console", "file", "error_file"],
},
"uvicorn": {
"level": "INFO",
"handlers": ["console", "file"],
"propagate": False,
},
"sqlalchemy": {
"level": "WARNING",
"handlers": ["file"],
"propagate": False,
},
},
}
def setup_logging():
"""初始化日志配置"""
import logging.config
logging.config.dictConfig(LOGGING_CONFIG)
```
**使用方式**
```python
# backend/app/main.py
from .logging_config import setup_logging
setup_logging()
logger = logging.getLogger(__name__)
@app.on_event("startup")
async def startup_event():
logger.info("应用启动")
```
---
### 方案 C:修复 unpacker 日志位置
**修改文件**`scripts/unpack_archives.py`
```python
# 修改前
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
LOG_FILE = os.path.join(PROJECT_ROOT, "unpacker_log.json")
ACTIVITY_LOG = os.path.join(PROJECT_ROOT, "unpacker_activity.log")
# 修改后
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
LOG_DIR = os.path.join(PROJECT_ROOT, "logs", "tasks", "unpacker")
os.makedirs(LOG_DIR, exist_ok=True)
# 使用日期命名,便于清理
from datetime import datetime
log_date = datetime.now().strftime("%Y%m%d")
LOG_FILE = os.path.join(LOG_DIR, f"unpacker_{log_date}.json")
ACTIVITY_LOG = os.path.join(LOG_DIR, f"unpacker_{log_date}.log")
```
---
### 方案 D:添加日志清理机制
**定期清理脚本**`scripts/cleanup_logs.py`
```python
import os
import time
from pathlib import Path
PROJECT_ROOT = Path(__file__).parent.parent
LOG_ROOT = PROJECT_ROOT / "logs"
# 清理策略
CLEANUP_RULES = {
"logs/app/*.log.*": 30, # 应用日志保留 30 天
"logs/tasks/envi/*.log": 7, # ENVI 日志保留 7 天
"logs/tasks/unpacker/*.log": 7, # 解包日志保留 7 天
}
def cleanup_old_logs():
"""清理过期日志"""
now = time.time()
for pattern, days in CLEANUP_RULES.items():
max_age = days * 86400 # 转换为秒
for log_file in LOG_ROOT.glob(pattern):
if log_file.is_file():
age = now - log_file.stat().st_mtime
if age > max_age:
print(f"删除过期日志: {log_file} (已存在 {age/86400:.1f} 天)")
log_file.unlink()
if __name__ == "__main__":
cleanup_old_logs()
```
**添加到定时任务**
```python
# backend/app/main.py
from apscheduler.schedulers.asyncio import AsyncIOScheduler
scheduler = AsyncIOScheduler()
@app.on_event("startup")
async def startup_event():
# 每天凌晨 3 点清理日志
scheduler.add_job(cleanup_old_logs, "cron", hour=3, minute=0)
scheduler.start()
```
---
## 实施步骤
### 第一步:创建日志目录结构
```bash
cd Z:\Code\Insar_management_system_v2
mkdir -p logs/app
mkdir -p logs/tasks/envi
mkdir -p logs/tasks/unpacker
mkdir -p logs/access
mkdir -p logs/error
```
### 第二步:移动现有日志
```bash
# 移动 unpacker 日志
mv unpacker_activity.log logs/tasks/unpacker/unpacker_20260304.log
mv unpacker_log.json logs/tasks/unpacker/unpacker_20260304.json
# 移动 ENVI 日志(已经在正确位置)
# backend/runtime/idl_worker/ 保持不变
```
### 第三步:修改 unpacker 脚本
修改 `scripts/unpack_archives.py`,使用新的日志路径。
### 第四步:配置 Python logging
创建 `backend/app/logging_config.py`,配置统一日志。
### 第五步:更新 .gitignore
```gitignore
# 日志文件
logs/
*.log
*.log.*
# 但保留日志目录结构
!logs/.gitkeep
!logs/app/.gitkeep
!logs/tasks/.gitkeep
```
### 第六步:添加日志清理
创建 `scripts/cleanup_logs.py`,配置定时清理。
---
## 推荐配置
### 日志级别
```python
# 开发环境
LOG_LEVEL = "DEBUG"
# 生产环境
LOG_LEVEL = "INFO"
# 错误追踪
ERROR_LOG_LEVEL = "ERROR"
```
### 日志轮转
```python
# 按大小轮转
maxBytes = 10 * 1024 * 1024 # 10MB
backupCount = 5 # 保留 5 个备份
# 按时间轮转
when = "midnight" # 每天午夜轮转
interval = 1 # 每 1 天
backupCount = 30 # 保留 30 天
```
### 日志保留
```python
# 应用日志:30 天
# 任务日志:7 天
# 错误日志:90 天
# 访问日志:30 天
```
---
## 总结
### 当前问题
1. ❌ unpacker 日志保存在根目录(不专业)
2. ❌ 日志分散在多个位置
3. ❌ 无统一日志框架
4. ❌ 无日志轮转和清理机制
### 推荐方案
1. ✅ 创建统一的 `logs/` 目录
2. ✅ 使用 Python logging 模块
3. ✅ 配置日志轮转(按大小或时间)
4. ✅ 添加定时清理机制
5. ✅ 更新 .gitignore
### 优先级
- **P0(立即)**:移动 unpacker 日志到 logs/ 目录
- **P1(本周)**:配置 Python logging 模块
- **P2(两周)**:添加日志轮转和清理
- **P3(一个月)**:集成日志分析工具(如 ELK)
---
## 下一步
需要我开始实施日志管理优化吗?我可以:
1. 创建日志目录结构
2. 修改 unpacker 脚本
3. 配置 Python logging
4. 添加日志清理脚本
还是你想先看看这个方案,再决定是否实施?