Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions internal/runtime/executor/aistudio_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func (e *AIStudioExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth,
baseModel := thinking.ParseSuffix(req.Model).ModelName
reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 119 to +120
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Defer failure tracking after ensurePublished

In Execute, this defer order is backwards for Go's LIFO semantics: ensurePublished runs first, calls once.Do, and then trackFailure cannot publish a failed record anymore. That means any error path that returns before an explicit usage publish (for example translateRequest failures in this function) is now recorded as a successful zero-usage request, which corrupts failure accounting. The same pattern appears in the other executors changed in this commit.

Useful? React with 👍 / 👎.

Comment on lines 119 to +120
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


translatedReq, body, err := e.translateRequest(req, opts, false)
if err != nil {
Expand Down Expand Up @@ -176,6 +177,7 @@ func (e *AIStudioExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth
baseModel := thinking.ParseSuffix(req.Model).ModelName
reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 179 to +180
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


translatedReq, body, err := e.translateRequest(req, opts, true)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions internal/runtime/executor/antigravity_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 207 to +208
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("antigravity")
Expand Down Expand Up @@ -347,6 +348,7 @@ func (e *AntigravityExecutor) executeClaudeNonStream(ctx context.Context, auth *

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 350 to +351
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("antigravity")
Expand Down Expand Up @@ -750,6 +752,7 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 754 to +755
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("antigravity")
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/claude_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func (e *ClaudeExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 106 to +107
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)

from := opts.SourceFormat
to := sdktranslator.FromString("claude")
// Use streaming translation to preserve function calling, except for claude.
Expand Down Expand Up @@ -272,6 +273,7 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 275 to +276
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)

from := opts.SourceFormat
to := sdktranslator.FromString("claude")
originalPayloadSource := req.Payload
Expand Down
3 changes: 3 additions & 0 deletions internal/runtime/executor/codex_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func (e *CodexExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 92 to +93
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("codex")
Expand Down Expand Up @@ -200,6 +201,7 @@ func (e *CodexExecutor) executeCompact(ctx context.Context, auth *cliproxyauth.A

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 203 to +204
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("openai-response")
Expand Down Expand Up @@ -290,6 +292,7 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 294 to +295
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("codex")
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/codex_websockets_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ func (e *CodexWebsocketsExecutor) Execute(ctx context.Context, auth *cliproxyaut

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 159 to +160
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("codex")
Expand Down Expand Up @@ -366,6 +367,7 @@ func (e *CodexWebsocketsExecutor) ExecuteStream(ctx context.Context, auth *clipr

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 369 to +370
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("codex")
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/gemini_cli_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func (e *GeminiCLIExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 116 to +117
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("gemini-cli")
Expand Down Expand Up @@ -268,6 +269,7 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 271 to +272
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("gemini-cli")
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/gemini_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func (e *GeminiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 114 to +115
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


// Official Gemini API via API key or OAuth bearer
from := opts.SourceFormat
Expand Down Expand Up @@ -220,6 +221,7 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 223 to +224
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("gemini")
Expand Down
4 changes: 4 additions & 0 deletions internal/runtime/executor/gemini_vertex_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ func (e *GeminiVertexExecutor) executeWithServiceAccount(ctx context.Context, au

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 305 to +306
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


var body []byte

Expand Down Expand Up @@ -429,6 +430,7 @@ func (e *GeminiVertexExecutor) executeWithAPIKey(ctx context.Context, auth *clip

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 432 to +433
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("gemini")
Expand Down Expand Up @@ -534,6 +536,7 @@ func (e *GeminiVertexExecutor) executeStreamWithServiceAccount(ctx context.Conte

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 538 to +539
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("gemini")
Expand Down Expand Up @@ -658,6 +661,7 @@ func (e *GeminiVertexExecutor) executeStreamWithAPIKey(ctx context.Context, auth

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 663 to +664
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("gemini")
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/iflow_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func (e *IFlowExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 90 to +91
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("openai")
Expand Down Expand Up @@ -191,6 +192,7 @@ func (e *IFlowExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 194 to +195
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("openai")
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/kimi_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func (e *KimiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 80 to +81
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


to := sdktranslator.FromString("openai")
originalPayloadSource := req.Payload
Expand Down Expand Up @@ -178,6 +179,7 @@ func (e *KimiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Aut

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 181 to +182
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


to := sdktranslator.FromString("openai")
originalPayloadSource := req.Payload
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/openai_compat_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (e *OpenAICompatExecutor) Execute(ctx context.Context, auth *cliproxyauth.A

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 76 to +77
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


baseURL, apiKey := e.resolveCredentials(auth)
if baseURL == "" {
Expand Down Expand Up @@ -181,6 +182,7 @@ func (e *OpenAICompatExecutor) ExecuteStream(ctx context.Context, auth *cliproxy

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 184 to +185
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


baseURL, apiKey := e.resolveCredentials(auth)
if baseURL == "" {
Expand Down
2 changes: 2 additions & 0 deletions internal/runtime/executor/qwen_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ func (e *QwenExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 232 to +233
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("openai")
Expand Down Expand Up @@ -333,6 +334,7 @@ func (e *QwenExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Aut

reporter := newUsageReporter(ctx, e.Identifier(), baseModel, auth)
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
Comment on lines 336 to +337
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The order of these defer statements is important. In Go, defer statements are executed in a Last-In, First-Out (LIFO) order. With the current order, reporter.ensurePublished(ctx) will be executed before reporter.trackFailure(ctx, &err).

Both ensurePublished and trackFailure use sync.Once to ensure the usage record is published only once. This means if an error occurs, ensurePublished will run first and publish a success record. trackFailure will then run, but its attempt to publish a failure record will be a no-op.

To fix this, the defer statements should be reordered so that trackFailure is executed first.

Suggested change
defer reporter.trackFailure(ctx, &err)
defer reporter.ensurePublished(ctx)
defer reporter.ensurePublished(ctx)
defer reporter.trackFailure(ctx, &err)


from := opts.SourceFormat
to := sdktranslator.FromString("openai")
Expand Down
Loading