✨ feat(database): 完善请求日志体系并为全表补充时间字段

- request_log 新增 user_agent 列(含旧表 ALTER 迁移)及 ip/status 索引,记录解码后的明文 query(含 key,不脱敏)
- 请求日志批量写入改为多值 INSERT 单次往返,替代事务逐条 Exec
- 新增按本地时区分天聚合查询,状态页展示今日请求量与近 7 天请求趋势(峰值日高亮)
- 新增 TZ 时区支持:.env 配置 TZ 后日志时间戳与状态页全部时间统一生效,二进制内嵌 tzdata 保证容器可用
- 五张表统一补齐 created_at/updated_at 字段,启动时自动补列并按业务时间回填旧行
- device_pool 的 device_header 增加唯一约束;audio_cache 写入改为 UPSERT 修复同 key 重复报错
- 状态页"最近请求"新增 UA 列与限流状态显示;config.yaml 暴露 rate_limit_qps 配置并默认启用请求日志
- deploy.sh 同名版本默认拒绝覆盖,新增 --force/-f 参数显式允许覆盖
This commit is contained in:
chenxin committed 2026-10-09 22:12:17 +08:00
1 parent 1a4997e031
commit e3d96ca637
13 files changed
+288 -55

No files matched your search

+17 -1
View File
@@ -186,6 +186,12 @@
.strack { height: 5px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
.sfill { display: block; height: 100%; border-radius: inherit; background: var(--accent); width: 0; transition: width 0.7s cubic-bezier(0.22, 0.61, 0.36, 1); }
.sval { font-size: 12px; font-weight: 600; color: var(--ink-2); text-align: right; }
/* 每日请求行:结构同 srow,宽度服务端算好,不参与 .srow 的 JS 归一化 */
.drows { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); display: flex; flex-direction: column; gap: 7px; }
.drow { display: grid; grid-template-columns: 44px 1fr 52px; gap: 8px; align-items: center; }
.dlabel { font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.dval { font-size: 12px; font-weight: 600; color: var(--ink-2); text-align: right; }
.drow.is-max .dlabel, .drow.is-max .dval { color: var(--accent); }
/* ── 最近请求表 ─────────────────────── */
.req-card { margin-bottom: 14px; overflow: hidden; }
@@ -472,6 +478,7 @@
<div class="hero-meta">
<div class="kv"><span class="k">签名算法</span><span class="v num">{{.Signature}}</span></div>
<div class="kv"><span class="k">启动时间</span><span class="v num">{{.StartTime}}</span></div>
<div class="kv"><span class="k">限流</span><span class="v num">{{.RateLimit}}</span></div>
</div>
</section>
@@ -513,7 +520,7 @@
<span class="kpi-label">请求统计</span>
</div>
<div class="big num" data-count-num="{{.StatTotal}}">{{.StatTotal}}</div>
<div class="big-sub">累计业务请求</div>
<div class="big-sub">累计业务请求 · 今日 <span class="num">{{.TodayCount}}</span> 次</div>
<div class="srows">
<div class="srow" data-count="{{.StatSearch}}"><span class="slabel">搜索</span><span class="strack"><i class="sfill"></i></span><span class="sval num">{{.StatSearch}}</span></div>
<div class="srow" data-count="{{.StatDetail}}"><span class="slabel">详情</span><span class="strack"><i class="sfill"></i></span><span class="sval num">{{.StatDetail}}</span></div>
@@ -524,6 +531,13 @@
<div class="srow" data-count="{{.StatVideo}}"><span class="slabel">视频</span><span class="strack"><i class="sfill"></i></span><span class="sval num">{{.StatVideo}}</span></div>
<div class="srow" data-count="{{.StatCategory}}"><span class="slabel">分类</span><span class="strack"><i class="sfill"></i></span><span class="sval num">{{.StatCategory}}</span></div>
</div>
{{if .DailyStats}}
<div class="drows">
{{range .DailyStats}}
<div class="drow{{if .MaxCount}} is-max{{end}}"><span class="dlabel">{{.Day}}</span><span class="strack"><i class="sfill" style="width: {{.Pct}}%"></i></span><span class="dval num">{{.Count}}</span></div>
{{end}}
</div>
{{end}}
</section>
<section class="card kpi">
@@ -553,6 +567,7 @@
<th>方法</th>
<th>路径</th>
<th>IP</th>
<th>UA</th>
<th>状态</th>
<th class="r">耗时</th>
</tr>
@@ -564,6 +579,7 @@
<td><span class="mth">{{.Method}}</span></td>
<td class="code path-cell" title="{{.Path}}">{{.Path}}{{if .Query}} <span class="q">?{{.Query}}</span>{{end}}</td>
<td class="code">{{.IP}}</td>
<td class="code" title="{{.UA}}">{{.UA}}</td>
<td><span class="stc {{if .IsErr}}stc-err{{else}}stc-ok{{end}}"><i aria-hidden="true"></i>{{.Status}}</span></td>
<td class="r num">{{.Duration}}</td>
</tr>