mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore: improve usage v2 page
This commit is contained in:
1 parent
fe33cc4cb2
commit
68426bcd08
12 files changed
+78
-117
No files matched your search
@@ -124,7 +124,7 @@ Queries which are the most time consuming are not necessarily bad, you may have
|
||||
|
||||
Generally for most applications a small percentage of data is accessed more regularly than the rest. To make sure that your regularly accessed data is available, Postgres tracks your data access patterns and keeps this in its [shared_buffers](https://www.postgresql.org/docs/15/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY) cache.
|
||||
|
||||
Applications with lower cache hit rates generally perform more poorly since they have to hit the disk to get results rather than serving them from memory. Very poor hit rates can also cause you to burst past your [Disk I/O limits](https://supabase.com/docs/guides/platform/compute-add-ons#disk-io-bandwidth) causing significant performance issues.
|
||||
Applications with lower cache hit rates generally perform more poorly since they have to hit the disk to get results rather than serving them from memory. Very poor hit rates can also cause you to burst past your [Disk I/O limits](https://supabase.com/docs/guides/platform/compute-add-ons#disk-throughput-and-iops) causing significant performance issues.
|
||||
|
||||
You can view your cache and index hit rate by executing the following query:
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Some common solutions for this issue are:
|
||||
- [Using fewer Postgres connections](../platform/performance#configuring-clients-to-use-fewer-connections) can reduce the amount of resources needed on the project.
|
||||
- [Restarting](https://app.supabase.com/project/_/settings/general) the database. This only temporarily solves the issue by terminating any ongoing workloads that might be tying up your compute resources.
|
||||
|
||||
If your [Daily Disk IO budget](../platform/compute-add-ons#disk-io-bandwidth) has been drained, you will need to either wait for it to be replenished the next day, or upgrade to a larger compute add-on to increase the budget available to your project.
|
||||
If your [Daily Disk IO budget](../platform/compute-add-ons#disk-throughput-and-iops) has been drained, you will need to either wait for it to be replenished the next day, or upgrade to a larger compute add-on to increase the budget available to your project.
|
||||
|
||||
## Unable to connect to your Supabase Project
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ const AddOns = ({}: AddOnsProps) => {
|
||||
<p className="text-sm">{computeInstanceSpecs?.connections_pooler ?? 200}</p>
|
||||
</div>
|
||||
<div className="w-full flex items-center justify-between border-b py-2">
|
||||
<Link href={`/project/${projectRef}/settings/billing/usage#disk_io_budget`}>
|
||||
<Link href={`/project/${projectRef}/settings/billing/usage#disk_io`}>
|
||||
<a>
|
||||
<div className="group flex items-center space-x-2">
|
||||
<p className="text-sm text-scale-1100 group-hover:text-scale-1200 transition cursor-pointer">
|
||||
@@ -240,7 +240,7 @@ const AddOns = ({}: AddOnsProps) => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="w-full flex items-center justify-between py-2">
|
||||
<Link href={`/project/${projectRef}/settings/billing/usage#disk_io_budget`}>
|
||||
<Link href={`/project/${projectRef}/settings/billing/usage#disk_io`}>
|
||||
<a>
|
||||
<div className="group flex items-center space-x-2">
|
||||
<p className="text-sm text-scale-1100 group-hover:text-scale-1200 transition cursor-pointer">
|
||||
|
||||
@@ -39,7 +39,7 @@ const EnterpriseCard = ({ plan, isCurrentPlan, isTeamTierEnabled }: EnterpriseCa
|
||||
<Link href="https://supabase.com/contact/enterprise">
|
||||
<a target="blank" rel="noreferrer">
|
||||
<Button block={!isTeamTierEnabled} type="default">
|
||||
Contact 24hr Sales Team
|
||||
Contact Sales Team
|
||||
</Button>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
@@ -176,7 +176,7 @@ const Activity = ({ projectRef }: ActivityProps) => {
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-4">
|
||||
<p className="text-sm">{attribute.name} quota usage</p>
|
||||
<p className="text-sm">{attribute.name} usage</p>
|
||||
{!usageBasedBilling && usageRatio >= 1 ? (
|
||||
<div className="flex items-center space-x-2 min-w-[115px]">
|
||||
<IconAlertTriangle
|
||||
@@ -237,7 +237,9 @@ const Activity = ({ projectRef }: ActivityProps) => {
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<p className="text-xs text-scale-1000">Used</p>
|
||||
<p className="text-xs text-scale-1000">
|
||||
{attribute.chartPrefix || 'Used '}in period
|
||||
</p>
|
||||
<p className="text-xs">{(usageMeta?.usage ?? 0).toLocaleString()}</p>
|
||||
</div>
|
||||
{usageMeta.limit > 0 && (
|
||||
@@ -254,7 +256,7 @@ const Activity = ({ projectRef }: ActivityProps) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p>{attribute.name} over time</p>
|
||||
<p>{attribute.name} per day</p>
|
||||
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
|
||||
<p key={`para-${idx}`} className="text-sm text-scale-1000">
|
||||
{paragraph}
|
||||
@@ -269,15 +271,12 @@ const Activity = ({ projectRef }: ActivityProps) => {
|
||||
</div>
|
||||
) : (
|
||||
<UsageBarChart
|
||||
hasQuota={usageMeta.limit > 0}
|
||||
name={attribute.name}
|
||||
name={`${attribute.chartPrefix || ''}${attribute.name}`}
|
||||
unit={attribute.unit}
|
||||
attribute={attribute.attribute}
|
||||
data={chartData}
|
||||
yLimit={usageMeta?.limit ?? 0}
|
||||
yLeftMargin={chartMeta[attribute.key].margin}
|
||||
yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)}
|
||||
quotaWarningType={isFreeTier || isProTier ? 'danger' : 'warning'}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -101,7 +101,7 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-4">
|
||||
<p className="text-sm">{attribute.name} quota usage</p>
|
||||
<p className="text-sm">{attribute.name} usage</p>
|
||||
{!usageBasedBilling && usageRatio >= 1 ? (
|
||||
<div className="flex items-center space-x-2 min-w-[115px]">
|
||||
<IconAlertTriangle
|
||||
@@ -154,7 +154,9 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<p className="text-xs text-scale-1000">Used</p>
|
||||
<p className="text-xs text-scale-1000">
|
||||
{attribute.chartPrefix || 'Used '}in period
|
||||
</p>
|
||||
<p className="text-xs">{formatBytes(usageMeta?.usage ?? 0)}</p>
|
||||
</div>
|
||||
{usageMeta?.limit > 0 && (
|
||||
@@ -168,7 +170,7 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p>{attribute.name} over time</p>
|
||||
<p>{attribute.name} per day</p>
|
||||
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
|
||||
<p key={`para-${idx}`} className="text-sm text-scale-1000">
|
||||
{paragraph}
|
||||
@@ -183,15 +185,12 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {
|
||||
</div>
|
||||
) : (
|
||||
<UsageBarChart
|
||||
hasQuota={usageMeta?.limit > 0}
|
||||
name={attribute.name}
|
||||
name={`${attribute.chartPrefix || ''}${attribute.name}`}
|
||||
unit={attribute.unit}
|
||||
attribute={attribute.attribute}
|
||||
data={chartData}
|
||||
yLimit={usageMeta?.limit ?? 0}
|
||||
yLeftMargin={chartMeta[attribute.key].margin}
|
||||
yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)}
|
||||
quotaWarningType={isFreeTier || isProTier ? 'danger' : 'warning'}
|
||||
/>
|
||||
)}
|
||||
</SectionContent>
|
||||
|
||||
@@ -77,17 +77,16 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
|
||||
|
||||
const { data: ioBudgetData, isLoading: isLoadingIoBudgetData } = useInfraMonitoringQuery({
|
||||
projectRef,
|
||||
attribute: 'disk_io_budget',
|
||||
attribute: 'disk_io_consumption',
|
||||
interval,
|
||||
startDate,
|
||||
endDate,
|
||||
dateFormat,
|
||||
})
|
||||
|
||||
const currentDayIoBudget = Number(
|
||||
ioBudgetData?.data.find((x) => x.periodStartFormatted === dayjs().format('DD MMM'))?.[
|
||||
'disk_io_budget'
|
||||
] ?? 100
|
||||
const highestIoBudgetConsumption = Math.max(
|
||||
...(ioBudgetData?.data || []).map((x) => Number(x.disk_io_consumption) ?? 0),
|
||||
0
|
||||
)
|
||||
|
||||
const chartMeta: { [key: string]: { data: DataPoint[]; isLoading: boolean } } = {
|
||||
@@ -99,7 +98,7 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
|
||||
isLoading: isLoadingMemoryUsageData,
|
||||
data: memoryUsageData?.data ?? [],
|
||||
},
|
||||
disk_io_budget: {
|
||||
disk_io_consumption: {
|
||||
isLoading: isLoadingIoBudgetData,
|
||||
data: ioBudgetData?.data ?? [],
|
||||
},
|
||||
@@ -116,14 +115,14 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
|
||||
return (
|
||||
<div id={attribute.anchor} key={attribute.key}>
|
||||
<SectionContent section={attribute}>
|
||||
{attribute.key === 'disk_io_budget' && (
|
||||
{attribute.key === 'disk_io_consumption' && (
|
||||
<>
|
||||
{currentDayIoBudget <= 0 ? (
|
||||
{highestIoBudgetConsumption >= 100 ? (
|
||||
<Alert withIcon variant="danger" title="IO Budget for today has been used up">
|
||||
<p className="mb-4">
|
||||
Your workload has used up all the burst IO throughput minutes during the day
|
||||
and is running at the baseline performance. If you need consistent disk
|
||||
performance, consider upgrading to a larger compute add-on.
|
||||
Your workload has used up all the burst IO throughput minutes and ran at the
|
||||
baseline performance. If you need consistent disk performance, consider
|
||||
upgrading to a larger compute add-on.
|
||||
</p>
|
||||
<Link href={upgradeUrl}>
|
||||
<a>
|
||||
@@ -133,7 +132,7 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
|
||||
</a>
|
||||
</Link>
|
||||
</Alert>
|
||||
) : currentDayIoBudget <= 20 ? (
|
||||
) : highestIoBudgetConsumption >= 80 ? (
|
||||
<Alert withIcon variant="warning" title="IO Budget for today is running out">
|
||||
<p className="mb-4">
|
||||
Your workload is about to use up all the burst IO throughput minutes during
|
||||
@@ -185,24 +184,17 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
|
||||
)}
|
||||
<div className="space-y-1">
|
||||
<div className="flex flex-row justify-between">
|
||||
{attribute.key === 'disk_io_budget' ? (
|
||||
<p>IO Budget remaining</p>
|
||||
{attribute.key === 'disk_io_consumption' ? (
|
||||
<p>IO consumed per day</p>
|
||||
) : (
|
||||
<p>
|
||||
Max{' '}
|
||||
<span className={attribute.key === 'ram_usage' ? 'lowercase' : ''}>
|
||||
{attribute.name}
|
||||
</span>{' '}
|
||||
usage
|
||||
per {interval === '1d' ? 'day' : 'hour'}
|
||||
</p>
|
||||
)}
|
||||
<Link href={`/project/${projectRef}/settings/billing/subscription`}>
|
||||
<a>
|
||||
<Button type="default" size="tiny">
|
||||
Upgrade compute
|
||||
</Button>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
|
||||
@@ -219,7 +211,7 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {
|
||||
</div>
|
||||
) : chartData.length ? (
|
||||
<UsageBarChart
|
||||
name={attribute.name}
|
||||
name={`${attribute.chartPrefix || ''}${attribute.name}`}
|
||||
unit={attribute.unit}
|
||||
attribute={attribute.attribute}
|
||||
data={chartData}
|
||||
|
||||
@@ -116,7 +116,7 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-4">
|
||||
<p className="text-sm">{attribute.name} quota usage</p>
|
||||
<p className="text-sm">{attribute.name} usage</p>
|
||||
{!usageBasedBilling && usageRatio >= 1 ? (
|
||||
<div className="flex items-center space-x-2 min-w-[115px]">
|
||||
<IconAlertTriangle
|
||||
@@ -172,7 +172,9 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<p className="text-xs text-scale-1000">Used</p>
|
||||
<p className="text-xs text-scale-1000">
|
||||
{attribute.chartPrefix || 'Used '}in period
|
||||
</p>
|
||||
<p className="text-xs">
|
||||
{attribute.unit === 'bytes'
|
||||
? formatBytes(usageMeta?.usage ?? 0)
|
||||
@@ -217,7 +219,10 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
|
||||
)}
|
||||
|
||||
<div className="space-y-1">
|
||||
<p>{attribute.name} over time</p>
|
||||
<p>
|
||||
{attribute.chartPrefix || ''}
|
||||
{attribute.name} per day
|
||||
</p>
|
||||
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
|
||||
<p key={`para-${idx}`} className="text-sm text-scale-1000">
|
||||
{paragraph}
|
||||
@@ -232,15 +237,12 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {
|
||||
</div>
|
||||
) : (
|
||||
<UsageBarChart
|
||||
hasQuota={usageMeta.limit > 0}
|
||||
name={attribute.name}
|
||||
name={`${attribute.chartPrefix || ''}${attribute.name}`}
|
||||
unit={attribute.unit}
|
||||
attribute={attribute.attribute}
|
||||
data={chartData}
|
||||
yLimit={usageMeta?.limit ?? 0}
|
||||
yLeftMargin={chartMeta[attribute.key].margin}
|
||||
yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)}
|
||||
quotaWarningType={isFreeTier || isProTier ? 'danger' : 'warning'}
|
||||
/>
|
||||
)}
|
||||
</SectionContent>
|
||||
|
||||
@@ -11,6 +11,7 @@ export interface CategoryAttribute {
|
||||
key: string // Property from project usage
|
||||
attribute: string // For querying against stats-daily / infra-monitoring
|
||||
name: string
|
||||
chartPrefix?: string
|
||||
unit: 'bytes' | 'absolute' | 'percentage'
|
||||
links?: {
|
||||
name: string
|
||||
@@ -29,7 +30,7 @@ export const USAGE_CATEGORIES: {
|
||||
{
|
||||
key: 'infra',
|
||||
name: 'Infrastructure',
|
||||
description: 'Usage statistics related to your Postgres server',
|
||||
description: 'Usage statistics related to your server instance',
|
||||
attributes: [
|
||||
{
|
||||
anchor: 'cpu',
|
||||
@@ -63,19 +64,19 @@ export const USAGE_CATEGORIES: {
|
||||
],
|
||||
},
|
||||
{
|
||||
anchor: 'disk_io_budget',
|
||||
key: 'disk_io_budget',
|
||||
attribute: 'disk_io_budget',
|
||||
anchor: 'disk_io',
|
||||
key: 'disk_io_consumption',
|
||||
attribute: 'disk_io_consumption',
|
||||
name: 'Disk IO bandwidth',
|
||||
unit: 'percentage',
|
||||
links: [
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: 'https://supabase.com/docs/guides/platform/compute-add-ons#disk-io-bandwidth',
|
||||
url: 'https://supabase.com/docs/guides/platform/compute-add-ons#disk-throughput-and-iops',
|
||||
},
|
||||
],
|
||||
description:
|
||||
'SSD Disks are attached to your servers and the disk performance of your workload is determined by the Disk IO bandwidth of this connection.',
|
||||
'SSD Disks are attached to your servers. The disk performance of your workload is determined by the Disk IO bandwidth of this connection.',
|
||||
chartDescription: '',
|
||||
},
|
||||
],
|
||||
@@ -92,8 +93,8 @@ export const USAGE_CATEGORIES: {
|
||||
name: 'Database egress',
|
||||
unit: 'bytes',
|
||||
description:
|
||||
'Contains any outgoing traffic (egress) from your database\nBilling is based on the total sum of egress in GB throughout your billing period.',
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
'Contains any outgoing traffic (egress) from your database.\nBilling is based on the total sum of egress in GB throughout your billing period.',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
{
|
||||
anchor: 'storageEgress',
|
||||
@@ -103,7 +104,7 @@ export const USAGE_CATEGORIES: {
|
||||
unit: 'bytes',
|
||||
description:
|
||||
'All requests to download/view your storage items go through our CDN. We sum up all outgoing traffic (egress) for storage related requests through our CDN. We do not differentiate between cache and no cache hits.\nBilling is based on the total amount of egress in GB throughout your billing period.',
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -117,6 +118,7 @@ export const USAGE_CATEGORIES: {
|
||||
key: 'db_size',
|
||||
attribute: 'total_db_size_bytes',
|
||||
name: 'Database size',
|
||||
chartPrefix: 'Average ',
|
||||
unit: 'bytes',
|
||||
description:
|
||||
'Billing is based on the average daily database size in GB throughout the billing period.',
|
||||
@@ -126,27 +128,29 @@ export const USAGE_CATEGORIES: {
|
||||
url: 'https://supabase.com/docs/guides/platform/database-size',
|
||||
},
|
||||
],
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
{
|
||||
anchor: 'storageSize',
|
||||
key: 'storage_size',
|
||||
attribute: 'total_storage_size_bytes',
|
||||
name: 'Storage size',
|
||||
chartPrefix: 'Max ',
|
||||
unit: 'bytes',
|
||||
description:
|
||||
'Sum of all objects in your storage buckets\nBilling is based on the average size in GB throughout your billing period',
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
'Sum of all objects in your storage buckets.\nBilling is based on the average size in GB throughout your billing period',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
{
|
||||
anchor: 'funcCount',
|
||||
key: 'func_count',
|
||||
attribute: 'total_func_count',
|
||||
name: 'Edge function count',
|
||||
chartPrefix: 'Max ',
|
||||
unit: 'absolute',
|
||||
description:
|
||||
'Number of serverless functions in your project\nBilling is based on the maximum amount of functions at any point in time throughout your billing period',
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
'Number of serverless functions in your project.\nBilling is based on the maximum amount of functions at any point in time throughout your billing period',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -159,23 +163,23 @@ export const USAGE_CATEGORIES: {
|
||||
anchor: 'mau',
|
||||
key: 'monthly_active_users',
|
||||
attribute: 'total_auth_billing_period_mau',
|
||||
name: 'Monthly active users',
|
||||
name: 'Monthly Active Users',
|
||||
unit: 'absolute',
|
||||
description:
|
||||
'Users who log in or refresh their token\nBilling is based on the sum of distinct users requesting your API throughout the billing period. Resets every billing cycle.',
|
||||
'Users who log in or refresh their token count towards MAU.\nBilling is based on the sum of distinct users requesting your API throughout the billing period. Resets every billing cycle.',
|
||||
chartDescription:
|
||||
'The data shown here is refreshed over a period of 24 hours and resets at the beginning of every billing period.',
|
||||
'The data shown here is refreshed over a period of 24 hours and resets at the beginning of every billing period.\nThe data points are relative to the beginning of your billing period.',
|
||||
},
|
||||
{
|
||||
anchor: 'mauSso',
|
||||
key: 'monthly_active_sso_users',
|
||||
attribute: 'total_auth_billing_period_sso_mau',
|
||||
name: 'Monthly active single sign-on users',
|
||||
name: 'Monthly Active SSO Users',
|
||||
unit: 'absolute',
|
||||
description:
|
||||
'SSO users who log in or refresh their token\nBilling is based on the sum of distinct Single Sign-On users requesting your API throughout the billing period. Resets every billing cycle.',
|
||||
'SSO users who log in or refresh their token count towards SSO MAU.\nBilling is based on the sum of distinct Single Sign-On users requesting your API throughout the billing period. Resets every billing cycle.',
|
||||
chartDescription:
|
||||
'The data shown here is refreshed over a period of 24 hours and resets at the beginning of every billing period.',
|
||||
'The data shown here is refreshed over a period of 24 hours and resets at the beginning of every billing period.\nThe data points are relative to the beginning of your billing period.',
|
||||
},
|
||||
{
|
||||
anchor: 'storageImageTransformations',
|
||||
@@ -185,7 +189,8 @@ export const USAGE_CATEGORIES: {
|
||||
unit: 'absolute',
|
||||
description:
|
||||
'We distinctly count all images that were transformed in the billing period, ignoring any transformations. If you transform one image with different transformations, it only counts as one.\nBilling is based on the unique count of (origin) images that used transformations throughout the billing period. Resets every billing cycle.',
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
chartDescription:
|
||||
'The data shown here refreshes every 24 hours.\nThe data points are relative to the beginning of your billing period.',
|
||||
},
|
||||
{
|
||||
anchor: 'functionInvocations',
|
||||
@@ -195,7 +200,7 @@ export const USAGE_CATEGORIES: {
|
||||
unit: 'absolute',
|
||||
description:
|
||||
'Every single serverless function invocation independent of response status is counted.\nBilling is based on the sum of all invocations throughout your billing period.',
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
{
|
||||
anchor: 'realtimeMessageCount',
|
||||
@@ -205,17 +210,18 @@ export const USAGE_CATEGORIES: {
|
||||
unit: 'absolute',
|
||||
description:
|
||||
"Count of messages going through Realtime. If you do a database change and 5 clients listen to that change via Realtime, that's 5 messages. If you broadcast a message and 4 clients listen to that, that's 5 messages (1 message sent, 4 received).\nBilling is based on the total amount of messages throughout your billing period.",
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
{
|
||||
anchor: 'realtimePeakConnection',
|
||||
key: 'realtime_peak_connection',
|
||||
attribute: 'total_realtime_peak_connection',
|
||||
name: 'Realtime peak connections',
|
||||
chartPrefix: 'Max ',
|
||||
unit: 'absolute',
|
||||
description:
|
||||
'Total number of successful connections (not connection attempts)\nBilling is based on the maximum amount of concurrent peak connections throughout your billing period.',
|
||||
chartDescription: 'The data shown here is refreshed over a period of 24 hours.',
|
||||
'Total number of successful connections (not connection attempts).\nBilling is based on the maximum amount of concurrent peak connections throughout your billing period.',
|
||||
chartDescription: 'The data shown here refreshes every 24 hours.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -57,7 +57,8 @@ const Usage = () => {
|
||||
|
||||
const subscriptionTierId = subscription?.tier?.supabase_prod_id
|
||||
const usageBillingEnabled =
|
||||
subscriptionTierId === PRICING_TIER_PRODUCT_IDS.FREE || PRICING_TIER_PRODUCT_IDS.PRO
|
||||
subscriptionTierId !== PRICING_TIER_PRODUCT_IDS.FREE &&
|
||||
subscriptionTierId !== PRICING_TIER_PRODUCT_IDS.PRO
|
||||
|
||||
const scrollTo = (id: 'infra' | 'bandwidth' | 'sizeCount' | 'activity') => {
|
||||
switch (id) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
CartesianGrid,
|
||||
Cell,
|
||||
ComposedChart,
|
||||
ReferenceLine,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
@@ -21,11 +20,9 @@ export interface UsageBarChartProps {
|
||||
name: string // Used within the tooltip
|
||||
attribute: string
|
||||
unit: 'bytes' | 'absolute' | 'percentage'
|
||||
hasQuota?: boolean
|
||||
yLimit?: number
|
||||
yLeftMargin?: number
|
||||
yFormatter?: (value: number | string) => string
|
||||
quotaWarningType?: 'warning' | 'danger'
|
||||
}
|
||||
|
||||
const UsageBarChart = ({
|
||||
@@ -33,23 +30,14 @@ const UsageBarChart = ({
|
||||
name,
|
||||
attribute,
|
||||
unit,
|
||||
hasQuota = false,
|
||||
yLimit,
|
||||
yLeftMargin = 10,
|
||||
yFormatter,
|
||||
quotaWarningType = 'warning',
|
||||
}: UsageBarChartProps) => {
|
||||
const yMin = 0 // We can consider passing this as a prop if there's a use case in the future
|
||||
const yMax = (yLimit ?? 0) * Y_DOMAIN_CEILING_MULTIPLIER
|
||||
const quotaWarningClass = quotaWarningType === 'warning' ? 'fill-amber-900' : 'fill-red-900'
|
||||
|
||||
const yDomain = [yMin, yLimit ?? 0]
|
||||
const ticks =
|
||||
yLimit !== undefined && hasQuota
|
||||
? [yMin, (yMax - yMin) * 0.25, (yMax - yMin) * 0.5, (yMax - yMin) * 0.75, yMax].map((x) =>
|
||||
Math.ceil(x)
|
||||
)
|
||||
: undefined
|
||||
|
||||
|
||||
return (
|
||||
<div className="w-full h-[200px]">
|
||||
@@ -62,7 +50,6 @@ const UsageBarChart = ({
|
||||
axisLine={false}
|
||||
tickLine={{ stroke: 'none' }}
|
||||
domain={yDomain}
|
||||
ticks={ticks}
|
||||
tickFormatter={yFormatter}
|
||||
/>
|
||||
<Tooltip
|
||||
@@ -97,35 +84,9 @@ const UsageBarChart = ({
|
||||
/>
|
||||
<Bar dataKey={attribute}>
|
||||
{data.map((entry) => {
|
||||
return (
|
||||
<Cell
|
||||
key={`${entry.period_start}`}
|
||||
className={
|
||||
yLimit !== undefined && Number(entry[attribute]) >= yLimit && hasQuota
|
||||
? quotaWarningClass
|
||||
: 'fill-scale-1200'
|
||||
}
|
||||
/>
|
||||
)
|
||||
return <Cell key={`${entry.period_start}`} className="fill-scale-1200" />
|
||||
})}
|
||||
</Bar>
|
||||
{hasQuota && yLimit && (
|
||||
<ReferenceLine
|
||||
y={yLimit}
|
||||
label={(props) => (
|
||||
<foreignObject
|
||||
x={props.viewBox.x + 30}
|
||||
y={props.viewBox.y - 10}
|
||||
width={200}
|
||||
height={24}
|
||||
>
|
||||
<div className="text-[0.7rem] font-bold text-scale-1200 bg-scale-100 w-fit p-1.5 py-0.5 rounded-md">
|
||||
INCLUDED USAGE
|
||||
</div>
|
||||
</foreignObject>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</ComposedChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { analyticsKeys } from './keys'
|
||||
|
||||
export type InfraMonitoringVariables = {
|
||||
projectRef?: string
|
||||
attribute: 'cpu_usage' | 'disk_io_budget' | 'ram_usage'
|
||||
attribute: 'cpu_usage' | 'disk_io_budget' | 'ram_usage' | 'disk_io_consumption'
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
interval?: '1m' | '5m' | '10m' | '30m' | '1h' | '1d'
|
||||
@@ -78,6 +78,7 @@ export const useInfraMonitoringQuery = <TData = InfraMonitoringData>(
|
||||
}),
|
||||
} as TData
|
||||
},
|
||||
staleTime: 1000 * 60, // default good for a minute
|
||||
...options,
|
||||
}
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user