Skip to content

Commit 7cd02a4

Browse files
committed
refactor: rename cache input token to cache read token and add cache write token for improved clarity and tracking
1 parent 868c25f commit 7cd02a4

11 files changed

Lines changed: 137 additions & 57 deletions

File tree

src/client/components/aiGateway/AIGatewayAnalytics.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,14 @@ export const AIGatewayAnalytics: React.FC<AIGatewayAnalyticsProps> = React.memo(
318318
{ name: 'inputToken', math: 'events', alias: 'inputToken' },
319319
{ name: 'outputToken', math: 'events', alias: 'outputToken' },
320320
{
321-
name: 'cacheInputToken',
321+
name: 'cacheReadInputToken',
322322
math: 'events',
323-
alias: 'cacheInputToken',
323+
alias: 'cacheReadInputToken',
324+
},
325+
{
326+
name: 'cacheWriteInputToken',
327+
math: 'events',
328+
alias: 'cacheWriteInputToken',
324329
},
325330
]}
326331
filters={[]}

src/client/components/aiGateway/AIGatewayLogTable.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,11 @@ export const AIGatewayLogTable: React.FC<AIGatewayLogTableProps> = React.memo(
148148

149149
<SheetDataSection label="Tokens">
150150
{selectedItem.inputToken}↑ | {selectedItem.outputToken}
151-
{selectedItem.cacheInputToken > 0 && (
152-
<> | {selectedItem.cacheInputToken} cached</>
151+
{selectedItem.cacheReadInputToken > 0 && (
152+
<> | {selectedItem.cacheReadInputToken} cache read</>
153+
)}
154+
{selectedItem.cacheWriteInputToken > 0 && (
155+
<> | {selectedItem.cacheWriteInputToken} cache write</>
153156
)}
154157
</SheetDataSection>
155158

src/client/components/aiGateway/AIGatewayOverview.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export const AIGatewayOverview: React.FC<AIGatewayOverviewProps> = React.memo(
3737
| '$all_event'
3838
| 'inputToken'
3939
| 'outputToken'
40-
| 'cacheInputToken'
40+
| 'cacheReadInputToken'
41+
| 'cacheWriteInputToken'
4142
| 'price'
4243
>('price');
4344
const [isQuotaModalOpen, setIsQuotaModalOpen] = useState(false);
@@ -92,10 +93,17 @@ export const AIGatewayOverview: React.FC<AIGatewayOverviewProps> = React.memo(
9293
color: colors.blue[500],
9394
},
9495
};
95-
} else if (type === 'cacheInputToken') {
96+
} else if (type === 'cacheReadInputToken') {
9697
return {
9798
value: {
98-
label: t('AIGateway Cache Input Token'),
99+
label: t('AIGateway Cache Read Token'),
100+
color: colors.blue[500],
101+
},
102+
};
103+
} else if (type === 'cacheWriteInputToken') {
104+
return {
105+
value: {
106+
label: t('AIGateway Cache Write Token'),
99107
color: colors.blue[500],
100108
},
101109
};
@@ -174,8 +182,11 @@ export const AIGatewayOverview: React.FC<AIGatewayOverviewProps> = React.memo(
174182
<SelectItem value="outputToken">
175183
{t('Output Token')}
176184
</SelectItem>
177-
<SelectItem value="cacheInputToken">
178-
{t('Cache Input Token')}
185+
<SelectItem value="cacheReadInputToken">
186+
{t('Cache Read Token')}
187+
</SelectItem>
188+
<SelectItem value="cacheWriteInputToken">
189+
{t('Cache Write Token')}
179190
</SelectItem>
180191
<SelectItem value="price">{t('Price')}</SelectItem>
181192
</SelectContent>

src/client/components/aiGateway/AIGatewaySummaryStats.tsx

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export const AIGatewaySummaryStats: React.FC<AIGatewaySummaryStatsProps> =
2626
{ name: '$all_event', math: 'events' },
2727
{ name: 'inputToken', math: 'events' },
2828
{ name: 'outputToken', math: 'events' },
29-
{ name: 'cacheInputToken', math: 'events' },
29+
{ name: 'cacheReadInputToken', math: 'events' },
30+
{ name: 'cacheWriteInputToken', math: 'events' },
3031
{ name: 'price', math: 'events' },
3132
],
3233
filters: [],
@@ -44,30 +45,43 @@ export const AIGatewaySummaryStats: React.FC<AIGatewaySummaryStatsProps> =
4445
return [];
4546
}
4647

47-
return data.map((metric, index) => {
48-
const metricNames = [
49-
'$all_event',
50-
'inputToken',
51-
'outputToken',
52-
'cacheInputToken',
53-
'price',
54-
];
48+
const metricNames = [
49+
'$all_event',
50+
'inputToken',
51+
'outputToken',
52+
'cacheReadInputToken',
53+
'cacheWriteInputToken',
54+
'price',
55+
];
56+
const totals: Record<string, number> = {};
57+
data.forEach((metric, index) => {
5558
const counts = metric?.data || [];
56-
const total = counts.reduce((sum, item) => sum + item.value, 0);
57-
58-
return {
59-
name: metricNames[index],
60-
total,
61-
};
59+
totals[metricNames[index]] = counts.reduce(
60+
(sum, item) => sum + item.value,
61+
0
62+
);
6263
});
64+
65+
return [
66+
{ name: '$all_event', total: totals['$all_event'] ?? 0 },
67+
{
68+
name: 'inputToken',
69+
total:
70+
(totals['inputToken'] ?? 0) +
71+
(totals['cacheReadInputToken'] ?? 0) +
72+
(totals['cacheWriteInputToken'] ?? 0),
73+
},
74+
{ name: 'outputToken', total: totals['outputToken'] ?? 0 },
75+
{ name: 'price', total: totals['price'] ?? 0 },
76+
];
6377
},
6478
}
6579
);
6680

6781
return (
6882
<LoadingView isLoading={isLoading}>
6983
<div className="mb-6">
70-
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-5">
84+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
7185
{summaryData.map((metric) => {
7286
let label = '';
7387
let formattedValue = '';
@@ -85,10 +99,6 @@ export const AIGatewaySummaryStats: React.FC<AIGatewaySummaryStatsProps> =
8599
label = t('Total Output Tokens');
86100
formattedValue = metric.total.toLocaleString();
87101
break;
88-
case 'cacheInputToken':
89-
label = t('Total Cache Input Tokens');
90-
formattedValue = metric.total.toLocaleString();
91-
break;
92102
case 'price':
93103
label = t('Total Price');
94104
formattedValue = `$${metric.total.toFixed(4)}`;

src/client/components/aiGateway/useAIGatewayLogColumns.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,13 @@ export function useAIGatewayLogColumns(onRowSelect?: (index: number) => void) {
7575
size: 120,
7676
cell: (props) => renderNullableValue(props.getValue()),
7777
}),
78-
columnHelper.accessor('cacheInputToken', {
79-
header: t('Cache Input Tokens'),
78+
columnHelper.accessor('cacheReadInputToken', {
79+
header: t('Cache Read Tokens'),
80+
size: 140,
81+
cell: (props) => renderNullableValue(props.getValue()),
82+
}),
83+
columnHelper.accessor('cacheWriteInputToken', {
84+
header: t('Cache Write Tokens'),
8085
size: 140,
8186
cell: (props) => renderNullableValue(props.getValue()),
8287
}),

src/server/model/aiGateway.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ export function buildOpenAIHandler(
9595
stream,
9696
inputToken: 0,
9797
outputToken: 0,
98-
cacheInputToken: 0,
98+
cacheReadInputToken: 0,
99+
cacheWriteInputToken: 0,
99100
duration: 0,
100101
ttft: 0,
101102
requestPayload: payload,
@@ -181,8 +182,9 @@ export function buildOpenAIHandler(
181182
calcOpenAIToken(outputContent, modelName),
182183
]);
183184

184-
const cacheInputToken =
185+
const cacheReadInputToken =
185186
get(usage, ['prompt_tokens_details', 'cached_tokens']) ?? 0;
187+
const cacheWriteInputToken = 0;
186188

187189
const customInputPrice = gatewayInfo?.customModelInputPrice;
188190
const customOutputPrice = gatewayInfo?.customModelOutputPrice;
@@ -211,7 +213,9 @@ export function buildOpenAIHandler(
211213
modelProvider,
212214
modelPriceName,
213215
inputToken,
214-
outputToken
216+
outputToken,
217+
cacheReadInputToken,
218+
cacheWriteInputToken
215219
);
216220

217221
await prisma.aIGatewayLogs.update({
@@ -223,7 +227,8 @@ export function buildOpenAIHandler(
223227
modelName: responseModelName,
224228
inputToken,
225229
outputToken,
226-
cacheInputToken,
230+
cacheReadInputToken,
231+
cacheWriteInputToken,
227232
duration,
228233
ttft,
229234
price,
@@ -267,8 +272,9 @@ export function buildOpenAIHandler(
267272
: Promise.resolve(0)),
268273
]);
269274

270-
const cacheInputToken =
275+
const cacheReadInputToken =
271276
response.usage?.prompt_tokens_details?.cached_tokens ?? 0;
277+
const cacheWriteInputToken = 0;
272278

273279
const customInputPrice = gatewayInfo?.customModelInputPrice;
274280
const customOutputPrice = gatewayInfo?.customModelOutputPrice;
@@ -297,7 +303,9 @@ export function buildOpenAIHandler(
297303
modelProvider,
298304
modelPriceName,
299305
inputToken,
300-
outputToken
306+
outputToken,
307+
cacheReadInputToken,
308+
cacheWriteInputToken
301309
);
302310

303311
await prisma.aIGatewayLogs.update({
@@ -308,7 +316,8 @@ export function buildOpenAIHandler(
308316
status: AIGatewayLogsStatus.Success,
309317
inputToken,
310318
outputToken,
311-
cacheInputToken,
319+
cacheReadInputToken,
320+
cacheWriteInputToken,
312321
duration,
313322
modelName: responseModelName,
314323
price,
@@ -418,7 +427,8 @@ export function buildAnthropicHandler(
418427
stream,
419428
inputToken: 0,
420429
outputToken: 0,
421-
cacheInputToken: 0,
430+
cacheReadInputToken: 0,
431+
cacheWriteInputToken: 0,
422432
duration: 0,
423433
ttft: 0,
424434
requestPayload: payload,
@@ -492,7 +502,8 @@ export function buildAnthropicHandler(
492502

493503
let inputTokens = 0;
494504
let outputTokens = 0;
495-
let cacheInputTokens = 0;
505+
let cacheReadInputTokens = 0;
506+
let cacheWriteInputTokens = 0;
496507
let outputContent = '';
497508
let ttft = -1;
498509
let responseModelName = modelName;
@@ -534,9 +545,6 @@ export function buildAnthropicHandler(
534545
const data = JSON.parse(line.slice(6));
535546
if (currentEventType === 'message_start' && data.message) {
536547
responseModelName = data.message.model || responseModelName;
537-
cacheInputTokens =
538-
data.message.usage?.cache_read_input_tokens ||
539-
cacheInputTokens;
540548
} else if (currentEventType === 'content_block_delta') {
541549
if (ttft === -1) {
542550
ttft = Date.now() - start;
@@ -548,6 +556,12 @@ export function buildAnthropicHandler(
548556
usage = data.usage;
549557
inputTokens = usage?.input_tokens || inputTokens;
550558
outputTokens = usage?.output_tokens || outputTokens;
559+
cacheReadInputTokens =
560+
data.message.usage?.cache_read_input_tokens ||
561+
cacheReadInputTokens;
562+
cacheWriteInputTokens =
563+
data.message.usage?.cache_creation_input_tokens ||
564+
cacheWriteInputTokens;
551565
responseCost = usage?.cost;
552566
}
553567
} catch {
@@ -582,7 +596,9 @@ export function buildAnthropicHandler(
582596
modelProvider,
583597
modelName,
584598
inputTokens,
585-
outputTokens
599+
outputTokens,
600+
cacheReadInputTokens,
601+
cacheWriteInputTokens
586602
);
587603

588604
await prisma.aIGatewayLogs.update({
@@ -592,7 +608,8 @@ export function buildAnthropicHandler(
592608
modelName: responseModelName,
593609
inputToken: inputTokens,
594610
outputToken: outputTokens,
595-
cacheInputToken: cacheInputTokens,
611+
cacheReadInputToken: cacheReadInputTokens,
612+
cacheWriteInputToken: cacheWriteInputTokens,
596613
duration,
597614
ttft,
598615
price,
@@ -622,7 +639,9 @@ export function buildAnthropicHandler(
622639
const usage = responseBody.usage;
623640
const inputTokens = usage?.input_tokens || 0;
624641
const outputTokens = usage?.output_tokens || 0;
625-
const cacheInputTokens = usage?.cache_read_input_tokens || 0;
642+
const cacheReadInputTokens = usage?.cache_read_input_tokens || 0;
643+
const cacheWriteInputTokens =
644+
usage?.cache_creation_input_tokens || 0;
626645
const responseCost = usage?.cost;
627646

628647
const contentBlocks = responseBody.content || [];
@@ -648,7 +667,9 @@ export function buildAnthropicHandler(
648667
modelProvider,
649668
modelName,
650669
inputTokens,
651-
outputTokens
670+
outputTokens,
671+
cacheReadInputTokens,
672+
cacheWriteInputTokens
652673
);
653674

654675
await prisma.aIGatewayLogs.update({
@@ -658,7 +679,8 @@ export function buildAnthropicHandler(
658679
modelName: responseModelName,
659680
inputToken: inputTokens,
660681
outputToken: outputTokens,
661-
cacheInputToken: cacheInputTokens,
682+
cacheReadInputToken: cacheReadInputTokens,
683+
cacheWriteInputToken: cacheWriteInputTokens,
662684
duration,
663685
price,
664686
responsePayload: {

src/server/model/insights/aiGateway.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ export class AIGatewayInsightsSqlBuilder extends InsightsSqlBuilder {
2727
[
2828
'inputToken',
2929
'outputToken',
30-
'cacheInputToken',
30+
'cacheReadInputToken',
31+
'cacheWriteInputToken',
3132
'price',
3233
'duration',
3334
'ttft',
@@ -124,7 +125,8 @@ export class AIGatewayInsightsSqlBuilder extends InsightsSqlBuilder {
124125
'stream',
125126
'inputToken',
126127
'outputToken',
127-
'cacheInputToken',
128+
'cacheReadInputToken',
129+
'cacheWriteInputToken',
128130
'duration',
129131
'ttft',
130132
'price',
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- AlterTable: Rename cacheInputToken to cacheReadInputToken and add cacheWriteInputToken
2+
ALTER TABLE "AIGatewayLogs" RENAME COLUMN "cacheInputToken" TO "cacheReadInputToken";
3+
ALTER TABLE "AIGatewayLogs" ADD COLUMN "cacheWriteInputToken" INTEGER NOT NULL DEFAULT 0;

src/server/prisma/schema.prisma

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,8 @@ model AIGatewayLogs {
977977
gatewayId String @db.VarChar(30)
978978
inputToken Int @default(0) @db.Integer
979979
outputToken Int @default(0) @db.Integer
980-
cacheInputToken Int @default(0) @db.Integer
980+
cacheReadInputToken Int @default(0) @db.Integer
981+
cacheWriteInputToken Int @default(0) @db.Integer
981982
stream Boolean @default(false) @db.Boolean // stream response or not
982983
modelName String
983984
status AIGatewayLogsStatus

src/server/prisma/zod/aigatewaylogs.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export const AIGatewayLogsModelSchema = z.object({
3030
gatewayId: z.string(),
3131
inputToken: z.number().int(),
3232
outputToken: z.number().int(),
33-
cacheInputToken: z.number().int().default(0),
33+
cacheReadInputToken: z.number().int().default(0),
34+
cacheWriteInputToken: z.number().int().default(0),
3435
stream: z.boolean(),
3536
modelName: z.string(),
3637
status: z.nativeEnum(AIGatewayLogsStatus),

0 commit comments

Comments
 (0)