Skip to content

Commit 8c8a264

Browse files
Merge pull request #1472 from corbitsdev/cl-10759-audit-nits-batch
chore(audit): keep only the pricing refresh log
2 parents 918be40 + 5587512 commit 8c8a264

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

‎src/cost/pricing-fetcher.ts‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { mkdir } from "node:fs/promises";
22
import { homedir } from "node:os";
33
import { dirname, join } from "node:path";
44

5+
import { getLogger } from "@intx/log";
56
import { type } from "arktype";
6-
import { SETTINGS_DIR_NAME } from "../branding.js";
7+
import { LOG_NAMESPACE_ROOT, SETTINGS_DIR_NAME } from "../branding.js";
78

89
export interface ModelPricing {
910
inputPricePerToken: number;
@@ -47,6 +48,8 @@ const DEFAULT_ENDPOINT = "https://models.dev/api.json";
4748
const DEFAULT_REFRESH_INTERVAL_MS = 24 * 60 * 60 * 1000;
4849
const DEFAULT_FETCH_TIMEOUT_MS = 5000;
4950

51+
const log = getLogger([LOG_NAMESPACE_ROOT, "cost", "pricing"]);
52+
5053
const modelPricingValidator = type({
5154
inputPricePerToken: "number",
5255
outputPricePerToken: "number",
@@ -288,7 +291,11 @@ export async function loadPricing(
288291
const pricing = await fetchPricing(options);
289292
await writePricingCache(pricing, cachePath);
290293
return pricing;
291-
} catch {
294+
} catch (err) {
295+
// One debug line keeps a failed refresh observable while stale cache carries on.
296+
log.debug("pricing refresh failed, keeping cached pricing: {error}", {
297+
error: err instanceof Error ? err.message : String(err),
298+
});
292299
return readPricingCache(cachePath);
293300
}
294301
}

‎src/pricing-fetcher.test.ts‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { defined } from "../testkit/defined.js";
22
import { describe, test, expect } from "bun:test";
33
import { isAbsolute, join } from "node:path";
4+
import { configureSync, getConfig, resetSync } from "@intx/log";
45
import {
56
parseModelsDevContextWindows,
67
parseModelsDevPricing,
@@ -259,6 +260,43 @@ describe("loadPricing", () => {
259260

260261
expect(result).toBeNull();
261262
});
263+
264+
test("emits a single debug line when refresh fails", async () => {
265+
const records: { level: string; text: string }[] = [];
266+
const previous = getConfig();
267+
configureSync({
268+
reset: true,
269+
sinks: {
270+
test: (record) => {
271+
records.push({
272+
level: record.level,
273+
text: record.message.map(String).join(""),
274+
});
275+
},
276+
},
277+
loggers: [{ category: [], lowestLevel: "debug", sinks: ["test"] }],
278+
});
279+
try {
280+
const failingFetch = (async (): Promise<Response> => {
281+
throw new Error("network error");
282+
}) as unknown as typeof fetch;
283+
const result = await loadPricing({
284+
fetchImpl: failingFetch,
285+
cachePath: "/tmp/nonexistent-pricing-cache-debug.json",
286+
});
287+
expect(result).toBeNull();
288+
const hits = records.filter(
289+
(record) =>
290+
record.level === "debug" &&
291+
record.text.includes("pricing refresh failed"),
292+
);
293+
expect(hits).toHaveLength(1);
294+
expect(hits[0]?.text).toContain("network error");
295+
} finally {
296+
if (previous === null) resetSync();
297+
else configureSync({ ...previous, reset: true });
298+
}
299+
});
262300
});
263301

264302
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)