fix(usage): synchronize Keeper metrics and improve detail refresh
- Align TPS and token normalization with Keeper - Add Redis usage queue batch pulling with HTTP fallback - Prevent cache and invalid token double counting - Refresh usage details immediately after new records arrive
This commit is contained in:
1 parent
19a9b4fc09
commit
32b55920af
9 files changed
+1188
-185
No files matched your search
+2
-2
@@ -414,7 +414,7 @@ export const jaOverrides = {
|
||||
'usage.stat.averageLatency': '平均レイテンシ',
|
||||
'usage.stat.tps': 'TPS',
|
||||
'usage.stat.performanceMeta': '有効サンプル {samples} 件 · RPM {rpm}',
|
||||
'usage.stat.performanceMetaTitle': 'TPS {tps}、有効サンプル {samples} 件、RPM {rpm}、平均レイテンシ {latency} ms',
|
||||
'usage.stat.performanceMetaTitle': 'TPS {tps}(総レイテンシで加重)、有効サンプル {samples} 件、RPM {rpm}、平均レイテンシ {latency} ms',
|
||||
'usage.stat.cacheHitRate': 'キャッシュヒット率',
|
||||
'usage.stat.cacheHitMeta': 'キャッシュ読取 {hit} · 入力 {input}',
|
||||
'usage.stat.cacheHitMetaTitle': 'キャッシュヒット率 {rate}%、読取 {hit} Token、入力 {input} Token',
|
||||
@@ -498,7 +498,7 @@ export const jaOverrides = {
|
||||
'usage.column.cache': 'キャッシュ',
|
||||
'usage.column.cacheRate': 'キャッシュ率',
|
||||
'usage.column.total': '合計',
|
||||
'usage.column.speed': '生成速度',
|
||||
'usage.column.speed': '出力速度',
|
||||
'usage.key.noRemark': 'メモなし',
|
||||
'usage.previous': '前へ',
|
||||
'usage.next': '次へ',
|
||||
|
||||
@@ -401,7 +401,7 @@ export const en: Record<MessageKey, string> = {
|
||||
'usage.stat.averageLatency': 'Average Latency',
|
||||
'usage.stat.tps': 'TPS',
|
||||
'usage.stat.performanceMeta': '{samples} samples · RPM {rpm}',
|
||||
'usage.stat.performanceMetaTitle': 'TPS {tps}, {samples} valid samples, RPM {rpm}, average latency {latency} ms',
|
||||
'usage.stat.performanceMetaTitle': 'TPS {tps} (weighted by total latency), {samples} valid samples, RPM {rpm}, average latency {latency} ms',
|
||||
'usage.stat.cacheHitRate': 'Cache Hit Rate',
|
||||
'usage.stat.cacheHitMeta': 'Cache read {hit} · Input {input}',
|
||||
'usage.stat.cacheHitMetaTitle': 'Cache hit rate {rate}%, cache read {hit} tokens, input {input} tokens',
|
||||
@@ -486,7 +486,7 @@ export const en: Record<MessageKey, string> = {
|
||||
'usage.column.cache': 'Cache',
|
||||
'usage.column.cacheRate': 'Cache Rate',
|
||||
'usage.column.total': 'Total',
|
||||
'usage.column.speed': 'Generation Speed',
|
||||
'usage.column.speed': 'Output Speed',
|
||||
'usage.key.noRemark': 'No remark',
|
||||
'usage.previous': 'Previous',
|
||||
'usage.next': 'Next',
|
||||
|
||||
@@ -400,7 +400,7 @@ export const zhCN = {
|
||||
'usage.stat.averageLatency': '平均延迟',
|
||||
'usage.stat.tps': 'TPS',
|
||||
'usage.stat.performanceMeta': '{samples} 条有效样本 · RPM {rpm}',
|
||||
'usage.stat.performanceMetaTitle': 'TPS {tps},{samples} 条有效样本,RPM {rpm},平均延迟 {latency} ms',
|
||||
'usage.stat.performanceMetaTitle': 'TPS {tps}(按总延迟加权),{samples} 条有效样本,RPM {rpm},平均延迟 {latency} ms',
|
||||
'usage.stat.cacheHitRate': '缓存命中率',
|
||||
'usage.stat.cacheHitMeta': '缓存读取 {hit} · 输入 {input}',
|
||||
'usage.stat.cacheHitMetaTitle': '缓存命中率 {rate}%,缓存读取 {hit} Token,输入 {input} Token',
|
||||
@@ -485,7 +485,7 @@ export const zhCN = {
|
||||
'usage.column.cache': '缓存',
|
||||
'usage.column.cacheRate': '缓存率',
|
||||
'usage.column.total': '总计',
|
||||
'usage.column.speed': '生成速度',
|
||||
'usage.column.speed': '输出速度',
|
||||
'usage.key.noRemark': '未备注',
|
||||
'usage.previous': '上一页',
|
||||
'usage.next': '下一页',
|
||||
|
||||
@@ -400,9 +400,9 @@ export function UsageRecordsPage() {
|
||||
);
|
||||
|
||||
const loadData = useCallback(
|
||||
(quiet = false) => {
|
||||
(quiet = false, immediate = !quiet) => {
|
||||
if (!quiet) setLoading(true);
|
||||
return schedulerRef.current!.schedule(() => executeLoadData(quiet), !quiet);
|
||||
return schedulerRef.current!.schedule(() => executeLoadData(quiet), immediate);
|
||||
},
|
||||
[executeLoadData],
|
||||
);
|
||||
@@ -419,7 +419,7 @@ export function UsageRecordsPage() {
|
||||
let disposed = false;
|
||||
let unlisten: (() => void) | null = null;
|
||||
const refresh = () => {
|
||||
if (!disposed && !document.hidden) void loadData(true);
|
||||
if (!disposed && !document.hidden) void loadData(true, true);
|
||||
};
|
||||
listen('usage-records-updated', refresh)
|
||||
.then((stop) => {
|
||||
@@ -1440,7 +1440,6 @@ function UsageEventCell({
|
||||
const value = formatGenerationSpeed({
|
||||
outputTokens: record.tokens.output_tokens,
|
||||
latencyMs: record.latency_ms,
|
||||
ttftMs: record.ttft_ms,
|
||||
});
|
||||
return <td className="usage-td-speed align-center" title={value === '—' ? undefined : value}>{value}</td>;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
type GenerationSpeedInput = {
|
||||
outputTokens: number;
|
||||
latencyMs: number;
|
||||
ttftMs: number | null;
|
||||
};
|
||||
|
||||
type CacheReadRateInput = {
|
||||
@@ -12,21 +11,17 @@ type CacheReadRateInput = {
|
||||
export const calculateGenerationSpeed = ({
|
||||
outputTokens,
|
||||
latencyMs,
|
||||
ttftMs,
|
||||
}: GenerationSpeedInput): number | null => {
|
||||
if (
|
||||
!Number.isFinite(outputTokens) ||
|
||||
!Number.isFinite(latencyMs) ||
|
||||
ttftMs === null ||
|
||||
!Number.isFinite(ttftMs) ||
|
||||
outputTokens <= 0 ||
|
||||
ttftMs <= 0 ||
|
||||
latencyMs <= ttftMs
|
||||
latencyMs <= 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const speed = outputTokens / ((latencyMs - ttftMs) / 1_000);
|
||||
const speed = outputTokens / (latencyMs / 1_000);
|
||||
return Number.isFinite(speed) && speed > 0 ? speed : null;
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user