History

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.

Luis Pater committed 6 months ago

Commit 04a336f1 parent a3255332 files · +40 −3Browse files

Unified · Split

2 files
  1. internal/runtime/executor/helps/usage_helpers.go +22 −3
  2. internal/runtime/executor/helps/usage_helpers_test.go +18 −0
internal/runtime/executor/helps/usage_helpers.go+22−3
@@ -49,15 +49,26 @@ func (r *UsageReporter) Publish(ctx context.Context, detail usage.Detail) { · 48 unmodified lines
4949 }
5050
5151 func (r *UsageReporter) PublishAdditionalModel(ctx context.Context, model string, detail usage.Detail) {
52− if r == nil {
52+ record, ok := r.buildAdditionalModelRecord(model, detail)
53+ if !ok {
5354 return
5455 }
56+ usage.PublishRecord(ctx, record)
57+}
58+
59+func (r *UsageReporter) buildAdditionalModelRecord(model string, detail usage.Detail) (usage.Record, bool) {
60+ if r == nil {
61+ return usage.Record{}, false
62+ }
5563 model = strings.TrimSpace(model)
5664 if model == "" {
57− return
65+ return usage.Record{}, false
5866 }
5967 detail = normalizeUsageDetailTotal(detail)
60− usage.PublishRecord(ctx, r.buildRecordForModel(model, detail, false))
68+ if !hasNonZeroTokenUsage(detail) {
69+ return usage.Record{}, false
70+ }
71+ return r.buildRecordForModel(model, detail, false), true
6172 }
6273
6374 func (r *UsageReporter) PublishFailure(ctx context.Context) {
@@ -93,6 +104,14 @@ func normalizeUsageDetailTotal(detail usage.Detail) usage.Detail { · 29 unmodified lines
93104 return detail
94105 }
95106
107+func hasNonZeroTokenUsage(detail usage.Detail) bool {
108+ return detail.InputTokens != 0 ||
109+ detail.OutputTokens != 0 ||
110+ detail.ReasoningTokens != 0 ||
111+ detail.CachedTokens != 0 ||
112+ detail.TotalTokens != 0
113+}
114+
96115 // ensurePublished guarantees that a usage record is emitted exactly once.
97116 // It is safe to call multiple times; only the first call wins due to once.Do.
98117 // This is used to ensure request counting even when upstream responses do not
internal/runtime/executor/helps/usage_helpers_test.go+18−0
@@ -62,3 +62,21 @@ func TestUsageReporterBuildRecordIncludesLatency(t *testing.T) { · 61 unmodified lines
6262 t.Fatalf("latency = %v, want <= 3s", record.Latency)
6363 }
6464 }
65+
66+func TestUsageReporterBuildAdditionalModelRecordSkipsZeroTokens(t *testing.T) {
67+ reporter := &UsageReporter{
68+ provider: "codex",
69+ model: "gpt-5.4",
70+ requestedAt: time.Now(),
71+ }
72+
73+ if _, ok := reporter.buildAdditionalModelRecord("gpt-image-2", usage.Detail{}); ok {
74+ t.Fatalf("expected all-zero token usage to be skipped")
75+ }
76+ if _, ok := reporter.buildAdditionalModelRecord("gpt-image-2", usage.Detail{InputTokens: 2}); !ok {
77+ t.Fatalf("expected non-zero input token usage to be recorded")
78+ }
79+ if _, ok := reporter.buildAdditionalModelRecord("gpt-image-2", usage.Detail{CachedTokens: 2}); !ok {
80+ t.Fatalf("expected non-zero cached token usage to be recorded")
81+ }
82+}