mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Finish deployments storage UI
This commit is contained in:
@@ -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<UsageProject> {
|
||||
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<UsageFunction> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
+36
-1
@@ -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;
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -46,4 +49,36 @@
|
||||
]} />
|
||||
</Card>
|
||||
{/if}
|
||||
</Container>
|
||||
{#if deploymentsStorage}
|
||||
<Card>
|
||||
<Heading tag="h6" size="6">{humanFileSize(deploymentsStorageTotal).value}{humanFileSize(deploymentsStorageTotal).unit}</Heading>
|
||||
<p>Deployments Storage</p>
|
||||
<div class="u-margin-block-start-16" />
|
||||
<BarChart
|
||||
options={{
|
||||
yAxis: {
|
||||
axisLabel: {
|
||||
formatter: (value) =>
|
||||
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}`
|
||||
}
|
||||
}
|
||||
]} />
|
||||
</Card>
|
||||
{/if}
|
||||
</Container>
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 @@
|
||||
</div>
|
||||
</Card>
|
||||
{/if}
|
||||
{#if deployments}
|
||||
{@const humanized = humanFileSize(deployments)}
|
||||
{#if deploymentsTotal}
|
||||
{@const humanized = humanFileSize(deploymentsTotal)}
|
||||
<div class="u-flex u-flex-vertical">
|
||||
<div class="u-flex u-main-space-between">
|
||||
<p>
|
||||
@@ -327,7 +327,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{#if data.usage.bucketsBreakdown.length > 0}
|
||||
{#if data.usage.deploymentsStorageBreakdown.length > 0}
|
||||
<Table noMargin noStyles>
|
||||
<TableHeader>
|
||||
<TableCellHead width={285}>Function</TableCellHead>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user