feat(日志): 任务步骤明细表 + 「日志 → 步骤明细」面板(按设备/任务/时间过滤、按运行归组、导出 CSV)
文本日志只能 grep,"这台设备这次运行为什么失败"翻起来很费劲。新增一张 **结构化**的步骤明细表,把"哪一步、什么类型、哪个选择器、结果、耗时"落库。 - core/models.py:新增 task_step_log(run_id/job/设备/step_path/selector/ result/detail/duration_ms),索引 run_id、created_at、(serial,created_at)、 (job_id,created_at); - core/step_log.py(新):**专用写线程 + 有界队列**批量落库——步骤执行是热路径, 任务线程只 put_nowait(实测 9000 次入队 31ms),队列满丢弃并计数,绝不阻塞; 另有保留期清理(默认 14 天,每日 04:13 + 每次启动); - tasks/generic/task.py:_exec_one 记一条(异常=error / handler 返回 False=miss / 未知类型=unknown / 概率未触发=skip);_exec_steps 维护路径栈得到 "2.1.3" 这样的嵌套位置;**单次运行封顶 2000 条**——forever 循环任务否则会写爆表; - 运行上下文 ctx(run_id/job_id/job_name/device_name)由 TaskManager 生成, 经 create_worker(serial, params, ctx=None) 传入 worker(扩展点向后兼容); - 接口:/api/step_logs(过滤+分页)、/runs(按运行归组)、/filters(下拉选项)、 /download(CSV,带 BOM); - 前端:日志页拆成「文件日志 / 步骤明细」子分栏 + static/admin/steplog.js。 红线:新表自动进备份覆盖清单(SUMMARY_TABLES 由元数据派生),已补 TABLE_LABELS 中文标签,导出实测 14 张表、coverage_missing 为空。 文档:DATA_MODEL §2.8/§1、API §10.2、ARCHITECTURE §1.1/§2.2/§3.1、 DEVELOPMENT §5.2 与红线表、DEPLOY §5.2、TASK_DEV §8.3、README。
This commit is contained in:
@@ -115,6 +115,12 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
.log-row{white-space:pre-wrap}
|
||||
.log-cont{color:#8a94a6;padding-left:2.2em} /* 续行(traceback 缩进行):淡色缩进 */
|
||||
.log-hit{background:#fbbf2433} /* 关键字命中高亮 */
|
||||
|
||||
/* 「步骤明细」表格的结果列配色(.log-* 那套作用域在 .log-content 里,表格用这套) */
|
||||
.res-error{color:#dc2626;font-weight:600} /* 异常 / 未知步骤类型 */
|
||||
.res-miss{color:#d97706} /* 未命中 / 超时 / 已达上限 */
|
||||
.res-skip{color:var(--text-light)} /* 概率未触发 */
|
||||
.res-ok{color:#059669}
|
||||
/* 工具栏:控件较多,允许换行;控件本身不参与收缩(否则会被挤成竖排文字) */
|
||||
.log-toolbar{display:flex;flex-wrap:wrap;gap:8px 10px;margin-bottom:12px;align-items:center}
|
||||
.log-toolbar>*{flex:0 0 auto}
|
||||
@@ -784,7 +790,15 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<!-- ========== Tab 4: 日志 ========== -->
|
||||
<div id="tab-logs" class="tab-panel">
|
||||
<div class="page-title">日志查看</div>
|
||||
<div class="page-sub">查看系统各模块运行日志</div>
|
||||
<div class="page-sub">原始文本日志 + 任务步骤明细(结构化,可按设备/任务/时间过滤)</div>
|
||||
|
||||
<div class="sub-tabs">
|
||||
<button class="sub-tab active" data-sub="files" onclick="showSubTab('logs','files')">文件日志</button>
|
||||
<button class="sub-tab" data-sub="steps" onclick="showSubTab('logs','steps')">步骤明细</button>
|
||||
</div>
|
||||
|
||||
<!-- 子分栏 1:文件日志 -->
|
||||
<div class="sub-panel active" id="logs-sub-files">
|
||||
<div class="log-toolbar">
|
||||
<!-- 文件下拉由 /api/logs 返回的清单动态渲染(含 .1/.2 滚动历史与 notify.log) -->
|
||||
<select id="log-file" class="form-control" style="width:auto" onchange="loadLogs()"></select>
|
||||
@@ -815,6 +829,64 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<span class="hint" id="log-hint"></span>
|
||||
</div>
|
||||
<div id="log-content" class="log-content"></div>
|
||||
</div><!-- /logs-sub-files -->
|
||||
|
||||
<!-- 子分栏 2:步骤明细(task_step_log 表,结构化,可按设备/任务/时间/结果过滤) -->
|
||||
<div class="sub-panel" id="logs-sub-steps">
|
||||
<div class="log-toolbar">
|
||||
<select id="sl-device" class="form-control" style="width:auto" onchange="loadStepLogs(true)"></select>
|
||||
<select id="sl-job" class="form-control" style="width:auto" onchange="loadStepLogs(true)"></select>
|
||||
<select id="sl-result" class="form-control" style="width:auto" onchange="loadStepLogs(true)">
|
||||
<option value="">全部结果</option>
|
||||
<option value="error">异常 error</option>
|
||||
<option value="miss">未命中 miss</option>
|
||||
<option value="unknown">未知类型 unknown</option>
|
||||
<option value="skip">概率跳过 skip</option>
|
||||
<option value="ok">正常 ok</option>
|
||||
<option value="cap">已截断 cap</option>
|
||||
</select>
|
||||
<input id="sl-q" class="form-control" style="width:170px" placeholder="关键字(步骤名/选择器/详情)"
|
||||
onkeydown="if(event.key==='Enter')loadStepLogs(true)">
|
||||
<input id="sl-since" type="datetime-local" class="form-control" style="width:auto" onchange="loadStepLogs(true)">
|
||||
<span class="text-muted">~</span>
|
||||
<input id="sl-until" type="datetime-local" class="form-control" style="width:auto" onchange="loadStepLogs(true)">
|
||||
<select id="sl-limit" class="form-control" style="width:auto" onchange="loadStepLogs(true)">
|
||||
<option value="100">每页 100</option>
|
||||
<option value="200" selected>每页 200</option>
|
||||
<option value="500">每页 500</option>
|
||||
</select>
|
||||
<button class="btn" onclick="loadStepLogs(true)">刷新</button>
|
||||
<button class="btn" onclick="downloadStepLogs()" title="导出当前筛选结果(CSV)">导出 CSV</button>
|
||||
<button class="btn" onclick="resetStepFilters()">重置</button>
|
||||
<span class="hint" id="sl-hint"></span>
|
||||
</div>
|
||||
<div class="hint" id="sl-note"></div>
|
||||
|
||||
<details id="sl-runs-box" style="margin:10px 0">
|
||||
<summary style="cursor:pointer;font-size:13px" id="sl-runs-summary">最近运行概览</summary>
|
||||
<table class="table" style="margin-top:8px">
|
||||
<thead><tr>
|
||||
<th style="width:150px">开始</th><th style="width:110px">设备</th><th>任务</th>
|
||||
<th style="width:70px">步骤数</th><th style="width:80px">失败</th><th style="width:70px"></th>
|
||||
</tr></thead>
|
||||
<tbody id="sl-runs-body"></tbody>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
<table class="table">
|
||||
<thead><tr>
|
||||
<th style="width:145px">时间</th><th style="width:105px">设备</th><th style="width:150px">任务</th>
|
||||
<th style="width:60px">步骤</th><th>标签</th><th style="width:95px">类型</th>
|
||||
<th style="width:75px">结果</th><th style="width:65px">耗时</th><th>详情</th>
|
||||
</tr></thead>
|
||||
<tbody id="sl-body"></tbody>
|
||||
</table>
|
||||
<div class="toolbar" style="margin-top:10px">
|
||||
<button class="btn" id="sl-prev" onclick="stepLogPage(-1)">上一页</button>
|
||||
<span class="hint" id="sl-page"></span>
|
||||
<button class="btn" id="sl-next" onclick="stepLogPage(1)">下一页</button>
|
||||
</div>
|
||||
</div><!-- /logs-sub-steps -->
|
||||
</div>
|
||||
|
||||
<!-- ========== Tab 5: 用户 ========== -->
|
||||
@@ -1284,5 +1356,6 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<script src="/static/admin/taskgen.js"></script>
|
||||
<script src="/static/admin/system.js"></script>
|
||||
<script src="/static/admin/notify.js"></script>
|
||||
<script src="/static/admin/steplog.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user