From 04a336f7dfc4e1623dabb3eca7be8612cb5e5cc2 Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Mon, 27 Apr 2026 10:56:22 +0800 Subject: [PATCH] fix(usage_helpers): skip zero-token usage in additional model records - Added `buildAdditionalModelRecord` to filter out zero-token usage details. - Introduced `hasNonZeroTokenUsage` helper function for token usage validation. - Updated tests to cover scenarios for zero and non-zero token usage. --- .../runtime/executor/helps/usage_helpers.go | 25 ++++++++++++++++--- .../executor/helps/usage_helpers_test.go | 18 +++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/internal/runtime/executor/helps/usage_helpers.go b/internal/runtime/executor/helps/usage_helpers.go index 615b6bedf..d3093de18 100644 --- a/internal/runtime/executor/helps/usage_helpers.go +++ b/internal/runtime/executor/helps/usage_helpers.go @@ -49,15 +49,26 @@ func (r *UsageReporter) Publish(ctx context.Context, detail usage.Detail) { } func (r *UsageReporter) PublishAdditionalModel(ctx context.Context, model string, detail usage.Detail) { - if r == nil { + record, ok := r.buildAdditionalModelRecord(model, detail) + if !ok { return } + usage.PublishRecord(ctx, record) +} + +func (r *UsageReporter) buildAdditionalModelRecord(model string, detail usage.Detail) (usage.Record, bool) { + if r == nil { + return usage.Record{}, false + } model = strings.TrimSpace(model) if model == "" { - return + return usage.Record{}, false } detail = normalizeUsageDetailTotal(detail) - usage.PublishRecord(ctx, r.buildRecordForModel(model, detail, false)) + if !hasNonZeroTokenUsage(detail) { + return usage.Record{}, false + } + return r.buildRecordForModel(model, detail, false), true } func (r *UsageReporter) PublishFailure(ctx context.Context) { @@ -93,6 +104,14 @@ func normalizeUsageDetailTotal(detail usage.Detail) usage.Detail { return detail } +func hasNonZeroTokenUsage(detail usage.Detail) bool { + return detail.InputTokens != 0 || + detail.OutputTokens != 0 || + detail.ReasoningTokens != 0 || + detail.CachedTokens != 0 || + detail.TotalTokens != 0 +} + // ensurePublished guarantees that a usage record is emitted exactly once. // It is safe to call multiple times; only the first call wins due to once.Do. // This is used to ensure request counting even when upstream responses do not diff --git a/internal/runtime/executor/helps/usage_helpers_test.go b/internal/runtime/executor/helps/usage_helpers_test.go index 1a5648e89..3708b7317 100644 --- a/internal/runtime/executor/helps/usage_helpers_test.go +++ b/internal/runtime/executor/helps/usage_helpers_test.go @@ -62,3 +62,21 @@ func TestUsageReporterBuildRecordIncludesLatency(t *testing.T) { t.Fatalf("latency = %v, want <= 3s", record.Latency) } } + +func TestUsageReporterBuildAdditionalModelRecordSkipsZeroTokens(t *testing.T) { + reporter := &UsageReporter{ + provider: "codex", + model: "gpt-5.4", + requestedAt: time.Now(), + } + + if _, ok := reporter.buildAdditionalModelRecord("gpt-image-2", usage.Detail{}); ok { + t.Fatalf("expected all-zero token usage to be skipped") + } + if _, ok := reporter.buildAdditionalModelRecord("gpt-image-2", usage.Detail{InputTokens: 2}); !ok { + t.Fatalf("expected non-zero input token usage to be recorded") + } + if _, ok := reporter.buildAdditionalModelRecord("gpt-image-2", usage.Detail{CachedTokens: 2}); !ok { + t.Fatalf("expected non-zero cached token usage to be recorded") + } +}