Show SPA e621 request times in the status pill
- New e621 metrics store tracks request count, cumulative time and the last request (path + duration) for the session - The e621 client measures each request around fetch and JSON parsing - Status pill appends a teal 'e621: <total>' segment with a tooltip showing request count and the last request; a server-side e621 time is shown separately if the backend ever reports one
This commit is contained in:
@@ -2,6 +2,7 @@ import { Laptop, Monitor, Terminal, type LucideIcon } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/cn";
|
||||
import type { SystemStatus } from "@/lib/types";
|
||||
import { useE621Metrics } from "@/store/e621Metrics";
|
||||
|
||||
const osIcons: Record<string, LucideIcon> = {
|
||||
linux: Terminal,
|
||||
@@ -10,10 +11,16 @@ const osIcons: Record<string, LucideIcon> = {
|
||||
};
|
||||
|
||||
function formatMs(value: number): string {
|
||||
return value >= 100 ? `${Math.round(value)}ms` : `${value.toFixed(1)}ms`;
|
||||
if (value >= 1000) return `${(value / 1000).toFixed(1)}s`;
|
||||
if (value >= 100) return `${Math.round(value)}ms`;
|
||||
return `${value.toFixed(1)}ms`;
|
||||
}
|
||||
|
||||
export function StatusPill({ status }: { status?: SystemStatus }) {
|
||||
const requestCount = useE621Metrics((state) => state.requestCount);
|
||||
const totalMs = useE621Metrics((state) => state.totalMs);
|
||||
const last = useE621Metrics((state) => state.last);
|
||||
|
||||
if (!status) return null;
|
||||
const OsIcon = osIcons[status.os.icon] ?? Monitor;
|
||||
|
||||
@@ -37,10 +44,25 @@ export function StatusPill({ status }: { status?: SystemStatus }) {
|
||||
<span>{status.os.name}</span>
|
||||
<span className="text-ctp-surface2">·</span>
|
||||
<span>{formatMs(status.server_time_ms)}</span>
|
||||
{requestCount > 0 ? (
|
||||
<>
|
||||
<span className="text-ctp-surface2">·</span>
|
||||
<span
|
||||
className="text-ctp-teal"
|
||||
title={`${requestCount} e621 request${
|
||||
requestCount === 1 ? "" : "s"
|
||||
} this session · last ${last ? `${formatMs(last.ms)} (${last.path})` : "—"}`}
|
||||
>
|
||||
e621: {formatMs(totalMs)}
|
||||
</span>
|
||||
</>
|
||||
) : null}
|
||||
{status.e621_time_ms !== null ? (
|
||||
<>
|
||||
<span className="text-ctp-surface2">·</span>
|
||||
<span>e621: {formatMs(status.e621_time_ms)}</span>
|
||||
<span title="Server-side e621 time">
|
||||
e621 (server): {formatMs(status.e621_time_ms)}
|
||||
</span>
|
||||
</>
|
||||
) : null}
|
||||
</span>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useE621Metrics } from "@/store/e621Metrics";
|
||||
|
||||
export interface E621Credentials {
|
||||
username: string;
|
||||
api_key: string;
|
||||
base_url: string;
|
||||
configured: boolean;
|
||||
}
|
||||
|
||||
export interface E621User {
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -141,6 +142,8 @@ export function e621Request<T>(
|
||||
);
|
||||
}
|
||||
|
||||
const startedAt = performance.now();
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: options.method ?? "GET",
|
||||
headers,
|
||||
@@ -161,6 +164,11 @@ export function e621Request<T>(
|
||||
return undefined as T;
|
||||
}
|
||||
return (await response.json()) as T;
|
||||
} finally {
|
||||
useE621Metrics
|
||||
.getState()
|
||||
.record(path, performance.now() - startedAt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
export interface E621RequestSample {
|
||||
path: string;
|
||||
ms: number;
|
||||
at: number;
|
||||
}
|
||||
|
||||
interface E621MetricsState {
|
||||
requestCount: number;
|
||||
totalMs: number;
|
||||
last: E621RequestSample | null;
|
||||
record: (path: string, ms: number) => void;
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
/** Rolling e621 request timings for the current SPA session. */
|
||||
export const useE621Metrics = create<E621MetricsState>((set) => ({
|
||||
requestCount: 0,
|
||||
totalMs: 0,
|
||||
last: null,
|
||||
|
||||
record: (path, ms) =>
|
||||
set((state) => ({
|
||||
requestCount: state.requestCount + 1,
|
||||
totalMs: state.totalMs + ms,
|
||||
last: { path, ms, at: Date.now() },
|
||||
})),
|
||||
|
||||
reset: () => set({ requestCount: 0, totalMs: 0, last: null }),
|
||||
}));
|
||||
Reference in New Issue
Block a user