Skip to content
This repository was archived by the owner on Sep 21, 2026. It is now read-only.

Commit 28b46d9

Browse files
committed
fix(usage): scope the executions breakdown to function executions
`executions` is the umbrella metric covering both functions and sites, but the table it feeds is headed "Function" and links each row to /functions/function-{resourceId}. A project with a trafficked site would get rows showing a raw site ID, unresolvable by functions.list, linking to a function that does not exist. `functions.executions` is the metric that matches the table. Fold the call into the load function's existing Promise.all so it no longer serialises behind the invoice and usage requests, and report a failure through trackError instead of swallowing it — a 403 or a malformed response was previously indistinguishable from a project with no executions. Drop the duplicate database-type read in the collection layout, which recomputed locally what the component already derives.
1 parent 1cc7e26 commit 28b46d9

4 files changed

Lines changed: 18 additions & 12 deletions

File tree

‎src/lib/actions/analytics.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ export enum Submit {
259259
ProjectService = 'submit_project_service',
260260
ProjectUpdateSMTP = 'submit_project_update_smtp',
261261
ProjectUpdateOAuth2Server = 'submit_project_update_oauth2_server',
262+
ProjectUsageExecutionsBreakdown = 'submit_project_usage_executions_breakdown',
262263
ProjectResume = 'submit_project_resume',
263264
MemberCreate = 'submit_member_create',
264265
MemberDelete = 'submit_member_delete',

‎src/lib/sdk/usage.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ const executionsBreakdownLimit = 25;
3737
/**
3838
* `UsageProject.executionsBreakdown` was dropped in SDK 16; the per-resource split now comes from
3939
* the dimensional usage API, which returns bare resource IDs, so names are resolved separately.
40+
*
41+
* Scoped to `functions.executions` rather than the umbrella `executions` metric, which also counts
42+
* site executions — those resolve to no name here and their rows link to a function that does not exist.
43+
* Omitting `interval` makes each point a whole-window aggregate per resource, so the limit is a
44+
* top-N-by-total rather than a truncation of the underlying data.
4045
*/
4146
export async function listExecutionsBreakdown(
4247
region: string,
@@ -47,7 +52,7 @@ export async function listExecutionsBreakdown(
4752
const project = sdk.forProject(region, projectId);
4853

4954
const events = await project.usage.listEvents({
50-
metrics: [UsageEventMetric.Executions],
55+
metrics: [UsageEventMetric.FunctionsExecutions],
5156
dimensions: [UsageEventDimension.ResourceId],
5257
startAt,
5358
endAt,

‎src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+layout.svelte‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,7 @@
257257
const { rows, ids } = generateFakeRecords($randomDataModalState.value, fields);
258258
documentIds = ids;
259259
260-
const dbType = data.database?.type;
261-
const isVectorsDb = dbType === 'vectorsdb';
260+
const isVectorsDb = databaseType === 'vectorsdb';
262261
const dimension = collection?.dimension ?? DEFAULT_VECTOR_DIMENSION;
263262
264263
// For vectorsdb, wrap fields in metadata and add empty embeddings

‎src/routes/(console)/project-[region]-[project]/settings/usage/[[invoice]]/+page.ts‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { sdk } from '$lib/stores/sdk';
2+
import { Submit, trackError } from '$lib/actions/analytics';
23
import type { PageLoad } from './$types';
34
import { accumulateUsage, listExecutionsBreakdown, type ExecutionsBreakdown } from '$lib/sdk/usage';
45
import { type Models, Query } from '@appwrite.io/console';
@@ -35,12 +36,19 @@ export const load: PageLoad = async ({ params, parent }) => {
3536
}
3637
}
3738

38-
const [invoices, usage] = await Promise.all([
39+
const [invoices, usage, executionsBreakdown] = await Promise.all([
3940
sdk.forConsole.organizations.listInvoices({
4041
organizationId: organization.$id,
4142
queries: [Query.orderDesc('from')]
4243
}),
43-
sdk.forProject(region, project).project.getUsage({ startDate, endDate })
44+
sdk.forProject(region, project).project.getUsage({ startDate, endDate }),
45+
listExecutionsBreakdown(region, project, startDate, endDate).catch(
46+
(error): ExecutionsBreakdown[] => {
47+
// supplementary to the executions chart, so never fail the page for it
48+
trackError(error, Submit.ProjectUsageExecutionsBreakdown);
49+
return [];
50+
}
51+
)
4452
]);
4553

4654
if (currentAggregation) {
@@ -66,13 +74,6 @@ export const load: PageLoad = async ({ params, parent }) => {
6674

6775
usage.users = accumulateUsage(usage.users, usage.usersTotal);
6876

69-
let executionsBreakdown: ExecutionsBreakdown[] = [];
70-
try {
71-
executionsBreakdown = await listExecutionsBreakdown(region, project, startDate, endDate);
72-
} catch {
73-
// supplementary — a server without the usage events API still renders the rest of the page
74-
}
75-
7677
return {
7778
usage,
7879
invoices,

0 commit comments

Comments
 (0)