mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-20 08:57:57 +00:00
feat: record cache hit/miss per request in audit trail and WebUI
- Req: add CacheHit and CacheMiss fields (carrying upstream cache accounting from either prompt_tokens_details.cached_tokens or legacy prompt_cache_hit_tokens) - recordChatUsage (non-streaming): copy cache fields from resp.TokenUsage - pumpStream (streaming): write lastUsage cache fields back onto rec at stream end, so streaming requests carry cache data too - CSV export: add first_byte_ms, cache_hit_tokens, cache_miss_tokens columns alongside the existing latency/prompt/completion - WebUI request-records table: add a Cache column showing hit% per row (green/amber tag with tooltip hit/miss breakdown; em-dash when the upstream reported no cache data)
This commit is contained in:
@ -1971,18 +1971,30 @@
|
||||
const slice = records.slice().reverse().slice(0, 300);
|
||||
el.innerHTML =
|
||||
`<table><tr><th>${t("thTime")}</th><th class="num">${t("thStatus")}</th><th>${t("thKey")}</th><th>${t("thType")}</th><th>${t("thModel")}</th><th>${t("thSrc")}</th>
|
||||
<th class="num">${t("thPrompt")}</th><th class="num">${t("thCompl")}</th><th class="num">${t("thLatMs")}</th></tr>` +
|
||||
<th class="num">${t("thPrompt")}</th><th class="num">${t("thCompl")}</th><th class="num">${t("thCache") || "缓存"}</th><th class="num">${t("thLatMs")}</th></tr>` +
|
||||
slice
|
||||
.map(
|
||||
(r) => `<tr>
|
||||
<td class="t-tag">${fmtTime(r.time)}</td>
|
||||
<td class="num">${r.ok ? `<span class="tag tag-green">${r.status || 200}</span>` : `<span class="tag tag-red" title="${esc(r.error || "")}">${r.status || 500}</span>`}</td>
|
||||
<td>${esc(keyNames[r.key] ? keyNames[r.key] + " · " + r.key : r.key)}</td><td class="t-tag">${esc(r.type)}</td><td>${esc(r.model)}</td><td>${esc(r.source || "")}</td>
|
||||
<td class="num">${fmtTok(r.prompt_tokens)}</td><td class="num">${fmtTok(r.completion_tokens)}</td><td class="num">${fmtMs(r.latency_ms)}</td></tr>`,
|
||||
<td class="num">${fmtTok(r.prompt_tokens)}</td><td class="num">${fmtTok(r.completion_tokens)}</td>
|
||||
<td class="num">${cacheCell(r)}</td>
|
||||
<td class="num">${fmtMs(r.latency_ms)}</td></tr>`,
|
||||
)
|
||||
.join("") +
|
||||
"</table>";
|
||||
}
|
||||
|
||||
// cacheCell renders the per-request cache-hit column: a percentage when
|
||||
// the upstream reported cache accounting, otherwise an em dash.
|
||||
function cacheCell(r) {
|
||||
const hit = r.cache_hit_tokens || 0;
|
||||
if (!hit && !(r.cache_miss_tokens > 0)) return '<span class="muted">—</span>';
|
||||
const prompt = r.prompt_tokens || 0;
|
||||
const pct = prompt > 0 ? Math.round((hit * 100) / prompt) : 0;
|
||||
return `<span class="tag ${pct >= 50 ? "tag-green" : pct > 0 ? "tag-amber" : ""}" title="命中 ${hit} / 未命中 ${r.cache_miss_tokens || 0}">${pct}%</span>`;
|
||||
}
|
||||
function showModelConfig(srcName, model) {
|
||||
const el = $("#conncfg");
|
||||
if (!el) return;
|
||||
|
||||
Reference in New Issue
Block a user