mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-18 02:30:51 +08:00
feat(ui): show success/failure in API usage stats
This commit is contained in:
@@ -39,10 +39,18 @@ export function ApiDetailsCard({ apiStats, loading, hasPrices }: ApiDetailsCardP
|
||||
<span className={styles.apiEndpoint}>{api.endpoint}</span>
|
||||
<div className={styles.apiStats}>
|
||||
<span className={styles.apiBadge}>
|
||||
{t('usage_stats.requests_count')}: {api.totalRequests}
|
||||
<span className={styles.requestCountCell}>
|
||||
<span>
|
||||
{t('usage_stats.requests_count')}: {api.totalRequests.toLocaleString()}
|
||||
</span>
|
||||
<span className={styles.requestBreakdown}>
|
||||
(<span className={styles.statSuccess}>{api.successCount.toLocaleString()}</span>{' '}
|
||||
<span className={styles.statFailure}>{api.failureCount.toLocaleString()}</span>)
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className={styles.apiBadge}>
|
||||
Tokens: {formatTokensInMillions(api.totalTokens)}
|
||||
{t('usage_stats.tokens_count')}: {formatTokensInMillions(api.totalTokens)}
|
||||
</span>
|
||||
{hasPrices && api.totalCost > 0 && (
|
||||
<span className={styles.apiBadge}>
|
||||
@@ -61,7 +69,13 @@ export function ApiDetailsCard({ apiStats, loading, hasPrices }: ApiDetailsCardP
|
||||
<div key={model} className={styles.modelRow}>
|
||||
<span className={styles.modelName}>{model}</span>
|
||||
<span className={styles.modelStat}>
|
||||
{stats.requests} {t('usage_stats.requests_count')}
|
||||
<span className={styles.requestCountCell}>
|
||||
<span>{stats.requests.toLocaleString()}</span>
|
||||
<span className={styles.requestBreakdown}>
|
||||
(<span className={styles.statSuccess}>{stats.successCount.toLocaleString()}</span>{' '}
|
||||
<span className={styles.statFailure}>{stats.failureCount.toLocaleString()}</span>)
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className={styles.modelStat}>{formatTokensInMillions(stats.tokens)}</span>
|
||||
</div>
|
||||
|
||||
@@ -54,9 +54,11 @@ export interface UsageDetail {
|
||||
export interface ApiStats {
|
||||
endpoint: string;
|
||||
totalRequests: number;
|
||||
successCount: number;
|
||||
failureCount: number;
|
||||
totalTokens: number;
|
||||
totalCost: number;
|
||||
models: Record<string, { requests: number; tokens: number }>;
|
||||
models: Record<string, { requests: number; successCount: number; failureCount: number; tokens: number }>;
|
||||
}
|
||||
|
||||
const TOKENS_PER_PRICE_UNIT = 1_000_000;
|
||||
@@ -542,28 +544,65 @@ export function getApiStats(usageData: any, modelPrices: Record<string, ModelPri
|
||||
const result: ApiStats[] = [];
|
||||
|
||||
Object.entries(apis as Record<string, any>).forEach(([endpoint, apiData]) => {
|
||||
const models: Record<string, { requests: number; tokens: number }> = {};
|
||||
const models: Record<string, { requests: number; successCount: number; failureCount: number; tokens: number }> = {};
|
||||
let derivedSuccessCount = 0;
|
||||
let derivedFailureCount = 0;
|
||||
let totalCost = 0;
|
||||
|
||||
const modelsData = apiData?.models || {};
|
||||
Object.entries(modelsData as Record<string, any>).forEach(([modelName, modelData]) => {
|
||||
models[modelName] = {
|
||||
requests: modelData.total_requests || 0,
|
||||
tokens: modelData.total_tokens || 0
|
||||
};
|
||||
const details = Array.isArray(modelData.details) ? modelData.details : [];
|
||||
const hasExplicitCounts =
|
||||
typeof modelData.success_count === 'number' || typeof modelData.failure_count === 'number';
|
||||
|
||||
let successCount = 0;
|
||||
let failureCount = 0;
|
||||
if (hasExplicitCounts) {
|
||||
successCount += Number(modelData.success_count) || 0;
|
||||
failureCount += Number(modelData.failure_count) || 0;
|
||||
}
|
||||
|
||||
const price = modelPrices[modelName];
|
||||
if (price) {
|
||||
const details = Array.isArray(modelData.details) ? modelData.details : [];
|
||||
if (details.length > 0 && (!hasExplicitCounts || price)) {
|
||||
details.forEach((detail: any) => {
|
||||
totalCost += calculateCost({ ...detail, __modelName: modelName }, modelPrices);
|
||||
if (!hasExplicitCounts) {
|
||||
if (detail?.failed === true) {
|
||||
failureCount += 1;
|
||||
} else {
|
||||
successCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (price) {
|
||||
totalCost += calculateCost({ ...detail, __modelName: modelName }, modelPrices);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
models[modelName] = {
|
||||
requests: modelData.total_requests || 0,
|
||||
successCount,
|
||||
failureCount,
|
||||
tokens: modelData.total_tokens || 0
|
||||
};
|
||||
derivedSuccessCount += successCount;
|
||||
derivedFailureCount += failureCount;
|
||||
});
|
||||
|
||||
const hasApiExplicitCounts =
|
||||
typeof apiData?.success_count === 'number' || typeof apiData?.failure_count === 'number';
|
||||
const successCount = hasApiExplicitCounts
|
||||
? (Number(apiData?.success_count) || 0)
|
||||
: derivedSuccessCount;
|
||||
const failureCount = hasApiExplicitCounts
|
||||
? (Number(apiData?.failure_count) || 0)
|
||||
: derivedFailureCount;
|
||||
|
||||
result.push({
|
||||
endpoint: maskUsageSensitiveValue(endpoint) || endpoint,
|
||||
totalRequests: apiData.total_requests || 0,
|
||||
successCount,
|
||||
failureCount,
|
||||
totalTokens: apiData.total_tokens || 0,
|
||||
totalCost,
|
||||
models
|
||||
|
||||
Reference in New Issue
Block a user