feat: implement real-time token tracking and API usage visibility with cost#376
feat: implement real-time token tracking and API usage visibility with cost#376SoorejS wants to merge 6 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds token-usage propagation and estimated USD cost from Gemini through services and controllers, persists token counts on messages, logs token metrics, updates service signatures to return usage metadata, and exposes token/cost fields in API JSON responses for debate message and judge endpoints. Changes
Sequence DiagramsequenceDiagram
participant Client
participant Controller as Controller (debatevsbot)
participant Service as Service (debatevsbot)
participant Gemini as Gemini API
participant DB as Database
Client->>Controller: POST /debate/send (user message)
activate Controller
Controller->>Service: GenerateBotResponse(ctx, history, ...)
activate Service
Service->>Gemini: generateDefaultModelText(ctx, prompt)
activate Gemini
Gemini-->>Service: (botText, usageMetadata)
deactivate Gemini
Service-->>Controller: (botText, usageMetadata)
deactivate Service
Controller->>Gemini: CountTokens(ctx, user_message_text)
activate Gemini
Gemini-->>Controller: user_input_tokens
deactivate Gemini
Controller->>DB: Append bot Message with Prompt/Response/Total tokens
DB-->>Controller: OK
Controller-->>Client: DebateMessageResponse {response, user_input_tokens, prompt_tokens, response_tokens, total_tokens, estimated_cost_usd}
deactivate Controller
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
backend/controllers/debatevsbot_controller.go (1)
285-290:⚠️ Potential issue | 🟡 MinorOperator precedence issue may cause unexpected behavior.
Lines 286 and 290 mix
&&and||without parentheses. In Go,&&has higher precedence than||, soA || B && Cis evaluated asA || (B && C), which may not be the intended logic.For example, line 286:
strings.Contains(resultLower, "user") && strings.Contains(resultLower, "win")This expression is evaluated independently from the
||conditions before it due to precedence.Proposed fix for clarity
- if strings.Contains(resultLower, "user win") || strings.Contains(resultLower, "user wins") || - strings.Contains(resultLower, "user") && strings.Contains(resultLower, "win") { + if strings.Contains(resultLower, "user win") || strings.Contains(resultLower, "user wins") || + (strings.Contains(resultLower, "user") && strings.Contains(resultLower, "win")) { resultStatus = "win" } else if strings.Contains(resultLower, "bot win") || strings.Contains(resultLower, "bot wins") || strings.Contains(resultLower, "lose") || strings.Contains(resultLower, "loss") || - strings.Contains(resultLower, "bot") && strings.Contains(resultLower, "win") { + (strings.Contains(resultLower, "bot") && strings.Contains(resultLower, "win")) { resultStatus = "loss"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/controllers/debatevsbot_controller.go` around lines 285 - 290, The conditional that sets resultStatus based on resultLower contains mixed && and || without grouping, causing operator-precedence bugs; update the if/else-if that checks strings.Contains(resultLower, "user win") ... and the subsequent else-if for bot/lose so that combined checks like strings.Contains(resultLower, "user") && strings.Contains(resultLower, "win") are wrapped in parentheses (or refactored into separate boolean variables) and the ORed alternatives are clearly grouped—ensure both the "user win" branch and the "bot win/lose" branch use explicit grouping so the intended logic for resultStatus ("win"/"lose") is unambiguous.backend/services/transcriptservice.go (1)
132-241:⚠️ Potential issue | 🟡 MinorSilent error swallowing in default case.
The
defaultcase (lines 240-241) silently ignores all errors other thannilandmongo.ErrNoDocuments. This could mask database connection issues, timeouts, or other unexpected errors, making debugging difficult.Consider logging or handling the error:
Proposed fix
default: + log.Printf("Error checking for existing transcript: %v", err) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/services/transcriptservice.go` around lines 132 - 241, The switch on err currently ignores unexpected errors in the default branch; update the default case to surface or log the error instead of swallowing it—use the existing logger or return the error so callers can handle it. Locate the switch that checks err (the same block that later calls SaveDebateTranscript, UpdateRatings and db.MongoDatabase.Collection("debates").InsertMany) and replace the empty default with a call to log the error (including err.Error() and context like roomID) and return or propagate the error up the call stack to avoid hiding DB/network failures.
🧹 Nitpick comments (2)
backend/controllers/debatevsbot_controller.go (1)
49-66: Consider addingomitemptyfor consistency with the Message model.The
DebateMessageResponseandJudgeResponsestructs will always include token fields in JSON responses, even when they're zero (e.g., when usage metadata is nil). TheMessagemodel usesomitemptyfor these same fields.For consistent API behavior and backward compatibility, consider adding
omitempty:Proposed fix
type DebateMessageResponse struct { DebateId string `json:"debateId"` BotName string `json:"botName"` BotLevel string `json:"botLevel"` Topic string `json:"topic"` Stance string `json:"stance"` Response string `json:"response"` - PromptTokens int `json:"prompt_tokens"` - ResponseTokens int `json:"response_tokens"` - TotalTokens int `json:"total_tokens"` + PromptTokens int `json:"prompt_tokens,omitempty"` + ResponseTokens int `json:"response_tokens,omitempty"` + TotalTokens int `json:"total_tokens,omitempty"` } type JudgeResponse struct { - Result string `json:"result"` - PromptTokens int `json:"prompt_tokens"` - ResponseTokens int `json:"response_tokens"` - TotalTokens int `json:"total_tokens"` + Result string `json:"result"` + PromptTokens int `json:"prompt_tokens,omitempty"` + ResponseTokens int `json:"response_tokens,omitempty"` + TotalTokens int `json:"total_tokens,omitempty"` }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/controllers/debatevsbot_controller.go` around lines 49 - 66, Add JSON `omitempty` tags to the token fields on DebateMessageResponse and JudgeResponse so zero-value token fields are omitted like Message does; specifically update DebateMessageResponse's PromptTokens, ResponseTokens, TotalTokens and JudgeResponse's PromptTokens, ResponseTokens, TotalTokens to use `json:"prompt_tokens,omitempty"`, `json:"response_tokens,omitempty"`, and `json:"total_tokens,omitempty"` respectively to ensure consistent API output when usage metadata is nil.backend/services/debatevsbot.go (1)
110-113: Consider if exportingConstructPromptis intentional.The function was renamed from
constructPrompttoConstructPrompt, making it part of the public API. Based on the context snippet, it's only called internally byGenerateBotResponse. If this export is for testing purposes, consider adding a comment to document the intent, or keep it unexported if external access isn't needed.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/services/debatevsbot.go` around lines 110 - 113, The function ConstructPrompt was exported (capitalized) but appears only used internally by GenerateBotResponse; either revert the name to unexported constructPrompt to keep it internal, or if export is intentional for tests/clients add a brief comment above ConstructPrompt documenting that it's intentionally public for external use/testing (mention GenerateBotResponse and ConstructPrompt in the comment to clarify relationship).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@backend/controllers/debatevsbot_controller.go`:
- Around line 285-290: The conditional that sets resultStatus based on
resultLower contains mixed && and || without grouping, causing
operator-precedence bugs; update the if/else-if that checks
strings.Contains(resultLower, "user win") ... and the subsequent else-if for
bot/lose so that combined checks like strings.Contains(resultLower, "user") &&
strings.Contains(resultLower, "win") are wrapped in parentheses (or refactored
into separate boolean variables) and the ORed alternatives are clearly
grouped—ensure both the "user win" branch and the "bot win/lose" branch use
explicit grouping so the intended logic for resultStatus ("win"/"lose") is
unambiguous.
In `@backend/services/transcriptservice.go`:
- Around line 132-241: The switch on err currently ignores unexpected errors in
the default branch; update the default case to surface or log the error instead
of swallowing it—use the existing logger or return the error so callers can
handle it. Locate the switch that checks err (the same block that later calls
SaveDebateTranscript, UpdateRatings and
db.MongoDatabase.Collection("debates").InsertMany) and replace the empty default
with a call to log the error (including err.Error() and context like roomID) and
return or propagate the error up the call stack to avoid hiding DB/network
failures.
---
Nitpick comments:
In `@backend/controllers/debatevsbot_controller.go`:
- Around line 49-66: Add JSON `omitempty` tags to the token fields on
DebateMessageResponse and JudgeResponse so zero-value token fields are omitted
like Message does; specifically update DebateMessageResponse's PromptTokens,
ResponseTokens, TotalTokens and JudgeResponse's PromptTokens, ResponseTokens,
TotalTokens to use `json:"prompt_tokens,omitempty"`,
`json:"response_tokens,omitempty"`, and `json:"total_tokens,omitempty"`
respectively to ensure consistent API output when usage metadata is nil.
In `@backend/services/debatevsbot.go`:
- Around line 110-113: The function ConstructPrompt was exported (capitalized)
but appears only used internally by GenerateBotResponse; either revert the name
to unexported constructPrompt to keep it internal, or if export is intentional
for tests/clients add a brief comment above ConstructPrompt documenting that
it's intentionally public for external use/testing (mention GenerateBotResponse
and ConstructPrompt in the comment to clarify relationship).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: dc56e4f3-93bc-4828-8c0a-c2695ce29a27
📒 Files selected for processing (7)
backend/controllers/debatevsbot_controller.gobackend/models/debatevsbot.gobackend/services/coach.gobackend/services/debatevsbot.gobackend/services/gemini.gobackend/services/pros_cons.gobackend/services/transcriptservice.go
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
backend/services/transcriptservice.go (1)
194-210:⚠️ Potential issue | 🟠 MajorAvoid logging raw participant emails here.
These error logs emit email addresses on normal persistence failures. That is avoidable PII exposure; log the room/role or a non-sensitive identifier instead.
🧹 Suggested fix
- log.Printf("[TRANSCRIPT] Error saving transcript for 'for' user %s in room %s: %v", forUser.Email, roomID, err) + log.Printf("[TRANSCRIPT] Error saving transcript for role=for room=%s: %v", roomID, err) ... - log.Printf("[TRANSCRIPT] Error saving transcript for 'against' user %s in room %s: %v", againstUser.Email, roomID, err) + log.Printf("[TRANSCRIPT] Error saving transcript for role=against room=%s: %v", roomID, err)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/services/transcriptservice.go` around lines 194 - 210, The error logs around the SaveDebateTranscript calls leak participant emails (forUser.Email and againstUser.Email); update the two log.Printf calls to avoid PII by logging a non-sensitive identifier such as the role ("for"/"against"), the user ID (forUser.ID / againstUser.ID) or an anonymized token, and include roomID and context instead; specifically modify the log.Printf invocations immediately after SaveDebateTranscript (and the earlier one for the "for" user) to replace raw email values with a safe identifier and keep the existing error and roomID information.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/controllers/debatevsbot_controller.go`:
- Around line 188-195: The Message model currently lacks a UserInputTokens field
so user_input_tokens is not persisted; add a UserInputTokens (int) field to
models.Message in backend/models/debatevsbot.go and update any DB marshaling if
necessary, then populate that field when creating updatedHistory in the
controller (the append using updatedHistory and models.Message) so you include
UserInputTokens alongside PromptTokens, ResponseTokens, and TotalTokens; make
the same change in the other similar block (the append at the later section
referenced) so both places persist the user input token split.
- Around line 156-169: The extra CountTokens call uses context.Background(),
which can hang SendDebateMessage; replace that call with a context that has a
short timeout/deadline (e.g., using context.WithTimeout) and ensure you call
cancel() via defer; pass that timed context to services.CountTokens and handle
timeout/errors gracefully (fall back to zero tokens or log) so the RPC cannot
stall SendDebateMessage (refer to the userInputTokens/userInputText block and
services.CountTokens within SendDebateMessage).
In `@backend/services/debatevsbot.go`:
- Around line 285-287: When response is empty you currently return
personalityErrorResponse(...), nil which discards any non-nil UsageMetadata
returned by generateDefaultModelText; instead propagate that UsageMetadata along
with the error response. Update the branch in debatevsbot.go where response ==
"" (and the similar branch around lines 457-463) to capture the UsageMetadata
from generateDefaultModelText and return personalityErrorResponse(botName, "Lost
in translation, my thoughts are."), usageMeta (or wrap/merge as your call sites
expect) rather than nil so token/cost visibility is preserved.
In `@backend/services/transcriptservice.go`:
- Around line 247-255: The duplicate-check FindOne error path should abort the
function instead of continuing to cleanup; change the default/error branch
handling around the duplicate-check (the code that logs "[TRANSCRIPT] Unexpected
error checking existing transcript in room %s") to return or propagate the error
immediately so you do not reach transcriptCollection.DeleteMany(ctx,
bson.M{"roomId": roomID}) and accidentally delete source transcripts after
debate_results was already inserted; update the handler in the function that
performs the FindOne check (and any surrounding judgment flow that writes to
debate_results) to stop execution on unexpected FindOne errors and surface the
error to the caller.
---
Outside diff comments:
In `@backend/services/transcriptservice.go`:
- Around line 194-210: The error logs around the SaveDebateTranscript calls leak
participant emails (forUser.Email and againstUser.Email); update the two
log.Printf calls to avoid PII by logging a non-sensitive identifier such as the
role ("for"/"against"), the user ID (forUser.ID / againstUser.ID) or an
anonymized token, and include roomID and context instead; specifically modify
the log.Printf invocations immediately after SaveDebateTranscript (and the
earlier one for the "for" user) to replace raw email values with a safe
identifier and keep the existing error and roomID information.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 30a037f9-fbc8-46a0-91c8-a283e8132b16
📒 Files selected for processing (3)
backend/controllers/debatevsbot_controller.gobackend/services/debatevsbot.gobackend/services/transcriptservice.go
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
backend/services/transcriptservice.go (1)
195-210:⚠️ Potential issue | 🔴 CriticalDon't continue into cleanup after post-judgment persistence failures.
These branches only log and continue, but the result document was already inserted earlier. If transcript saves or rating/debate writes fail here,
DeleteManystill removes the recoverable source transcripts and later retries short-circuit as “already judged”, so the missing side effects become permanent.Also applies to: 223-224, 232-233, 253-257
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/services/transcriptservice.go` around lines 195 - 210, The current flow logs errors from SaveDebateTranscript (and similar persistence calls) and proceeds to call DeleteMany, which can permanently remove source transcripts after the result doc was inserted; change the error handling in the branches that call SaveDebateTranscript (and the other persistence functions referenced) to return the error immediately (or propagate it up) instead of just logging and continuing so cleanup (DeleteMany) is not run when these saves fail; locate calls to SaveDebateTranscript, any rating/debate write functions, and the DeleteMany invocation and ensure failures from SaveDebateTranscript cause an early return/error propagation before DeleteMany is executed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/controllers/debatevsbot_controller.go`:
- Around line 171-177: The code currently writes userInputTokens into the last
user message (req.History[*].UserInputTokens) and then duplicates the same value
onto the appended bot message, causing double-counting; update the logic so
user_input_tokens is persisted in one canonical place — keep setting
req.History[i].UserInputTokens on the last user message (in the loop that checks
Sender == "User") and remove the duplicate assignment that writes the same
userInputTokens onto the bot message when you append it (also remove the
duplicate in the similar block around the 200-208 region), or alternatively move
storage to a single request-level field and eliminate per-bot-message writes;
adjust any tests/consumers expecting the bot message field accordingly.
- Around line 153-154: The Gemini RPC calls ignore request cancellation because
services.GenerateBotResponse and services.JudgeDebate use context.Background();
change both function signatures to accept a context.Context (e.g., func
GenerateBotResponse(ctx context.Context, ... ) and func JudgeDebate(ctx
context.Context, ... )), update their internal calls to use the passed ctx, and
from the controller pass c.Request.Context() (optionally wrap it with a timeout
via context.WithTimeout before passing) at the existing call sites (the
GenerateBotResponse invocation around the bot response and the JudgeDebate call
near line 271) so client cancellations and deadlines propagate into Gemini
calls.
In `@backend/services/transcriptservice.go`:
- Line 195: Replace instances where log.Printf emits raw participant emails
(forUser.Email / againstUser.Email) with a non-PII identifier such as the user's
internal ID (forUser.ID / againstUser.ID) or the role ("for"/"against") plus
roomID; update the two occurrences around the transcript save error (the
log.Printf at the shown diff and the similar one at line ~210) so they log
roomID and role or internal ID instead of email, and ensure the formatted
message still includes the error variable (err) and context.
---
Duplicate comments:
In `@backend/services/transcriptservice.go`:
- Around line 195-210: The current flow logs errors from SaveDebateTranscript
(and similar persistence calls) and proceeds to call DeleteMany, which can
permanently remove source transcripts after the result doc was inserted; change
the error handling in the branches that call SaveDebateTranscript (and the other
persistence functions referenced) to return the error immediately (or propagate
it up) instead of just logging and continuing so cleanup (DeleteMany) is not run
when these saves fail; locate calls to SaveDebateTranscript, any rating/debate
write functions, and the DeleteMany invocation and ensure failures from
SaveDebateTranscript cause an early return/error propagation before DeleteMany
is executed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d5d13542-a593-4b61-8d64-1b5ff056a82f
📒 Files selected for processing (4)
backend/controllers/debatevsbot_controller.gobackend/models/debatevsbot.gobackend/services/debatevsbot.gobackend/services/transcriptservice.go
🚧 Files skipped from review as they are similar to previous changes (1)
- backend/services/debatevsbot.go
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
backend/controllers/debatevsbot_controller.go (2)
223-224:⚠️ Potential issue | 🟠 MajorSilent database write failure - errors are discarded.
The empty error handling block means database save failures go unnoticed. This contradicts the PR's observability goals and can cause silent data loss, preventing token analytics from being persisted.
🔧 Proposed fix
- if err := db.SaveDebateVsBot(debate); err != nil { - } + if err := db.SaveDebateVsBot(debate); err != nil { + log.Printf("[DB ERROR] Failed to save debate: %v", err) + // Continue to return response - don't fail the request for DB errors + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/controllers/debatevsbot_controller.go` around lines 223 - 224, The db.SaveDebateVsBot(debate) call currently swallows errors; update the error handling in the surrounding function (the handler calling db.SaveDebateVsBot) to log the error via the existing logger (e.g., process or request logger) and return an appropriate error response (or propagate the error) instead of leaving the block empty; include context (operation and debate ID) in the log message and ensure the function returns/handles the error so database write failures are observable and do not silently drop token analytics data.
288-289:⚠️ Potential issue | 🟠 MajorSilent database update failure - errors are discarded.
Same issue as above: the empty error block silently ignores failures when updating debate outcomes.
🔧 Proposed fix
- if err := db.UpdateDebateVsBotOutcome(email, result); err != nil { - } + if err := db.UpdateDebateVsBotOutcome(email, result); err != nil { + log.Printf("[DB ERROR] Failed to update debate outcome: %v", err) + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/controllers/debatevsbot_controller.go` around lines 288 - 289, The UpdateDebateVsBotOutcome call currently swallows errors (if err := db.UpdateDebateVsBotOutcome(email, result); err != nil { }), so restore proper error handling: check the returned err from db.UpdateDebateVsBotOutcome(email, result), log the error (using the controller's logger or fmt) with context including email and result, and return or propagate an appropriate error/HTTP response instead of silently ignoring it; ensure you update the surrounding handler to handle the failure path (e.g., return a 500 or call next with the error) so failures are visible and actionable.
🧹 Nitpick comments (1)
backend/services/transcriptservice.go (1)
489-489: Consider capturing usage metadata for observability.The usage metadata from
generateDefaultModelTextis discarded here. Given the PR objectives around token tracking and cost visibility, consider logging the token usage for human vs human debate judgments as well:text, usageMeta, err := generateDefaultModelText(ctx, prompt) if err != nil { return "Unable to judge." } if usageMeta != nil { log.Printf("[TOKEN USAGE] JudgeHvH | Prompt: %d | Response: %d | Total: %d", usageMeta.PromptTokenCount, usageMeta.CandidatesTokenCount, usageMeta.TotalTokenCount) }This would provide consistent observability across all AI interactions, aligning with the structured logging pattern mentioned in the PR objectives.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/services/transcriptservice.go` at line 489, The call to generateDefaultModelText currently discards the usage metadata; update the call in transcriptservice.go to capture the second return value (e.g., usageMeta) alongside text and err, handle err as before, and if usageMeta is non-nil emit a structured log with PromptTokenCount, CandidatesTokenCount (or ResponseTokenCount) and TotalTokenCount for the JudgeHvH path; reference the existing generateDefaultModelText call and the usageMeta fields to ensure token counts are logged for observability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@backend/controllers/debatevsbot_controller.go`:
- Around line 223-224: The db.SaveDebateVsBot(debate) call currently swallows
errors; update the error handling in the surrounding function (the handler
calling db.SaveDebateVsBot) to log the error via the existing logger (e.g.,
process or request logger) and return an appropriate error response (or
propagate the error) instead of leaving the block empty; include context
(operation and debate ID) in the log message and ensure the function
returns/handles the error so database write failures are observable and do not
silently drop token analytics data.
- Around line 288-289: The UpdateDebateVsBotOutcome call currently swallows
errors (if err := db.UpdateDebateVsBotOutcome(email, result); err != nil { }),
so restore proper error handling: check the returned err from
db.UpdateDebateVsBotOutcome(email, result), log the error (using the
controller's logger or fmt) with context including email and result, and return
or propagate an appropriate error/HTTP response instead of silently ignoring it;
ensure you update the surrounding handler to handle the failure path (e.g.,
return a 500 or call next with the error) so failures are visible and
actionable.
---
Nitpick comments:
In `@backend/services/transcriptservice.go`:
- Line 489: The call to generateDefaultModelText currently discards the usage
metadata; update the call in transcriptservice.go to capture the second return
value (e.g., usageMeta) alongside text and err, handle err as before, and if
usageMeta is non-nil emit a structured log with PromptTokenCount,
CandidatesTokenCount (or ResponseTokenCount) and TotalTokenCount for the
JudgeHvH path; reference the existing generateDefaultModelText call and the
usageMeta fields to ensure token counts are logged for observability.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6a0568da-ae13-456a-ab58-8121b030709b
📒 Files selected for processing (3)
backend/controllers/debatevsbot_controller.gobackend/services/debatevsbot.gobackend/services/transcriptservice.go
🚧 Files skipped from review as they are similar to previous changes (1)
- backend/services/debatevsbot.go
|
sorry |
Addressed Issues:
Fixes #375
Screenshots/Recordings:
Before:
26.03.2026_22.45.28_REC.mp4
After:
26.03.2026_22.55.20_REC.1.1.mp4
Additional Notes:
This PR introduces token observability with actionable insights beyond basic logging.
1. Granular Token Breakdown
Gemini’s
PromptTokenCountincludes system prompt + history + user input.To isolate user input, this PR adds a
CountTokens()call on raw input.user_input_tokens→ CountTokens(userMessage)prompt_tokens→ UsageMetadata.PromptTokenCountresponse_tokens→ UsageMetadata.CandidatesTokenCounttotal_tokens→ UsageMetadata.TotalTokenCount2. Real-Time Cost Estimation
Adds
estimated_cost_usdusing Gemini 2.5 Flash pricing:Available in API response and server logs.
3. Persistent Storage
Each message now stores token fields in MongoDB, enabling future analytics (per-user cost, session summaries, dashboards).
4. Observability (No UI Changes)
5. Compatibility
omitemptyAI Usage Disclosure:
I have used the following AI models and tools: Claude
Checklist
Summary by CodeRabbit
New Features
Bug Fix / Behavior