Files
insar-management-system-v2/docs/archive/LOG_MANAGEMENT_ANALYSIS_2026-03-05.md
T

12 KiB
Raw Blame History

系统日志管理分析与优化方案(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 格式)

内容示例

{
  "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

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)

使用方式

# 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

# 修改前
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

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()

添加到定时任务

# 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()

实施步骤

第一步:创建日志目录结构

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

第二步:移动现有日志

# 移动 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

# 日志文件
logs/
*.log
*.log.*

# 但保留日志目录结构
!logs/.gitkeep
!logs/app/.gitkeep
!logs/tasks/.gitkeep

第六步:添加日志清理

创建 scripts/cleanup_logs.py,配置定时清理。


推荐配置

日志级别

# 开发环境
LOG_LEVEL = "DEBUG"

# 生产环境
LOG_LEVEL = "INFO"

# 错误追踪
ERROR_LOG_LEVEL = "ERROR"

日志轮转

# 按大小轮转
maxBytes = 10 * 1024 * 1024  # 10MB
backupCount = 5  # 保留 5 个备份

# 按时间轮转
when = "midnight"  # 每天午夜轮转
interval = 1  # 每 1 天
backupCount = 30  # 保留 30 天

日志保留

# 应用日志: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. 添加日志清理脚本

还是你想先看看这个方案,再决定是否实施?