ui-svelte: fix histogram calculation (#695)

- Fix the histogram calculation to use server provided generation
tokens/second.
- Move histogram to Activities page where it can exist with the rest of
the token metrics

Fixes #681
This commit is contained in:
Benson Wong
2026-04-22 23:42:39 -07:00
committed by GitHub
parent 5938dbee8f
commit 0b31ccacc1
11 changed files with 365 additions and 238 deletions
+35 -29
View File
@@ -1,5 +1,6 @@
<script lang="ts">
import { metrics, getCapture } from "../stores/api";
import ActivityStats from "../components/ActivityStats.svelte";
import Tooltip from "../components/Tooltip.svelte";
import CaptureDialog from "../components/CaptureDialog.svelte";
import type { ReqRespCapture } from "../lib/types";
@@ -63,33 +64,38 @@
<div class="p-2">
<h1 class="text-2xl font-bold">Activity</h1>
<div class="mt-4 mb-4">
<ActivityStats />
</div>
{#if $metrics.length === 0}
<div class="text-center py-8">
<p class="text-gray-600">No metrics data available</p>
</div>
{:else}
<div class="card overflow-auto">
<table class="min-w-full divide-y">
<thead class="border-gray-200 dark:border-white/10">
<tr class="text-left text-xs uppercase tracking-wider">
<th class="px-6 py-3">ID</th>
<th class="px-6 py-3">Time</th>
<th class="px-6 py-3">Model</th>
<th class="px-6 py-3">
Cached <Tooltip content="prompt tokens from cache" />
</th>
<th class="px-6 py-3">
Prompt <Tooltip content="new prompt tokens processed" />
</th>
<th class="px-6 py-3">Generated</th>
<th class="px-6 py-3">Prompt Processing</th>
<th class="px-6 py-3">Generation Speed</th>
<th class="px-6 py-3">Duration</th>
<th class="px-6 py-3">Capture</th>
<div class="card overflow-auto">
<table class="min-w-full divide-y">
<thead class="border-gray-200 dark:border-white/10">
<tr class="text-left text-xs uppercase tracking-wider">
<th class="px-6 py-3">ID</th>
<th class="px-6 py-3">Time</th>
<th class="px-6 py-3">Model</th>
<th class="px-6 py-3">
Cached <Tooltip content="prompt tokens from cache" />
</th>
<th class="px-6 py-3">
Prompt <Tooltip content="new prompt tokens processed" />
</th>
<th class="px-6 py-3">Generated</th>
<th class="px-6 py-3">Prompt Processing</th>
<th class="px-6 py-3">Generation Speed</th>
<th class="px-6 py-3">Duration</th>
<th class="px-6 py-3">Capture</th>
</tr>
</thead>
<tbody class="divide-y">
{#if sortedMetrics.length === 0}
<tr>
<td colspan="10" class="px-6 py-8 text-center text-sm text-gray-500 dark:text-gray-400">
No activity recorded
</td>
</tr>
</thead>
<tbody class="divide-y">
{:else}
{#each sortedMetrics as metric (metric.id)}
<tr class="whitespace-nowrap text-sm border-gray-200 dark:border-white/10">
<td class="px-4 py-4">{metric.id + 1}</td>
@@ -116,10 +122,10 @@
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
{/if}
</tbody>
</table>
</div>
</div>
<CaptureDialog capture={selectedCapture} open={dialogOpen} onclose={closeDialog} />
+1 -9
View File
@@ -2,7 +2,6 @@
import { isNarrow } from "../stores/theme";
import { upstreamLogs } from "../stores/api";
import ModelsPanel from "../components/ModelsPanel.svelte";
import StatsPanel from "../components/StatsPanel.svelte";
import LogPanel from "../components/LogPanel.svelte";
import ResizablePanels from "../components/ResizablePanels.svelte";
@@ -14,13 +13,6 @@
<ModelsPanel />
{/snippet}
{#snippet rightPanel()}
<div class="flex flex-col h-full space-y-4">
{#if direction === "horizontal"}
<StatsPanel />
{/if}
<div class="flex-1 min-h-0">
<LogPanel id="modelsupstream" title="Upstream Logs" logData={$upstreamLogs} />
</div>
</div>
<LogPanel id="modelsupstream" title="Upstream Logs" logData={$upstreamLogs} />
{/snippet}
</ResizablePanels>