feat:[FL-212][任务监控页面支持查看执行日志]

- 后端添加任务日志存储和查询API
  - 新增 /api/v1/admin/task-logs 端点支持上传、获取和列出任务日志
  - 日志存储到MinIO,路径格式: logs/YYYY/MM/DD/{task_id}.log
  - 新增 task_log_service 处理MinIO存储交互
  - 新增 task_log schema 定义API请求响应格式

- 前端任务监控页面添加查看日志功能
  - 在任务表格和卡片视图中添加"查看日志"按钮
  - 点击按钮打开模态框显示任务执行日志
  - 支持桌面端表格和移动端卡片两种视图

- 新增单元测试验证日志路径生成和错误处理

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
chengkai3
2026-06-28 15:30:51 +08:00
parent f210c029b6
commit cc988abdac
6 changed files with 455 additions and 1 deletions
+64
View File
@@ -0,0 +1,64 @@
"""
Basic unit tests for task log service.
"""
from __future__ import annotations
import pytest
from datetime import datetime, timezone
from unittest.mock import MagicMock, patch
from app.services.task_log_service import (
TaskLogServiceError,
TaskLogNotFoundError,
_get_log_path,
upload_task_log,
get_task_log,
)
def test_get_log_path_with_timestamp():
"""Test log path generation with specific timestamp"""
timestamp = datetime(2026, 6, 28, 12, 30, 45, tzinfo=timezone.utc)
task_id = "test-task-123"
result = _get_log_path(task_id, timestamp)
assert result == "logs/2026/06/28/test-task-123.log"
def test_get_log_path_without_timestamp():
"""Test log path generation with current timestamp"""
task_id = "test-task-456"
result = _get_log_path(task_id)
# Should contain the task_id and follow the pattern
assert task_id in result
assert result.startswith("logs/")
assert result.endswith(f"/{task_id}.log")
@patch("app.services.task_log_service.get_settings")
def test_upload_task_log_minio_disabled(mock_get_settings):
"""Test upload fails when MinIO is disabled"""
mock_settings = MagicMock()
mock_settings.minio_enabled = False
mock_get_settings.return_value = mock_settings
with pytest.raises(TaskLogServiceError) as exc_info:
upload_task_log("task-123", "log content")
assert "MinIO storage is not enabled" in str(exc_info.value)
@patch("app.services.task_log_service.get_settings")
def test_get_task_log_minio_disabled(mock_get_settings):
"""Test retrieval fails when MinIO is disabled"""
mock_settings = MagicMock()
mock_settings.minio_enabled = False
mock_get_settings.return_value = mock_settings
with pytest.raises(TaskLogServiceError) as exc_info:
get_task_log("task-123")
assert "MinIO storage is not enabled" in str(exc_info.value)