diff --git a/CHANGELOG.md b/CHANGELOG.md index 112f70f..4d91900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,11 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) ยท semantic ver ### Changed +- **fix(logs):** the console request line now tags a skipped conversion as + `savings:skip()` instead of a bare reason word, so skip reasons are + greppable in `omniglyph` stdout and `wrangler tail`. Extracted to a pure + `skipReasonTag` helper shared by the Node and Worker hosts. + - **perf(render):** harden the rendered-page LRU with canonical full SHA-256 keys, race-safe byte accounting, smaller Worker defaults, runtime budget control and cache-pressure counters in `/proxy-stats`. (thanks diff --git a/src/log-tags.ts b/src/log-tags.ts new file mode 100644 index 0000000..b0eb714 --- /dev/null +++ b/src/log-tags.ts @@ -0,0 +1,8 @@ +/** Console request-log formatting shared by the Node and Worker hosts. */ + +/** Tag a non-compressed outcome's skip reason for the stdout / `wrangler tail` + * request line. Empty string when there is no reason, so the caller can append + * it unconditionally without a spurious `savings:skip()`. */ +export function skipReasonTag(reason: string | undefined): string { + return reason ? `savings:skip(${reason})` : ''; +} diff --git a/src/node.ts b/src/node.ts index cd7380b..54d85a4 100644 --- a/src/node.ts +++ b/src/node.ts @@ -19,6 +19,7 @@ import { } from './core/safety-policy.js'; import type { TransformOptions } from './core/transform.js'; import { resolveOpenAIApiKey } from './node-auth.js'; +import { skipReasonTag } from './log-tags.js'; import { parseExportArgv, runExportCore, @@ -1018,7 +1019,7 @@ async function main(): Promise { const extraTag = extra.length > 0 ? ` (${extra.join(' ')})` : ''; const tag = e.info?.compressed ? `compressed ${e.info.origChars}ch โ†’ ${e.info.imageCount}img/${e.info.imageBytes}B${extraTag}` - : (e.info?.reason ?? ''); + : skipReasonTag(e.info?.reason); const cacheRead = e.usage?.cache_read_input_tokens ?? 0; const inputTokens = e.usage?.input_tokens ?? 0; const usageTag = diff --git a/src/worker.ts b/src/worker.ts index dc29cee..6a4ce34 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -19,6 +19,7 @@ import { import type { TransformOptions } from './core/transform.js'; import { toTrackEvent, JsonLogTracker, noopTracker, type Tracker } from './core/tracker.js'; import { setRenderCacheMaxBytes } from './core/render-cache.js'; +import { skipReasonTag } from './log-tags.js'; export interface Env { /** Optional single upstream base for every API family. Family-specific env vars override it. */ @@ -151,7 +152,7 @@ export default { // shows up in `wrangler tail`). const tag = e.info?.compressed ? `compressed ${e.info.origChars}ch โ†’ ${e.info.imageCount}img/${e.info.imageBytes}B` - : (e.info?.reason ?? ''); + : skipReasonTag(e.info?.reason); const cacheRead = e.usage?.cache_read_input_tokens ?? 0; console.log(`${e.method} ${e.path} โ†’ ${e.status} (${e.durationMs}ms) ${tag} cache_read=${cacheRead}`); diff --git a/tests/log-tags.test.ts b/tests/log-tags.test.ts new file mode 100644 index 0000000..d495313 --- /dev/null +++ b/tests/log-tags.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from 'vitest'; +import { skipReasonTag } from '../src/log-tags.js'; + +/** The console request-log line tags a non-compressed outcome so skip reasons + * are greppable in `omniglyph` stdout / `wrangler tail` (e.g. savings:skip(not_profitable)). */ +describe('skipReasonTag', () => { + it('wraps a skip reason as savings:skip()', () => { + expect(skipReasonTag('not_profitable')).toBe('savings:skip(not_profitable)'); + expect(skipReasonTag('below_threshold')).toBe('savings:skip(below_threshold)'); + }); + + it('is empty when there is no reason (no spurious tag)', () => { + expect(skipReasonTag(undefined)).toBe(''); + expect(skipReasonTag('')).toBe(''); + }); +});