diff --git a/src/lib/sdk/tempFunctions.ts b/src/lib/sdk/tempFunctions.ts new file mode 100644 index 000000000..9df8775fa --- /dev/null +++ b/src/lib/sdk/tempFunctions.ts @@ -0,0 +1,236 @@ +import { AppwriteException, FunctionUsageRange, type Client, type Payload, type ProjectUsageRange } from '@appwrite.io/console'; + +/** + * Metric + */ +type Metric = { + /** + * The value of this metric at the timestamp. + */ + value: number; + /** + * The date at which this metric was aggregated in ISO 8601 format. + */ + date: string; +}; + +/** + * Metric Breakdown + */ +type MetricBreakdown = { + /** + * Resource ID. + */ + resourceId: string; + /** + * Resource name. + */ + name: string; + /** + * The value of this metric at the timestamp. + */ + value: number; +}; + +/** + * UsageProject + */ +type UsageProject = { + /** + * Total aggregated number of function executions. + */ + executionsTotal: number; + /** + * Total aggregated number of documents. + */ + documentsTotal: number; + /** + * Total aggregated number of databases. + */ + databasesTotal: number; + /** + * Total aggregated number of users. + */ + usersTotal: number; + /** + * Total aggregated sum of files storage size (in bytes). + */ + filesStorageTotal: number; + /** + * Total aggregated sum of deployments storage size (in bytes). + */ + deploymentsStorageTotal: number; + /** + * Total aggregated number of buckets. + */ + bucketsTotal: number; + /** + * Aggregated number of requests per period. + */ + requests: Metric[]; + /** + * Aggregated number of consumed bandwidth per period. + */ + network: Metric[]; + /** + * Aggregated number of users per period. + */ + users: Metric[]; + /** + * Aggregated number of executions per period. + */ + executions: Metric[]; + /** + * Aggregated breakdown in totals of executions by functions. + */ + executionsBreakdown: MetricBreakdown[]; + /** + * Aggregated breakdown in totals of usage by buckets. + */ + bucketsBreakdown: MetricBreakdown[]; + /** + * Aggregated breakdown in totals of usage by deployments. + */ + deploymentsStorageBreakdown: MetricBreakdown[]; +}; + +/** + * UsageFunction + */ +export type UsageFunction = { + /** + * The time range of the usage stats. + */ + range: string; + /** + * Total aggregated number of function deployments. + */ + deploymentsTotal: number; + /** + * Total aggregated sum of function deployments storage. + */ + deploymentsStorageTotal: number; + /** + * Total aggregated number of function builds. + */ + buildsTotal: number; + /** + * total aggregated sum of function builds storage. + */ + buildsStorageTotal: number; + /** + * Total aggregated sum of function builds compute time. + */ + buildsTimeTotal: number; + /** + * Total aggregated number of function executions. + */ + executionsTotal: number; + /** + * Total aggregated sum of function executions compute time. + */ + executionsTimeTotal: number; + /** + * Aggregated number of function deployments per period. + */ + deployments: Metric[]; + /** + * Aggregated number of function deployments storage per period. + */ + deploymentsStorage: Metric[]; + /** + * Aggregated number of function builds per period. + */ + builds: Metric[]; + /** + * Aggregated sum of function builds storage per period. + */ + buildsStorage: Metric[]; + /** + * Aggregated sum of function builds compute time per period. + */ + buildsTime: Metric[]; + /** + * Aggregated number of function executions per period. + */ + executions: Metric[]; + /** + * Aggregated number of function executions compute time per period. + */ + executionsTime: Metric[]; +}; + +export class TempFunctions { + client: Client; + + constructor(client: Client) { + this.client = client; + } + + /** + * Get project usage stats + * + * + * @param {string} startDate + * @param {string} endDate + * @param {ProjectUsageRange} period + * @throws {AppwriteException} + * @returns {Promise} + */ + async getUsage(startDate: string, endDate: string, period?: ProjectUsageRange): Promise { + if (typeof startDate === 'undefined') { + throw new AppwriteException('Missing required parameter: "startDate"'); + } + + if (typeof endDate === 'undefined') { + throw new AppwriteException('Missing required parameter: "endDate"'); + } + + const apiPath = '/project/usage'; + const payload: Payload = {}; + + if (typeof startDate !== 'undefined') { + payload['startDate'] = startDate; + } + + if (typeof endDate !== 'undefined') { + payload['endDate'] = endDate; + } + + if (typeof period !== 'undefined') { + payload['period'] = period; + } + + const uri = new URL(this.client.config.endpoint + apiPath); + return await this.client.call('get', uri, { + 'content-type': 'application/json', + }, payload); + } + + /** + * Get function usage + * + * + * @param {string} functionId + * @param {FunctionUsageRange} range + * @throws {AppwriteException} + * @returns {Promise} + */ + async getFunctionUsage(functionId: string, range?: FunctionUsageRange): Promise { + if (typeof functionId === 'undefined') { + throw new AppwriteException('Missing required parameter: "functionId"'); + } + + const apiPath = '/functions/{functionId}/usage'.replace('{functionId}', functionId); + const payload: Payload = {}; + + if (typeof range !== 'undefined') { + payload['range'] = range; + } + + const uri = new URL(this.client.config.endpoint + apiPath); + return await this.client.call('get', uri, { + 'content-type': 'application/json', + }, payload); + } +} \ No newline at end of file diff --git a/src/lib/stores/sdk.ts b/src/lib/stores/sdk.ts index 8dacdc079..6589742aa 100644 --- a/src/lib/stores/sdk.ts +++ b/src/lib/stores/sdk.ts @@ -23,6 +23,7 @@ import { } from '@appwrite.io/console'; import { Billing } from '../sdk/billing'; import { Sources } from '$lib/sdk/sources'; +import { TempFunctions } from '$lib/sdk/tempFunctions'; const endpoint = VARS.APPWRITE_ENDPOINT ?? `${globalThis?.location?.origin}/v1`; @@ -48,7 +49,8 @@ const sdkForProject = { users: new Users(clientProject), vcs: new Vcs(clientProject), proxy: new Proxy(clientProject), - migrations: new Migrations(clientProject) + migrations: new Migrations(clientProject), + tempFunctions: new TempFunctions(clientProject) }; export const getSdkForProject = (projectId: string) => { @@ -74,7 +76,8 @@ export const sdk = { console: new Console(clientConsole), assistant: new Assistant(clientConsole), billing: new Billing(clientConsole), - sources: new Sources(clientConsole) + sources: new Sources(clientConsole), + tempFunctions: new TempFunctions(clientConsole) }, get forProject() { const projectId = getProjectId(); diff --git a/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.svelte b/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.svelte index c486d2ba5..fc264912d 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.svelte @@ -5,10 +5,13 @@ import { page } from '$app/stores'; import type { PageData } from './$types'; import { formatNumberWithCommas } from '$lib/helpers/numbers'; + import { humanFileSize } from '$lib/helpers/sizeConvertion'; export let data: PageData; $: total = data.executionsTotal; $: count = data.executions; + $: deploymentsStorageTotal = data.deploymentsStorageTotal; + $: deploymentsStorage = data.deploymentsStorage; @@ -46,4 +49,36 @@ ]} /> {/if} - + {#if deploymentsStorage} + + {humanFileSize(deploymentsStorageTotal).value}{humanFileSize(deploymentsStorageTotal).unit} +

Deployments Storage

+
+ + value + ? `${humanFileSize(+value).value} ${ + humanFileSize(+value).unit + }` + : '0' + } + } + }} + series={[ + { + name: 'Bandwidth', + data: [ + ...deploymentsStorage.map((e) => [e.date, e.value]) + ], + tooltip: { + valueFormatter: (value) => + `${humanFileSize(+value).value} ${humanFileSize(+value).unit}` + } + } + ]} /> + +{/if} + \ No newline at end of file diff --git a/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts index 1766c60a0..f47f27e6c 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts @@ -9,7 +9,7 @@ export const load: PageLoad = async ({ params }) => { const period = isValueOfStringEnum(FunctionUsageRange, params.period) ? params.period : FunctionUsageRange.ThirtyDays; - return sdk.forProject.functions.getFunctionUsage(params.function, period); + return sdk.forProject.tempFunctions.getFunctionUsage(params.function, period); } catch (e) { error(e.code, e.message); } diff --git a/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.svelte b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.svelte index c3c3e103c..4a98567c5 100644 --- a/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.svelte +++ b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.svelte @@ -28,7 +28,7 @@ $: executions = data.usage.executions; $: executionsTotal = data.usage.executionsTotal; $: storage = data.usage.filesStorageTotal; - $: deployments = data.usage.deploymentsStorageTotal; + $: deploymentsTotal = data.usage.deploymentsStorageTotal; const tier = data?.currentInvoice?.tier ?? $organization?.billingPlan; const plan = tierToPlan(tier).name; @@ -317,8 +317,8 @@
{/if} - {#if deployments} - {@const humanized = humanFileSize(deployments)} + {#if deploymentsTotal} + {@const humanized = humanFileSize(deploymentsTotal)}

@@ -327,7 +327,7 @@

- {#if data.usage.bucketsBreakdown.length > 0} + {#if data.usage.deploymentsStorageBreakdown.length > 0} Function diff --git a/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts index 2cb455ae0..ca0d0ad76 100644 --- a/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts +++ b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts @@ -29,7 +29,7 @@ export const load: PageLoad = async ({ params, parent }) => { /** * Workaround because project id might not be populated yet. */ - getSdkForProject(project).project.getUsage(startDate, endDate) + getSdkForProject(project).tempFunctions.getUsage(startDate, endDate) ]); if (invoice) {