add: database read, writes in org. usage screen.

This commit is contained in:
Darshan
2025-01-24 13:01:08 +05:30
parent a6792974f9
commit 884c454c55
2 changed files with 160 additions and 23 deletions
@@ -193,6 +193,65 @@
</svelte:fragment>
</CardGrid>
<CardGrid>
<Heading tag="h6" size="7">Databases reads and writes</Heading>
<p class="text">
The total number of database reads and writes across all projects in your organization.
</p>
<svelte:fragment slot="aside">
<!-- types need to be added to console sdk -->
{#if data.organizationUsage.databasesReadsTotal || data.organizationUsage.databasesWritesTotal}
<div style:margin-top="-1.5em">
<BarChart
options={{
yAxis: {
axisLabel: {
formatter: formatNum
}
}
}}
series={[
{
name: 'Reads',
data: [
...data.organizationUsage.databasesReads.map((e) => [
e.date,
e.value
])
]
},
{
name: 'Writes',
data: [
...data.organizationUsage.databasesWrites.map((e) => [
e.date,
e.value
])
]
}
]} />
</div>
{#if project?.length > 0}
<ProjectBreakdown
{data}
projects={project}
databaseOperationMetric={['databasesReads', 'databasesWrites']} />
{/if}
{:else}
<Card isDashed>
<div class="u-flex u-cross-center u-flex-vertical u-main-center u-flex">
<span
class="icon-chart-square-bar text-large"
aria-hidden="true"
style="font-size: 32px;" />
<p class="u-bold">No data to show</p>
</div>
</Card>
{/if}
</svelte:fragment>
</CardGrid>
<CardGrid>
<Heading tag="h6" size="7">Executions</Heading>
@@ -318,6 +377,7 @@
{/if}
</svelte:fragment>
</CardGrid>
<CardGrid>
<Heading tag="h6" size="7">GB hours</Heading>
@@ -378,6 +438,7 @@
{/if}
</svelte:fragment>
</CardGrid>
<CardGrid>
<Heading tag="h6" size="7">Phone OTP</Heading>
<p class="text">
@@ -430,6 +491,7 @@
{/if}
</svelte:fragment>
</CardGrid>
<TotalMembers members={data?.organizationMembers} />
<p class="text common-section u-color-text-gray">
@@ -15,14 +15,26 @@
import type { OrganizationUsage } from '$lib/sdk/billing';
import { base } from '$app/paths';
import { canSeeProjects } from '$lib/stores/roles';
import { onMount } from 'svelte';
type Metric =
| 'users'
| 'storage'
| 'bandwidth'
| 'executions'
| 'authPhoneTotal'
| 'databasesReads'
| 'databasesWrites';
type Metric = 'users' | 'storage' | 'bandwidth' | 'executions' | 'authPhoneTotal';
type Estimate = 'authPhoneEstimate';
type DatabaseOperationMetric = Extract<Metric, 'databasesReads' | 'databasesWrites'>;
export let data: PageData;
export let projects: OrganizationUsage['projects'];
export let metric: Metric;
export let metric: Metric | undefined = undefined;
export let estimate: Estimate | undefined = undefined;
export let databaseOperationMetric: DatabaseOperationMetric[] | undefined = undefined;
function getMetricTitle(metric: Metric): string {
switch (metric) {
@@ -38,25 +50,48 @@
}
function groupByProject(
metric: Metric,
estimate?: Estimate
): Array<{ projectId: string; usage: number; estimate?: number }> {
metric: Metric | undefined,
estimate?: Estimate,
databaseOps?: DatabaseOperationMetric[]
): Array<{
projectId: string;
databasesReads?: number;
databasesWrites?: number;
usage?: number;
estimate?: number;
}> {
const data = [];
for (const project of projects) {
const usage = project[metric];
if (!usage) {
continue;
if (metric) {
const usage = project[metric];
if (!usage) continue;
data.push({
projectId: project.projectId,
usage: usage ?? 0,
estimate: estimate ? project[estimate] : undefined
});
} else if (databaseOps) {
const reads = project['databasesReads'] ?? 0;
const writes = project['databasesWrites'] ?? 0;
if (reads || writes) {
data.push({
projectId: project.projectId,
databasesReads: reads,
databasesWrites: writes
});
}
}
data.push({
projectId: project.projectId,
usage: usage ?? 0,
estimate: estimate ? project[estimate] : undefined
});
}
return data;
}
function format(value: number): string {
if (databaseOperationMetric) {
return abbreviateNumber(value);
}
switch (metric) {
case 'authPhoneTotal':
return formatNumberWithCommas(value);
@@ -68,6 +103,12 @@
return humanFileSize(value).value + humanFileSize(value).unit;
}
}
onMount(() => {
if (metric === undefined && databaseOperationMetric === undefined) {
throw new Error(`metric or database operations must be defined`);
}
});
</script>
<Collapsible>
@@ -76,7 +117,13 @@
<TableScroll dense noStyles noMargin style="table-layout: auto">
<TableHeader>
<TableCellHead>Project</TableCellHead>
<TableCellHead>{getMetricTitle(metric)}</TableCellHead>
{#if databaseOperationMetric}
<TableCellHead>Reads</TableCellHead>
<TableCellHead>Writes</TableCellHead>
{:else}
<TableCellHead>{getMetricTitle(metric)}</TableCellHead>
{/if}
{#if estimate}
<TableCellHead>Estimated cost</TableCellHead>
{/if}
@@ -85,17 +132,33 @@
{/if}
</TableHeader>
<TableBody>
{#each groupByProject(metric, estimate).sort((a, b) => b.usage - a.usage) as project}
{#each groupByProject(metric, estimate, databaseOperationMetric).sort((a, b) => {
const aValue = a.usage ?? a.databasesReads ?? 0;
const bValue = b.usage ?? b.databasesReads ?? 0;
return bValue - aValue;
}) as project}
{#if !$canSeeProjects}
<TableRow>
<TableCell title="Project">
{data.projectNames[project.projectId]?.name ?? 'Unknown'}
</TableCell>
<TableCell title={getMetricTitle(metric)}
>{format(project.usage)}</TableCell>
{#if databaseOperationMetric}
<TableCell title="Reads">
{format(project.databasesReads ?? 0)}
</TableCell>
<TableCell title="Writes">
{format(project.databasesWrites ?? 0)}
</TableCell>
{:else}
<TableCell>
{format(project.usage)}
</TableCell>
{/if}
{#if project.estimate}
<TableCell title="Estimated cost"
>{formatCurrency(project.estimate)}</TableCell>
<TableCell title="Estimated cost">
{formatCurrency(project.estimate)}
</TableCell>
{/if}
</TableRow>
{:else}
@@ -103,11 +166,23 @@
<TableCell title="Project">
{data.projectNames[project.projectId]?.name ?? 'Unknown'}
</TableCell>
<TableCell title={getMetricTitle(metric)}
>{format(project.usage)}</TableCell>
{#if databaseOperationMetric}
<TableCell title="Reads">
{format(project.databasesReads ?? 0)}
</TableCell>
<TableCell title="Writes">
{format(project.databasesWrites ?? 0)}
</TableCell>
{:else}
<TableCell>
{format(project.usage)}
</TableCell>
{/if}
{#if project.estimate}
<TableCell title="Estimated cost"
>{formatCurrency(project.estimate)}</TableCell>
<TableCell title="Estimated cost">
{formatCurrency(project.estimate)}
</TableCell>
{/if}
<TableCell right={true}>
<span