This commit is contained in:
devin-ai-integration[bot] 2026-08-27 18:13:41 -05:00 committed by GitHub
commit d0cc49bbd3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 54 additions and 1 deletions

View file

@ -525,6 +525,53 @@ describe("UsagePage", () => {
expect(screen.getByText("Top Virtual Keys")).toBeInTheDocument();
});
it("should not crash when a breakdown entry is missing its metrics (partial/large dataset)", async () => {
const malformedSpendData = {
...mockSpendData,
results: [
{
...mockSpendData.results[0],
breakdown: {
...mockSpendData.results[0].breakdown,
api_keys: {
...mockSpendData.results[0].breakdown.api_keys,
"sk-broken": {
metadata: { key_alias: "Broken Key", tags: [] },
},
},
models: {
...mockSpendData.results[0].breakdown.models,
"broken-model": {
metadata: {},
api_key_breakdown: {},
},
},
model_groups: {
...mockSpendData.results[0].breakdown.model_groups,
"broken-group": {
metadata: {},
api_key_breakdown: {},
},
},
providers: {
...mockSpendData.results[0].breakdown.providers,
"broken-provider": {},
},
},
},
],
};
mockUserDailyActivityAggregatedCall.mockResolvedValue(malformedSpendData as any);
renderWithProviders(<UsagePage {...defaultProps} />);
await waitFor(() => {
expect(mockUserDailyActivityAggregatedCall).toHaveBeenCalled();
});
expect(screen.getByText("Top Virtual Keys")).toBeInTheDocument();
});
it("should render the daily spend and top models charts with cyan bars", async () => {
const { container } = renderWithProviders(<UsagePage {...defaultProps} />);

View file

@ -262,6 +262,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
const modelSpend: { [key: string]: MetricWithMetadata } = {};
userSpendData.results.forEach((day) => {
Object.entries(day.breakdown.models || {}).forEach(([model, metrics]) => {
if (!metrics?.metrics) return;
if (!modelSpend[model]) {
modelSpend[model] = {
metrics: {
@ -308,6 +309,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
const modelGroupSpend: { [key: string]: MetricWithMetadata } = {};
userSpendData.results.forEach((day) => {
Object.entries(day.breakdown.model_groups || {}).forEach(([modelGroup, metrics]) => {
if (!metrics?.metrics) return;
if (!modelGroupSpend[modelGroup]) {
modelGroupSpend[modelGroup] = {
metrics: {
@ -356,6 +358,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
const providerSpendMap: { [key: string]: MetricWithMetadata } = {};
userSpendData.results.forEach((day) => {
Object.entries(day.breakdown.providers || {}).forEach(([provider, metrics]) => {
if (!metrics?.metrics) return;
if (!providerSpendMap[provider]) {
providerSpendMap[provider] = {
metrics: {
@ -401,6 +404,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
const keySpend: { [key: string]: KeyMetricWithMetadata } = {};
userSpendData.results.forEach((day) => {
Object.entries(day.breakdown.api_keys || {}).forEach(([key, metrics]) => {
if (!metrics?.metrics) return;
if (!keySpend[key]) {
keySpend[key] = {
metrics: {

View file

@ -452,6 +452,7 @@ export const processActivityData = (
dailyActivity.results.forEach((day) => {
Object.entries(day.breakdown[key] || {}).forEach(([model, modelData]) => {
if (!modelData?.metrics) return;
if (!modelMetrics[model]) {
modelMetrics[model] = {
label:
@ -513,6 +514,7 @@ export const processActivityData = (
const modelData = day.breakdown[key]?.[model];
if (modelData && "api_key_breakdown" in modelData) {
Object.entries(modelData.api_key_breakdown || {}).forEach(([apiKey, keyData]) => {
if (!keyData?.metrics) return;
if (!apiKeyBreakdown[apiKey]) {
apiKeyBreakdown[apiKey] = {
api_key: apiKey,
@ -549,7 +551,7 @@ export const processActivityData = (
Object.entries(day.breakdown.models || {}).forEach(([modelName, modelData]) => {
if (modelData && "api_key_breakdown" in modelData) {
const keyDataForModel = modelData.api_key_breakdown?.[apiKeyHash];
if (keyDataForModel) {
if (keyDataForModel?.metrics) {
if (!modelBreakdown[modelName]) {
modelBreakdown[modelName] = {
model: modelName,