feat(monitor): 运行历史要写清楚失败原因,不能只写「退出码 1」
用户的要求:运行历史的说明要写清楚。现在确实写不清楚 —— 抖音那次失败,运行历史里 只有一句 `Crawler exited with code 1`,而真正的报错 `DataFetchError: account blocked` 埋在子进程的 stderr 里,谁也看不到。 那两者本来是断开的两条路:子进程的输出只流向日志 WebSocket(前端 Terminal 看得到), 而监控层调 run_and_wait() 只拿得到一个退出码。 * crawler_manager 在 _push_log() 里留一份输出尾巴(80 行,每次 start 清空)—— 那是所有输出的唯一出口,挂这儿不会漏。新增 get_output_tail()。 * ingest 新增 diagnose_failure():倒着找第一行像异常的行(traceback 的末行), 认不出就退回最后一行;管理器自己补的「Crawler exited with code」不是原因,排除掉。 * describe_exit_code() 接受这个原因并附在消息里;失败事件的标题也带上,这样企业微信 通知和事件流不用翻日志就能看懂。 * runner 把尾巴交给 ingest;「超时/没起来」那条分支同样带上原因 —— -1 同时代表两种 情况,而要查的东西完全不同。 * 运行历史那一格是截断的(240px),而失败原因现在有一整行 —— 补上 title 悬停显示, 并放宽到 320px。没有悬停提示等于把最要紧的半句藏起来。 测试 +5:能挑出异常行、不会把管理器自己的话当成原因、没有输出时不报错、认不出时退回 最后一行、以及失败运行同时记下退出码与真因(含事件标题)。
This commit is contained in:
+11
-2
@@ -40,7 +40,7 @@ from ..schemas import (
|
||||
from ..services import crawler_manager
|
||||
from . import adapters, app_settings, covers, notify
|
||||
from .db import get_session
|
||||
from .ingest import IngestResult, ingest_run
|
||||
from .ingest import IngestResult, diagnose_failure, ingest_run
|
||||
from .models import (
|
||||
MODE_CREATOR,
|
||||
RUN_FAILED,
|
||||
@@ -259,11 +259,20 @@ async def execute_task(task_id: int, trigger: str = "manual") -> IngestResult:
|
||||
run.finished_at = get_current_timestamp()
|
||||
run.exit_code = exit_code
|
||||
run.error_message = "Run was killed by timeout or failed to start"
|
||||
# -1 同时代表「超时」和「根本没起来」,两者要查的东西完全不同。输出尾巴里
|
||||
# 有异常就带上它,否则运行历史里只能看到这句没有信息量的话。
|
||||
cause = diagnose_failure(crawler_manager.get_output_tail())
|
||||
if cause:
|
||||
run.error_message = f"{run.error_message};原因:{cause}"
|
||||
result = IngestResult(status=RUN_TIMEOUT, error=run.error_message)
|
||||
else:
|
||||
run.exit_code = exit_code
|
||||
run.finished_at = get_current_timestamp()
|
||||
result = await ingest_run(session, run, task, out_dir)
|
||||
# 把爬虫输出的尾巴交给 ingest:退出码本身说明不了问题,运行历史里要显示的
|
||||
# 是真正的报错(比如抖音的 DataFetchError: account blocked)。
|
||||
result = await ingest_run(
|
||||
session, run, task, out_dir, output_tail=crawler_manager.get_output_tail()
|
||||
)
|
||||
|
||||
# A run that authenticated fine is the only useful signal that the
|
||||
# stored cookie still works.
|
||||
|
||||
Reference in New Issue
Block a user