mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-15 09:12:18 +00:00
Merge f77102c9ff into 527d882508
This commit is contained in:
commit
f9dc5c8d29
3 changed files with 82 additions and 45 deletions
|
|
@ -39,16 +39,17 @@ const EndpointUsage: React.FC<EndpointUsageProps> = ({ userSpendData }) => {
|
|||
api_key_breakdown: {},
|
||||
};
|
||||
}
|
||||
aggregatedEndpoints[endpoint].metrics.spend += metrics.metrics.spend;
|
||||
aggregatedEndpoints[endpoint].metrics.prompt_tokens += metrics.metrics.prompt_tokens;
|
||||
aggregatedEndpoints[endpoint].metrics.completion_tokens += metrics.metrics.completion_tokens;
|
||||
aggregatedEndpoints[endpoint].metrics.total_tokens += metrics.metrics.total_tokens;
|
||||
aggregatedEndpoints[endpoint].metrics.api_requests += metrics.metrics.api_requests;
|
||||
aggregatedEndpoints[endpoint].metrics.successful_requests += metrics.metrics.successful_requests || 0;
|
||||
aggregatedEndpoints[endpoint].metrics.failed_requests += metrics.metrics.failed_requests || 0;
|
||||
aggregatedEndpoints[endpoint].metrics.cache_read_input_tokens += metrics.metrics.cache_read_input_tokens || 0;
|
||||
aggregatedEndpoints[endpoint].metrics.spend += metrics.metrics?.spend ?? 0;
|
||||
aggregatedEndpoints[endpoint].metrics.prompt_tokens += metrics.metrics?.prompt_tokens ?? 0;
|
||||
aggregatedEndpoints[endpoint].metrics.completion_tokens += metrics.metrics?.completion_tokens ?? 0;
|
||||
aggregatedEndpoints[endpoint].metrics.total_tokens += metrics.metrics?.total_tokens ?? 0;
|
||||
aggregatedEndpoints[endpoint].metrics.api_requests += metrics.metrics?.api_requests ?? 0;
|
||||
aggregatedEndpoints[endpoint].metrics.successful_requests += (metrics.metrics?.successful_requests ?? 0) || 0;
|
||||
aggregatedEndpoints[endpoint].metrics.failed_requests += (metrics.metrics?.failed_requests ?? 0) || 0;
|
||||
aggregatedEndpoints[endpoint].metrics.cache_read_input_tokens +=
|
||||
(metrics.metrics?.cache_read_input_tokens ?? 0) || 0;
|
||||
aggregatedEndpoints[endpoint].metrics.cache_creation_input_tokens +=
|
||||
metrics.metrics.cache_creation_input_tokens || 0;
|
||||
(metrics.metrics?.cache_creation_input_tokens ?? 0) || 0;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { getGlobalTopKeys, getTopModels, getTopAgents } from "./entityUsageAggregations";
|
||||
import type { DailyData } from "@/components/UsagePage/types";
|
||||
|
||||
const partialDay = {
|
||||
date: "2026-09-01",
|
||||
breakdown: {
|
||||
models: { model: { metadata: {} } },
|
||||
api_keys: { key: { metadata: { key_alias: "test key" } } },
|
||||
entities: { agent: { metadata: { agent_name: "test agent" }, api_key_breakdown: {} } },
|
||||
},
|
||||
} as unknown as DailyData;
|
||||
|
||||
describe("partial breakdown metrics", () => {
|
||||
it("defaults missing global-key metrics to zero", () => {
|
||||
expect(getGlobalTopKeys([partialDay], 10)[0].spend).toBe(0);
|
||||
});
|
||||
it("defaults missing model metrics to zero", () => {
|
||||
expect(getTopModels([partialDay], "models", 10)[0].tokens).toBe(0);
|
||||
});
|
||||
it("defaults missing agent metrics to zero", () => {
|
||||
expect(getTopAgents([partialDay], 10)[0].spend).toBe(0);
|
||||
});
|
||||
it("still sums populated days after a partial day", () => {
|
||||
const goodDay = {
|
||||
...partialDay,
|
||||
breakdown: {
|
||||
...partialDay.breakdown,
|
||||
api_keys: {
|
||||
key: { metadata: { key_alias: "test key" }, metrics: { spend: 5 } },
|
||||
},
|
||||
},
|
||||
} as unknown as DailyData;
|
||||
expect(getGlobalTopKeys([partialDay, goodDay], 10)[0].spend).toBe(5);
|
||||
});
|
||||
});
|
||||
|
|
@ -37,14 +37,14 @@ export const getTopModels = (
|
|||
};
|
||||
}
|
||||
try {
|
||||
modelSpend[model].spend += metrics.metrics.spend;
|
||||
modelSpend[model].spend += metrics.metrics?.spend ?? 0;
|
||||
} catch (e) {
|
||||
console.error(`Error adding spend for ${model}: ${e}, got metrics: ${JSON.stringify(metrics)}`);
|
||||
}
|
||||
modelSpend[model].requests += metrics.metrics.api_requests;
|
||||
modelSpend[model].successful_requests += metrics.metrics.successful_requests;
|
||||
modelSpend[model].failed_requests += metrics.metrics.failed_requests;
|
||||
modelSpend[model].tokens += metrics.metrics.total_tokens;
|
||||
modelSpend[model].requests += metrics.metrics?.api_requests ?? 0;
|
||||
modelSpend[model].successful_requests += metrics.metrics?.successful_requests ?? 0;
|
||||
modelSpend[model].failed_requests += metrics.metrics?.failed_requests ?? 0;
|
||||
modelSpend[model].tokens += metrics.metrics?.total_tokens ?? 0;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -71,11 +71,11 @@ export const getTopAgents = (results: ExtendedDailyData[], topAgentsLimit: numbe
|
|||
agent_name: (data.metadata as any)?.agent_name || agentId,
|
||||
};
|
||||
}
|
||||
agentSpend[agentId].spend += data.metrics.spend;
|
||||
agentSpend[agentId].requests += data.metrics.api_requests;
|
||||
agentSpend[agentId].successful_requests += data.metrics.successful_requests;
|
||||
agentSpend[agentId].failed_requests += data.metrics.failed_requests;
|
||||
agentSpend[agentId].tokens += data.metrics.total_tokens;
|
||||
agentSpend[agentId].spend += data.metrics?.spend ?? 0;
|
||||
agentSpend[agentId].requests += data.metrics?.api_requests ?? 0;
|
||||
agentSpend[agentId].successful_requests += data.metrics?.successful_requests ?? 0;
|
||||
agentSpend[agentId].failed_requests += data.metrics?.failed_requests ?? 0;
|
||||
agentSpend[agentId].tokens += data.metrics?.total_tokens ?? 0;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -115,15 +115,15 @@ export const getGlobalTopKeys = (results: DailyData[], topKeysLimit: number): To
|
|||
},
|
||||
};
|
||||
}
|
||||
keySpend[key].metrics.spend += metrics.metrics.spend;
|
||||
keySpend[key].metrics.prompt_tokens += metrics.metrics.prompt_tokens;
|
||||
keySpend[key].metrics.completion_tokens += metrics.metrics.completion_tokens;
|
||||
keySpend[key].metrics.total_tokens += metrics.metrics.total_tokens;
|
||||
keySpend[key].metrics.api_requests += metrics.metrics.api_requests;
|
||||
keySpend[key].metrics.successful_requests += metrics.metrics.successful_requests;
|
||||
keySpend[key].metrics.failed_requests += metrics.metrics.failed_requests;
|
||||
keySpend[key].metrics.cache_read_input_tokens += metrics.metrics.cache_read_input_tokens || 0;
|
||||
keySpend[key].metrics.cache_creation_input_tokens += metrics.metrics.cache_creation_input_tokens || 0;
|
||||
keySpend[key].metrics.spend += metrics.metrics?.spend ?? 0;
|
||||
keySpend[key].metrics.prompt_tokens += metrics.metrics?.prompt_tokens ?? 0;
|
||||
keySpend[key].metrics.completion_tokens += metrics.metrics?.completion_tokens ?? 0;
|
||||
keySpend[key].metrics.total_tokens += metrics.metrics?.total_tokens ?? 0;
|
||||
keySpend[key].metrics.api_requests += metrics.metrics?.api_requests ?? 0;
|
||||
keySpend[key].metrics.successful_requests += metrics.metrics?.successful_requests ?? 0;
|
||||
keySpend[key].metrics.failed_requests += metrics.metrics?.failed_requests ?? 0;
|
||||
keySpend[key].metrics.cache_read_input_tokens += (metrics.metrics?.cache_read_input_tokens ?? 0) || 0;
|
||||
keySpend[key].metrics.cache_creation_input_tokens += (metrics.metrics?.cache_creation_input_tokens ?? 0) || 0;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ export const getGlobalTopKeys = (results: DailyData[], topKeysLimit: number): To
|
|||
user: metrics.metadata.user_email ?? metrics.metadata.user_id ?? null,
|
||||
key_exists: metrics.metadata.key_exists,
|
||||
tags: metrics.metadata.tags || [],
|
||||
spend: metrics.metrics.spend,
|
||||
spend: metrics.metrics?.spend ?? 0,
|
||||
}))
|
||||
.sort((a, b) => b.spend - a.spend)
|
||||
.slice(0, topKeysLimit);
|
||||
|
|
@ -148,7 +148,7 @@ export const getTopAPIKeys = (results: ExtendedDailyData[], topKeysLimit: number
|
|||
const tagDictionary = Object.keys(entities).reduce((acc: { [key: string]: TagUsage[] }, entity) => {
|
||||
const { api_key_breakdown } = entities[entity];
|
||||
Object.keys(api_key_breakdown).forEach((key) => {
|
||||
const tagUsage = { tag: entity, usage: api_key_breakdown[key].metrics.spend };
|
||||
const tagUsage = { tag: entity, usage: api_key_breakdown[key].metrics?.spend ?? 0 };
|
||||
if (acc[key]) {
|
||||
acc[key].push(tagUsage);
|
||||
} else {
|
||||
|
|
@ -181,15 +181,15 @@ export const getTopAPIKeys = (results: ExtendedDailyData[], topKeysLimit: number
|
|||
},
|
||||
};
|
||||
}
|
||||
keySpend[key].metrics.spend += metrics.metrics.spend;
|
||||
keySpend[key].metrics.prompt_tokens += metrics.metrics.prompt_tokens;
|
||||
keySpend[key].metrics.completion_tokens += metrics.metrics.completion_tokens;
|
||||
keySpend[key].metrics.total_tokens += metrics.metrics.total_tokens;
|
||||
keySpend[key].metrics.api_requests += metrics.metrics.api_requests;
|
||||
keySpend[key].metrics.successful_requests += metrics.metrics.successful_requests;
|
||||
keySpend[key].metrics.failed_requests += metrics.metrics.failed_requests;
|
||||
keySpend[key].metrics.cache_read_input_tokens += metrics.metrics.cache_read_input_tokens || 0;
|
||||
keySpend[key].metrics.cache_creation_input_tokens += metrics.metrics.cache_creation_input_tokens || 0;
|
||||
keySpend[key].metrics.spend += metrics.metrics?.spend ?? 0;
|
||||
keySpend[key].metrics.prompt_tokens += metrics.metrics?.prompt_tokens ?? 0;
|
||||
keySpend[key].metrics.completion_tokens += metrics.metrics?.completion_tokens ?? 0;
|
||||
keySpend[key].metrics.total_tokens += metrics.metrics?.total_tokens ?? 0;
|
||||
keySpend[key].metrics.api_requests += metrics.metrics?.api_requests ?? 0;
|
||||
keySpend[key].metrics.successful_requests += metrics.metrics?.successful_requests ?? 0;
|
||||
keySpend[key].metrics.failed_requests += metrics.metrics?.failed_requests ?? 0;
|
||||
keySpend[key].metrics.cache_read_input_tokens += (metrics.metrics?.cache_read_input_tokens ?? 0) || 0;
|
||||
keySpend[key].metrics.cache_creation_input_tokens += (metrics.metrics?.cache_creation_input_tokens ?? 0) || 0;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ export const getTopAPIKeys = (results: ExtendedDailyData[], topKeysLimit: number
|
|||
user: metrics.metadata.user_email ?? metrics.metadata.user_id ?? null,
|
||||
key_exists: metrics.metadata.key_exists,
|
||||
tags: metrics.metadata.tags || [],
|
||||
spend: metrics.metrics.spend,
|
||||
spend: metrics.metrics?.spend ?? 0,
|
||||
}))
|
||||
.sort((a, b) => b.spend - a.spend)
|
||||
.slice(0, topKeysLimit);
|
||||
|
|
@ -223,11 +223,11 @@ export const getProviderSpend = (results: ExtendedDailyData[]): ProviderSpendRow
|
|||
};
|
||||
}
|
||||
try {
|
||||
providerSpend[provider].spend += metrics.metrics.spend;
|
||||
providerSpend[provider].requests += metrics.metrics.api_requests;
|
||||
providerSpend[provider].successful_requests += metrics.metrics.successful_requests;
|
||||
providerSpend[provider].failed_requests += metrics.metrics.failed_requests;
|
||||
providerSpend[provider].tokens += metrics.metrics.total_tokens;
|
||||
providerSpend[provider].spend += metrics.metrics?.spend ?? 0;
|
||||
providerSpend[provider].requests += metrics.metrics?.api_requests ?? 0;
|
||||
providerSpend[provider].successful_requests += metrics.metrics?.successful_requests ?? 0;
|
||||
providerSpend[provider].failed_requests += metrics.metrics?.failed_requests ?? 0;
|
||||
providerSpend[provider].tokens += metrics.metrics?.total_tokens ?? 0;
|
||||
} catch (e) {
|
||||
console.error(`Error processing provider ${provider}: ${e}`);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue