From 0d86eaa3a1ab8f124640356d596cea3b82a44a58 Mon Sep 17 00:00:00 2001 From: Waleed Date: Tue, 23 Sep 2025 17:11:29 -0700 Subject: [PATCH] fix(usage): persist cost multiplier at provider level instead of also at the logger level (#1433) * feat(changelog): added changelog * fix(usage): persist cost multiplier at provider level * Revert "feat(changelog): added changelog" This reverts commit 885d10c4d93eef55af56c77883a503d98a4f3913. --------- Co-authored-by: waleed --- apps/sim/app/api/billing/update-cost/route.ts | 2 +- apps/sim/lib/logs/execution/logger.ts | 10 +++------- apps/sim/providers/index.ts | 11 ++++++++++- apps/sim/providers/utils.ts | 7 ------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/sim/app/api/billing/update-cost/route.ts b/apps/sim/app/api/billing/update-cost/route.ts index 816b7e997..fd897c59b 100644 --- a/apps/sim/app/api/billing/update-cost/route.ts +++ b/apps/sim/app/api/billing/update-cost/route.ts @@ -9,7 +9,7 @@ import { createLogger } from '@/lib/logs/console/logger' import { generateRequestId } from '@/lib/utils' import { calculateCost } from '@/providers/utils' -const logger = createLogger('billing-update-cost') +const logger = createLogger('BillingUpdateCostAPI') const UpdateCostSchema = z.object({ userId: z.string().min(1, 'User ID is required'), diff --git a/apps/sim/lib/logs/execution/logger.ts b/apps/sim/lib/logs/execution/logger.ts index 7bfefb672..fe56801c9 100644 --- a/apps/sim/lib/logs/execution/logger.ts +++ b/apps/sim/lib/logs/execution/logger.ts @@ -11,7 +11,7 @@ import { eq, sql } from 'drizzle-orm' import { v4 as uuidv4 } from 'uuid' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { checkUsageStatus, maybeSendUsageThresholdEmail } from '@/lib/billing/core/usage' -import { getCostMultiplier, isBillingEnabled } from '@/lib/environment' +import { isBillingEnabled } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' import { emitWorkflowExecutionCompleted } from '@/lib/logs/events' import { snapshotService } from '@/lib/logs/execution/snapshot/service' @@ -195,9 +195,7 @@ export class ExecutionLogger implements IExecutionLoggerService { if (usr?.email) { const sub = await getHighestPrioritySubscription(usr.id) - const costMultiplier = getCostMultiplier() - const costDelta = - (costSummary.baseExecutionCharge || 0) + (costSummary.modelCost || 0) * costMultiplier + const costDelta = costSummary.totalCost const planName = sub?.plan || 'Free' const scope: 'user' | 'organization' = @@ -399,9 +397,7 @@ export class ExecutionLogger implements IExecutionLoggerService { } const userId = workflowRecord.userId - const costMultiplier = getCostMultiplier() - // Apply cost multiplier only to model costs, not base execution charge - const costToStore = costSummary.baseExecutionCharge + costSummary.modelCost * costMultiplier + const costToStore = costSummary.totalCost const existing = await db.select().from(userStats).where(eq(userStats.userId, userId)) if (existing.length === 0) { diff --git a/apps/sim/providers/index.ts b/apps/sim/providers/index.ts index a464ff91d..d4af6e5c1 100644 --- a/apps/sim/providers/index.ts +++ b/apps/sim/providers/index.ts @@ -1,3 +1,4 @@ +import { getCostMultiplier } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' import type { StreamingExecution } from '@/executor/types' import type { ProviderRequest, ProviderResponse } from '@/providers/types' @@ -87,7 +88,15 @@ export async function executeProviderRequest( const useCachedInput = !!request.context && request.context.length > 0 if (shouldBillModelUsage(response.model)) { - response.cost = calculateCost(response.model, promptTokens, completionTokens, useCachedInput) + const costMultiplier = getCostMultiplier() + response.cost = calculateCost( + response.model, + promptTokens, + completionTokens, + useCachedInput, + costMultiplier, + costMultiplier + ) } else { response.cost = { input: 0, diff --git a/apps/sim/providers/utils.ts b/apps/sim/providers/utils.ts index 435877e36..14f02c3c1 100644 --- a/apps/sim/providers/utils.ts +++ b/apps/sim/providers/utils.ts @@ -496,13 +496,11 @@ export function calculateCost( * Get pricing information for a specific model (including embedding models) */ export function getModelPricing(modelId: string): any { - // First check if it's an embedding model const embeddingPricing = getEmbeddingModelPricing(modelId) if (embeddingPricing) { return embeddingPricing } - // Then check chat models return getModelPricingFromDefinitions(modelId) } @@ -516,20 +514,15 @@ export function formatCost(cost: number): string { if (cost === undefined || cost === null) return '—' if (cost >= 1) { - // For costs >= $1, show two decimal places return `$${cost.toFixed(2)}` } if (cost >= 0.01) { - // For costs between 1¢ and $1, show three decimal places return `$${cost.toFixed(3)}` } if (cost >= 0.001) { - // For costs between 0.1¢ and 1¢, show four decimal places return `$${cost.toFixed(4)}` } if (cost > 0) { - // For very small costs, still show as fixed decimal instead of scientific notation - // Find the first non-zero digit and show a few more places const places = Math.max(4, Math.abs(Math.floor(Math.log10(cost))) + 3) return `$${cost.toFixed(places)}` }