fix: Cache Token拆分为缓存创建和缓存读取
This commit is contained in:
@@ -57,25 +57,28 @@ type DashboardStats struct {
|
|||||||
|
|
||||||
// TrendDataPoint represents a single point in trend data
|
// TrendDataPoint represents a single point in trend data
|
||||||
type TrendDataPoint struct {
|
type TrendDataPoint struct {
|
||||||
Date string `json:"date"`
|
Date string `json:"date"`
|
||||||
Requests int64 `json:"requests"`
|
Requests int64 `json:"requests"`
|
||||||
InputTokens int64 `json:"input_tokens"`
|
InputTokens int64 `json:"input_tokens"`
|
||||||
OutputTokens int64 `json:"output_tokens"`
|
OutputTokens int64 `json:"output_tokens"`
|
||||||
CacheTokens int64 `json:"cache_tokens"`
|
CacheCreationTokens int64 `json:"cache_creation_tokens"`
|
||||||
TotalTokens int64 `json:"total_tokens"`
|
CacheReadTokens int64 `json:"cache_read_tokens"`
|
||||||
Cost float64 `json:"cost"` // 标准计费
|
TotalTokens int64 `json:"total_tokens"`
|
||||||
ActualCost float64 `json:"actual_cost"` // 实际扣除
|
Cost float64 `json:"cost"` // 标准计费
|
||||||
|
ActualCost float64 `json:"actual_cost"` // 实际扣除
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModelStat represents usage statistics for a single model
|
// ModelStat represents usage statistics for a single model
|
||||||
type ModelStat struct {
|
type ModelStat struct {
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
Requests int64 `json:"requests"`
|
Requests int64 `json:"requests"`
|
||||||
InputTokens int64 `json:"input_tokens"`
|
InputTokens int64 `json:"input_tokens"`
|
||||||
OutputTokens int64 `json:"output_tokens"`
|
OutputTokens int64 `json:"output_tokens"`
|
||||||
TotalTokens int64 `json:"total_tokens"`
|
CacheCreationTokens int64 `json:"cache_creation_tokens"`
|
||||||
Cost float64 `json:"cost"` // 标准计费
|
CacheReadTokens int64 `json:"cache_read_tokens"`
|
||||||
ActualCost float64 `json:"actual_cost"` // 实际扣除
|
TotalTokens int64 `json:"total_tokens"`
|
||||||
|
Cost float64 `json:"cost"` // 标准计费
|
||||||
|
ActualCost float64 `json:"actual_cost"` // 实际扣除
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupStat represents usage statistics for a single group
|
// GroupStat represents usage statistics for a single group
|
||||||
|
|||||||
@@ -1363,7 +1363,8 @@ func (r *usageLogRepository) GetUserUsageTrendByUserID(ctx context.Context, user
|
|||||||
COUNT(*) as requests,
|
COUNT(*) as requests,
|
||||||
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
||||||
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
||||||
COALESCE(SUM(cache_creation_tokens + cache_read_tokens), 0) as cache_tokens,
|
COALESCE(SUM(cache_creation_tokens), 0) as cache_creation_tokens,
|
||||||
|
COALESCE(SUM(cache_read_tokens), 0) as cache_read_tokens,
|
||||||
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
||||||
COALESCE(SUM(total_cost), 0) as cost,
|
COALESCE(SUM(total_cost), 0) as cost,
|
||||||
COALESCE(SUM(actual_cost), 0) as actual_cost
|
COALESCE(SUM(actual_cost), 0) as actual_cost
|
||||||
@@ -1401,6 +1402,8 @@ func (r *usageLogRepository) GetUserModelStats(ctx context.Context, userID int64
|
|||||||
COUNT(*) as requests,
|
COUNT(*) as requests,
|
||||||
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
||||||
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
||||||
|
COALESCE(SUM(cache_creation_tokens), 0) as cache_creation_tokens,
|
||||||
|
COALESCE(SUM(cache_read_tokens), 0) as cache_read_tokens,
|
||||||
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
||||||
COALESCE(SUM(total_cost), 0) as cost,
|
COALESCE(SUM(total_cost), 0) as cost,
|
||||||
COALESCE(SUM(actual_cost), 0) as actual_cost
|
COALESCE(SUM(actual_cost), 0) as actual_cost
|
||||||
@@ -1664,7 +1667,8 @@ func (r *usageLogRepository) GetUsageTrendWithFilters(ctx context.Context, start
|
|||||||
COUNT(*) as requests,
|
COUNT(*) as requests,
|
||||||
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
||||||
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
||||||
COALESCE(SUM(cache_creation_tokens + cache_read_tokens), 0) as cache_tokens,
|
COALESCE(SUM(cache_creation_tokens), 0) as cache_creation_tokens,
|
||||||
|
COALESCE(SUM(cache_read_tokens), 0) as cache_read_tokens,
|
||||||
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
||||||
COALESCE(SUM(total_cost), 0) as cost,
|
COALESCE(SUM(total_cost), 0) as cost,
|
||||||
COALESCE(SUM(actual_cost), 0) as actual_cost
|
COALESCE(SUM(actual_cost), 0) as actual_cost
|
||||||
@@ -1747,7 +1751,8 @@ func (r *usageLogRepository) getUsageTrendFromAggregates(ctx context.Context, st
|
|||||||
total_requests as requests,
|
total_requests as requests,
|
||||||
input_tokens,
|
input_tokens,
|
||||||
output_tokens,
|
output_tokens,
|
||||||
(cache_creation_tokens + cache_read_tokens) as cache_tokens,
|
cache_creation_tokens,
|
||||||
|
cache_read_tokens,
|
||||||
(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens) as total_tokens,
|
(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens) as total_tokens,
|
||||||
total_cost as cost,
|
total_cost as cost,
|
||||||
actual_cost
|
actual_cost
|
||||||
@@ -1762,7 +1767,8 @@ func (r *usageLogRepository) getUsageTrendFromAggregates(ctx context.Context, st
|
|||||||
total_requests as requests,
|
total_requests as requests,
|
||||||
input_tokens,
|
input_tokens,
|
||||||
output_tokens,
|
output_tokens,
|
||||||
(cache_creation_tokens + cache_read_tokens) as cache_tokens,
|
cache_creation_tokens,
|
||||||
|
cache_read_tokens,
|
||||||
(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens) as total_tokens,
|
(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens) as total_tokens,
|
||||||
total_cost as cost,
|
total_cost as cost,
|
||||||
actual_cost
|
actual_cost
|
||||||
@@ -1806,6 +1812,8 @@ func (r *usageLogRepository) GetModelStatsWithFilters(ctx context.Context, start
|
|||||||
COUNT(*) as requests,
|
COUNT(*) as requests,
|
||||||
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
COALESCE(SUM(input_tokens), 0) as input_tokens,
|
||||||
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
COALESCE(SUM(output_tokens), 0) as output_tokens,
|
||||||
|
COALESCE(SUM(cache_creation_tokens), 0) as cache_creation_tokens,
|
||||||
|
COALESCE(SUM(cache_read_tokens), 0) as cache_read_tokens,
|
||||||
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
COALESCE(SUM(input_tokens + output_tokens + cache_creation_tokens + cache_read_tokens), 0) as total_tokens,
|
||||||
COALESCE(SUM(total_cost), 0) as cost,
|
COALESCE(SUM(total_cost), 0) as cost,
|
||||||
%s
|
%s
|
||||||
@@ -2622,7 +2630,8 @@ func scanTrendRows(rows *sql.Rows) ([]TrendDataPoint, error) {
|
|||||||
&row.Requests,
|
&row.Requests,
|
||||||
&row.InputTokens,
|
&row.InputTokens,
|
||||||
&row.OutputTokens,
|
&row.OutputTokens,
|
||||||
&row.CacheTokens,
|
&row.CacheCreationTokens,
|
||||||
|
&row.CacheReadTokens,
|
||||||
&row.TotalTokens,
|
&row.TotalTokens,
|
||||||
&row.Cost,
|
&row.Cost,
|
||||||
&row.ActualCost,
|
&row.ActualCost,
|
||||||
@@ -2646,6 +2655,8 @@ func scanModelStatsRows(rows *sql.Rows) ([]ModelStat, error) {
|
|||||||
&row.Requests,
|
&row.Requests,
|
||||||
&row.InputTokens,
|
&row.InputTokens,
|
||||||
&row.OutputTokens,
|
&row.OutputTokens,
|
||||||
|
&row.CacheCreationTokens,
|
||||||
|
&row.CacheReadTokens,
|
||||||
&row.TotalTokens,
|
&row.TotalTokens,
|
||||||
&row.Cost,
|
&row.Cost,
|
||||||
&row.ActualCost,
|
&row.ActualCost,
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func TestUsageLogRepositoryGetUsageTrendWithFiltersRequestTypePriority(t *testin
|
|||||||
|
|
||||||
mock.ExpectQuery("AND \\(request_type = \\$3 OR \\(request_type = 0 AND stream = TRUE AND openai_ws_mode = FALSE\\)\\)").
|
mock.ExpectQuery("AND \\(request_type = \\$3 OR \\(request_type = 0 AND stream = TRUE AND openai_ws_mode = FALSE\\)\\)").
|
||||||
WithArgs(start, end, requestType).
|
WithArgs(start, end, requestType).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"date", "requests", "input_tokens", "output_tokens", "cache_tokens", "total_tokens", "cost", "actual_cost"}))
|
WillReturnRows(sqlmock.NewRows([]string{"date", "requests", "input_tokens", "output_tokens", "cache_creation_tokens", "cache_read_tokens", "total_tokens", "cost", "actual_cost"}))
|
||||||
|
|
||||||
trend, err := repo.GetUsageTrendWithFilters(context.Background(), start, end, "day", 0, 0, 0, 0, "", &requestType, &stream, nil)
|
trend, err := repo.GetUsageTrendWithFilters(context.Background(), start, end, "day", 0, 0, 0, 0, "", &requestType, &stream, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -144,7 +144,7 @@ func TestUsageLogRepositoryGetModelStatsWithFiltersRequestTypePriority(t *testin
|
|||||||
|
|
||||||
mock.ExpectQuery("AND \\(request_type = \\$3 OR \\(request_type = 0 AND openai_ws_mode = TRUE\\)\\)").
|
mock.ExpectQuery("AND \\(request_type = \\$3 OR \\(request_type = 0 AND openai_ws_mode = TRUE\\)\\)").
|
||||||
WithArgs(start, end, requestType).
|
WithArgs(start, end, requestType).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"model", "requests", "input_tokens", "output_tokens", "total_tokens", "cost", "actual_cost"}))
|
WillReturnRows(sqlmock.NewRows([]string{"model", "requests", "input_tokens", "output_tokens", "cache_creation_tokens", "cache_read_tokens", "total_tokens", "cost", "actual_cost"}))
|
||||||
|
|
||||||
stats, err := repo.GetModelStatsWithFilters(context.Background(), start, end, 0, 0, 0, 0, &requestType, &stream, nil)
|
stats, err := repo.GetModelStatsWithFilters(context.Background(), start, end, 0, 0, 0, 0, &requestType, &stream, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ const chartColors = computed(() => ({
|
|||||||
grid: isDarkMode.value ? '#374151' : '#e5e7eb',
|
grid: isDarkMode.value ? '#374151' : '#e5e7eb',
|
||||||
input: '#3b82f6',
|
input: '#3b82f6',
|
||||||
output: '#10b981',
|
output: '#10b981',
|
||||||
cache: '#f59e0b'
|
cacheCreation: '#f59e0b',
|
||||||
|
cacheRead: '#06b6d4'
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const chartData = computed(() => {
|
const chartData = computed(() => {
|
||||||
@@ -89,10 +90,18 @@ const chartData = computed(() => {
|
|||||||
tension: 0.3
|
tension: 0.3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Cache',
|
label: 'Cache Creation',
|
||||||
data: props.trendData.map((d) => d.cache_tokens),
|
data: props.trendData.map((d) => d.cache_creation_tokens),
|
||||||
borderColor: chartColors.value.cache,
|
borderColor: chartColors.value.cacheCreation,
|
||||||
backgroundColor: `${chartColors.value.cache}20`,
|
backgroundColor: `${chartColors.value.cacheCreation}20`,
|
||||||
|
fill: true,
|
||||||
|
tension: 0.3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Cache Read',
|
||||||
|
data: props.trendData.map((d) => d.cache_read_tokens),
|
||||||
|
borderColor: chartColors.value.cacheRead,
|
||||||
|
backgroundColor: `${chartColors.value.cacheRead}20`,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.3
|
tension: 0.3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ export default {
|
|||||||
requests: 'Requests',
|
requests: 'Requests',
|
||||||
inputTokens: 'Input Tokens',
|
inputTokens: 'Input Tokens',
|
||||||
outputTokens: 'Output Tokens',
|
outputTokens: 'Output Tokens',
|
||||||
|
cacheCreationTokens: 'Cache Creation',
|
||||||
|
cacheReadTokens: 'Cache Read',
|
||||||
totalTokens: 'Total Tokens',
|
totalTokens: 'Total Tokens',
|
||||||
cost: 'Cost',
|
cost: 'Cost',
|
||||||
// Status
|
// Status
|
||||||
@@ -155,11 +157,19 @@ export default {
|
|||||||
subscriptionExpires: 'Subscription Expires',
|
subscriptionExpires: 'Subscription Expires',
|
||||||
// Usage stat cells
|
// Usage stat cells
|
||||||
todayRequests: 'Today Requests',
|
todayRequests: 'Today Requests',
|
||||||
|
todayInputTokens: 'Today Input',
|
||||||
|
todayOutputTokens: 'Today Output',
|
||||||
todayTokens: 'Today Tokens',
|
todayTokens: 'Today Tokens',
|
||||||
|
todayCacheCreation: 'Today Cache Creation',
|
||||||
|
todayCacheRead: 'Today Cache Read',
|
||||||
todayCost: 'Today Cost',
|
todayCost: 'Today Cost',
|
||||||
rpmTpm: 'RPM / TPM',
|
rpmTpm: 'RPM / TPM',
|
||||||
totalRequests: 'Total Requests',
|
totalRequests: 'Total Requests',
|
||||||
|
totalInputTokens: 'Total Input',
|
||||||
|
totalOutputTokens: 'Total Output',
|
||||||
totalTokensLabel: 'Total Tokens',
|
totalTokensLabel: 'Total Tokens',
|
||||||
|
totalCacheCreation: 'Total Cache Creation',
|
||||||
|
totalCacheRead: 'Total Cache Read',
|
||||||
totalCost: 'Total Cost',
|
totalCost: 'Total Cost',
|
||||||
avgDuration: 'Avg Duration',
|
avgDuration: 'Avg Duration',
|
||||||
// Messages
|
// Messages
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ export default {
|
|||||||
requests: '请求数',
|
requests: '请求数',
|
||||||
inputTokens: '输入 Tokens',
|
inputTokens: '输入 Tokens',
|
||||||
outputTokens: '输出 Tokens',
|
outputTokens: '输出 Tokens',
|
||||||
|
cacheCreationTokens: '缓存创建',
|
||||||
|
cacheReadTokens: '缓存读取',
|
||||||
totalTokens: '总 Tokens',
|
totalTokens: '总 Tokens',
|
||||||
cost: '费用',
|
cost: '费用',
|
||||||
// Status
|
// Status
|
||||||
@@ -155,11 +157,19 @@ export default {
|
|||||||
subscriptionExpires: '订阅到期',
|
subscriptionExpires: '订阅到期',
|
||||||
// Usage stat cells
|
// Usage stat cells
|
||||||
todayRequests: '今日请求',
|
todayRequests: '今日请求',
|
||||||
|
todayInputTokens: '今日输入',
|
||||||
|
todayOutputTokens: '今日输出',
|
||||||
todayTokens: '今日 Tokens',
|
todayTokens: '今日 Tokens',
|
||||||
|
todayCacheCreation: '今日缓存创建',
|
||||||
|
todayCacheRead: '今日缓存读取',
|
||||||
todayCost: '今日费用',
|
todayCost: '今日费用',
|
||||||
rpmTpm: 'RPM / TPM',
|
rpmTpm: 'RPM / TPM',
|
||||||
totalRequests: '累计请求',
|
totalRequests: '累计请求',
|
||||||
|
totalInputTokens: '累计输入',
|
||||||
|
totalOutputTokens: '累计输出',
|
||||||
totalTokensLabel: '累计 Tokens',
|
totalTokensLabel: '累计 Tokens',
|
||||||
|
totalCacheCreation: '累计缓存创建',
|
||||||
|
totalCacheRead: '累计缓存读取',
|
||||||
totalCost: '累计费用',
|
totalCost: '累计费用',
|
||||||
avgDuration: '平均耗时',
|
avgDuration: '平均耗时',
|
||||||
// Messages
|
// Messages
|
||||||
|
|||||||
@@ -1098,7 +1098,8 @@ export interface TrendDataPoint {
|
|||||||
requests: number
|
requests: number
|
||||||
input_tokens: number
|
input_tokens: number
|
||||||
output_tokens: number
|
output_tokens: number
|
||||||
cache_tokens: number
|
cache_creation_tokens: number
|
||||||
|
cache_read_tokens: number
|
||||||
total_tokens: number
|
total_tokens: number
|
||||||
cost: number // 标准计费
|
cost: number // 标准计费
|
||||||
actual_cost: number // 实际扣除
|
actual_cost: number // 实际扣除
|
||||||
@@ -1109,6 +1110,8 @@ export interface ModelStat {
|
|||||||
requests: number
|
requests: number
|
||||||
input_tokens: number
|
input_tokens: number
|
||||||
output_tokens: number
|
output_tokens: number
|
||||||
|
cache_creation_tokens: number
|
||||||
|
cache_read_tokens: number
|
||||||
total_tokens: number
|
total_tokens: number
|
||||||
cost: number // 标准计费
|
cost: number // 标准计费
|
||||||
actual_cost: number // 实际扣除
|
actual_cost: number // 实际扣除
|
||||||
|
|||||||
@@ -302,6 +302,8 @@
|
|||||||
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.requests') }}</th>
|
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.requests') }}</th>
|
||||||
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.inputTokens') }}</th>
|
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.inputTokens') }}</th>
|
||||||
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.outputTokens') }}</th>
|
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.outputTokens') }}</th>
|
||||||
|
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.cacheCreationTokens') }}</th>
|
||||||
|
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.cacheReadTokens') }}</th>
|
||||||
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.totalTokens') }}</th>
|
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.totalTokens') }}</th>
|
||||||
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.cost') }}</th>
|
<th class="px-4 py-3 text-right text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-dark-400">{{ t('keyUsage.cost') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -316,6 +318,8 @@
|
|||||||
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.requests) }}</td>
|
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.requests) }}</td>
|
||||||
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.input_tokens) }}</td>
|
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.input_tokens) }}</td>
|
||||||
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.output_tokens) }}</td>
|
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.output_tokens) }}</td>
|
||||||
|
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.cache_creation_tokens) }}</td>
|
||||||
|
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.cache_read_tokens) }}</td>
|
||||||
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.total_tokens) }}</td>
|
<td class="px-4 py-3 text-sm tabular-nums text-right text-gray-700 dark:text-dark-200">{{ fmtNum(m.total_tokens) }}</td>
|
||||||
<td class="px-4 py-3 text-sm tabular-nums text-right font-medium text-gray-900 dark:text-white">{{ usd(m.actual_cost != null ? m.actual_cost : m.cost) }}</td>
|
<td class="px-4 py-3 text-sm tabular-nums text-right font-medium text-gray-900 dark:text-white">{{ usd(m.actual_cost != null ? m.actual_cost : m.cost) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -694,11 +698,19 @@ const usageStatCells = computed<StatCell[]>(() => {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
{ label: t('keyUsage.todayRequests'), value: fmtNum(today.requests) },
|
{ label: t('keyUsage.todayRequests'), value: fmtNum(today.requests) },
|
||||||
|
{ label: t('keyUsage.todayInputTokens'), value: fmtNum(today.input_tokens) },
|
||||||
|
{ label: t('keyUsage.todayOutputTokens'), value: fmtNum(today.output_tokens) },
|
||||||
{ label: t('keyUsage.todayTokens'), value: fmtNum(today.total_tokens) },
|
{ label: t('keyUsage.todayTokens'), value: fmtNum(today.total_tokens) },
|
||||||
|
{ label: t('keyUsage.todayCacheCreation'), value: fmtNum(today.cache_creation_tokens) },
|
||||||
|
{ label: t('keyUsage.todayCacheRead'), value: fmtNum(today.cache_read_tokens) },
|
||||||
{ label: t('keyUsage.todayCost'), value: usd(today.actual_cost) },
|
{ label: t('keyUsage.todayCost'), value: usd(today.actual_cost) },
|
||||||
{ label: t('keyUsage.rpmTpm'), value: `${usage.rpm || 0} / ${usage.tpm || 0}` },
|
{ label: t('keyUsage.rpmTpm'), value: `${usage.rpm || 0} / ${usage.tpm || 0}` },
|
||||||
{ label: t('keyUsage.totalRequests'), value: fmtNum(total.requests) },
|
{ label: t('keyUsage.totalRequests'), value: fmtNum(total.requests) },
|
||||||
|
{ label: t('keyUsage.totalInputTokens'), value: fmtNum(total.input_tokens) },
|
||||||
|
{ label: t('keyUsage.totalOutputTokens'), value: fmtNum(total.output_tokens) },
|
||||||
{ label: t('keyUsage.totalTokensLabel'), value: fmtNum(total.total_tokens) },
|
{ label: t('keyUsage.totalTokensLabel'), value: fmtNum(total.total_tokens) },
|
||||||
|
{ label: t('keyUsage.totalCacheCreation'), value: fmtNum(total.cache_creation_tokens) },
|
||||||
|
{ label: t('keyUsage.totalCacheRead'), value: fmtNum(total.cache_read_tokens) },
|
||||||
{ label: t('keyUsage.totalCost'), value: usd(total.actual_cost) },
|
{ label: t('keyUsage.totalCost'), value: usd(total.actual_cost) },
|
||||||
{ label: t('keyUsage.avgDuration'), value: usage.average_duration_ms ? `${Math.round(usage.average_duration_ms)} ms` : '-' },
|
{ label: t('keyUsage.avgDuration'), value: usage.average_duration_ms ? `${Math.round(usage.average_duration_ms)} ms` : '-' },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -113,6 +113,9 @@
|
|||||||
|
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<div class="ml-auto flex items-center gap-3">
|
<div class="ml-auto flex items-center gap-3">
|
||||||
|
<button @click="applyFilters" :disabled="loading" class="btn btn-secondary">
|
||||||
|
{{ t('common.refresh') }}
|
||||||
|
</button>
|
||||||
<button @click="resetFilters" class="btn btn-secondary">
|
<button @click="resetFilters" class="btn btn-secondary">
|
||||||
{{ t('common.reset') }}
|
{{ t('common.reset') }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user