feat: expose usage stats via shared runtime StatsCache

This commit is contained in:
c4ch3c4d3
2026-08-14 12:54:34 -06:00
parent 4727bdcf46
commit f1a5f89e0f
+21
View File
@@ -1,6 +1,8 @@
import { EventFeed } from "./event-feed"; import { EventFeed } from "./event-feed";
import { InflightTracker } from "./inflight-tracker"; import { InflightTracker } from "./inflight-tracker";
import { MetricsPoller } from "./metrics-poller"; import { MetricsPoller } from "./metrics-poller";
import { StatsCache } from "./stats-cache";
import { type UsageStats } from "./stats";
import { type LlamaSwapConfig } from "./util"; import { type LlamaSwapConfig } from "./util";
class Runtime { class Runtime {
@@ -9,6 +11,8 @@ class Runtime {
private cfg?: LlamaSwapConfig; private cfg?: LlamaSwapConfig;
private feed?: EventFeed; private feed?: EventFeed;
private poller?: MetricsPoller; private poller?: MetricsPoller;
private statsCache?: StatsCache;
private statsUnsub?: () => void;
private listeners = new Set<() => void>(); private listeners = new Set<() => void>();
ensureConnections(cfg: LlamaSwapConfig): void { ensureConnections(cfg: LlamaSwapConfig): void {
@@ -18,11 +22,15 @@ class Runtime {
this.poller?.stop(); this.poller?.stop();
this.feed = undefined; this.feed = undefined;
this.poller = undefined; this.poller = undefined;
this.statsUnsub?.();
this.statsCache = undefined;
this.statsUnsub = undefined;
this.cfg = cfg; this.cfg = cfg;
} }
if (!this.feed) { if (!this.feed) {
this.feed = new EventFeed(cfg, (ev) => { this.feed = new EventFeed(cfg, (ev) => {
this.tracker.apply(ev); this.tracker.apply(ev);
if (ev.type === "activity") this.statsCache?.scheduleRefresh();
this.emit(); this.emit();
}); });
this.feed.setStatusHandler((connected) => { this.feed.setStatusHandler((connected) => {
@@ -36,12 +44,25 @@ class Runtime {
this.poller.on(() => this.emit()); this.poller.on(() => this.emit());
this.poller.start(); this.poller.start();
} }
if (!this.statsCache) {
this.statsCache = new StatsCache(cfg);
this.statsUnsub = this.statsCache.onChange(() => this.emit());
}
} }
get pollerInstance(): MetricsPoller | undefined { get pollerInstance(): MetricsPoller | undefined {
return this.poller; return this.poller;
} }
getStats(modelId: string): UsageStats | undefined {
return this.statsCache?.get(modelId);
}
watchStats(modelId: string): () => void {
this.statsCache?.register(modelId);
return () => this.statsCache?.unregister(modelId);
}
subscribe(listener: () => void): () => void { subscribe(listener: () => void): () => void {
this.listeners.add(listener); this.listeners.add(listener);
return () => { return () => {