logging usage

This commit is contained in:
redshift
2026-03-13 12:40:21 +00:00
parent b75b093ce6
commit 7e1bd78ffe
+99
View File
@@ -242,6 +242,78 @@ type UsageData = {
satsCost: number;
};
type UsageTrackingEntry = UsageData & {
id: string;
timestamp: number;
modelId: string;
baseUrl: string;
requestId: string;
client?: string;
sessionId?: string;
tags?: string[];
};
function extractUsageFromResponseBody(body: unknown): UsageData | null {
if (!body || typeof body !== "object") return null;
const usage = (body as { usage?: Record<string, unknown> }).usage;
if (!usage || typeof usage !== "object") return null;
const promptTokens = Number(usage.prompt_tokens ?? 0);
const completionTokens = Number(usage.completion_tokens ?? 0);
const totalTokens = Number(usage.total_tokens ?? 0);
const costValue = usage.cost;
let cost = 0;
let satsCost = 0;
if (typeof costValue === "number") {
cost = costValue;
} else if (costValue && typeof costValue === "object") {
const costObj = costValue as Record<string, unknown>;
const totalUsd = costObj.total_usd;
const totalMsats = costObj.total_msats;
cost = typeof totalUsd === "number" ? totalUsd : 0;
satsCost = typeof totalMsats === "number" ? totalMsats / 1000 : 0;
}
if (
promptTokens === 0 &&
completionTokens === 0 &&
totalTokens === 0 &&
cost === 0 &&
satsCost === 0
) {
return null;
}
return {
promptTokens,
completionTokens,
totalTokens,
cost,
satsCost,
};
}
function resolveUsageBaseUrl(response: Response, fallback?: string): string {
const responseWithBaseUrl = response as Response & { baseUrl?: unknown };
if (typeof responseWithBaseUrl.baseUrl === "string") {
return responseWithBaseUrl.baseUrl;
}
try {
if (response.url) {
const parsed = new URL(response.url);
return `${parsed.protocol}//${parsed.host}`;
}
} catch {
// Ignore URL parsing failures.
}
return fallback || "unknown";
}
function createSSEParserTransform(
onUsage: (usage: UsageData) => void,
): Transform {
@@ -342,6 +414,13 @@ async function main(): Promise<void> {
const sqliteDriver = createBunSqliteDriver(DB_PATH);
const store = await createSdkStore({ driver: sqliteDriver });
const appendUsageTracking = (entry: UsageTrackingEntry): void => {
const state = store.getState();
const nextUsage = [...(state.usageTracking || []), entry];
state.setUsageTracking(nextUsage);
logger.log("Usage tracking saved:", JSON.stringify(entry));
};
// Create adapters from our SQLite-backed store
const discoveryAdapter = createDiscoveryAdapterFromStore(store);
const providerRegistry = createProviderRegistryFromStore(store);
@@ -792,6 +871,7 @@ async function main(): Promise<void> {
const requestId =
response.headers.get("x-routstr-request-id") || undefined;
logger.log("Request ID, ", requestId, " with path: ", url.pathname);
const usageBaseUrl = resolveUsageBaseUrl(response, forcedProvider);
if (isStream) {
res.statusCode = response.status;
@@ -812,6 +892,14 @@ async function main(): Promise<void> {
res.on("finish", () => {
if (capturedUsage) {
appendUsageTracking({
id: `${requestId || `req-${Date.now()}`}-${modelId}`,
timestamp: Date.now(),
modelId,
baseUrl: usageBaseUrl,
requestId: requestId || "unknown",
...capturedUsage,
});
logger.log(
`Streaming request usage:`,
JSON.stringify(capturedUsage),
@@ -825,6 +913,17 @@ async function main(): Promise<void> {
}
const responseBody = await response.json();
const nonStreamUsage = extractUsageFromResponseBody(responseBody);
if (nonStreamUsage) {
appendUsageTracking({
id: `${requestId || `req-${Date.now()}`}-${modelId}`,
timestamp: Date.now(),
modelId,
baseUrl: usageBaseUrl,
requestId: requestId || "unknown",
...nonStreamUsage,
});
}
res.writeHead(response.status, {
"Content-Type": "application/json",
});