fix(monitor): fix statistics logic issues in monitor charts
Changes: - Fix hourly token chart incorrectly counting failed request tokens - Fix daily trend chart using UTC date causing cross-day statistics errors - Daily trend chart now distinguishes success/failed request counts - Token statistics only count successful requests for more accurate data Modified files: - src/components/monitor/DailyTrendChart.tsx (modified) - src/components/monitor/HourlyTokenChart.tsx (modified) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,8 @@ interface DailyTrendChartProps {
|
||||
interface DailyStat {
|
||||
date: string;
|
||||
requests: number;
|
||||
successRequests: number;
|
||||
failedRequests: number;
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
reasoningTokens: number;
|
||||
@@ -29,19 +31,33 @@ export function DailyTrendChart({ data, loading, isDark, timeRange }: DailyTrend
|
||||
|
||||
const dailyStats: Record<string, {
|
||||
requests: number;
|
||||
successRequests: number;
|
||||
failedRequests: number;
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
reasoningTokens: number;
|
||||
cachedTokens: number;
|
||||
}> = {};
|
||||
|
||||
// 辅助函数:获取本地日期字符串 YYYY-MM-DD
|
||||
const getLocalDateString = (timestamp: string): string => {
|
||||
const date = new Date(timestamp);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
Object.values(data.apis).forEach((apiData) => {
|
||||
Object.values(apiData.models).forEach((modelData) => {
|
||||
modelData.details.forEach((detail) => {
|
||||
const date = new Date(detail.timestamp).toISOString().split('T')[0];
|
||||
// 使用本地日期而非 UTC 日期
|
||||
const date = getLocalDateString(detail.timestamp);
|
||||
if (!dailyStats[date]) {
|
||||
dailyStats[date] = {
|
||||
requests: 0,
|
||||
successRequests: 0,
|
||||
failedRequests: 0,
|
||||
inputTokens: 0,
|
||||
outputTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
@@ -49,10 +65,16 @@ export function DailyTrendChart({ data, loading, isDark, timeRange }: DailyTrend
|
||||
};
|
||||
}
|
||||
dailyStats[date].requests++;
|
||||
dailyStats[date].inputTokens += detail.tokens.input_tokens || 0;
|
||||
dailyStats[date].outputTokens += detail.tokens.output_tokens || 0;
|
||||
dailyStats[date].reasoningTokens += detail.tokens.reasoning_tokens || 0;
|
||||
dailyStats[date].cachedTokens += detail.tokens.cached_tokens || 0;
|
||||
if (detail.failed) {
|
||||
dailyStats[date].failedRequests++;
|
||||
} else {
|
||||
dailyStats[date].successRequests++;
|
||||
// 只统计成功请求的 Token
|
||||
dailyStats[date].inputTokens += detail.tokens.input_tokens || 0;
|
||||
dailyStats[date].outputTokens += detail.tokens.output_tokens || 0;
|
||||
dailyStats[date].reasoningTokens += detail.tokens.reasoning_tokens || 0;
|
||||
dailyStats[date].cachedTokens += detail.tokens.cached_tokens || 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,10 +48,13 @@ export function HourlyTokenChart({ data, loading, isDark }: HourlyTokenChartProp
|
||||
hourlyStats[hour] = { total: 0, input: 0, output: 0, reasoning: 0, cached: 0 };
|
||||
});
|
||||
|
||||
// 收集每小时的 Token 数据
|
||||
// 收集每小时的 Token 数据(只统计成功请求)
|
||||
Object.values(data.apis).forEach((apiData) => {
|
||||
Object.values(apiData.models).forEach((modelData) => {
|
||||
modelData.details.forEach((detail) => {
|
||||
// 跳过失败请求,失败请求的 Token 数据不准确
|
||||
if (detail.failed) return;
|
||||
|
||||
const timestamp = new Date(detail.timestamp);
|
||||
if (timestamp < cutoffTime) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user