diff --git a/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx b/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx index 1c4f5da3225ec3..93eb5843c5c0ff 100644 --- a/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx +++ b/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx @@ -13,6 +13,7 @@ import {resetMockDate, setMockDate} from 'sentry-test/utils'; import {DataCategory} from 'sentry/types/core'; +import {GIGABYTE} from 'getsentry/constants'; import SubscriptionStore from 'getsentry/stores/subscriptionStore'; import Overview from 'getsentry/views/subscriptionPage/overview'; import UsageOverview from 'getsentry/views/subscriptionPage/usageOverview'; @@ -116,6 +117,12 @@ describe('UsageOverview', () => { usage: 6000, onDemandSpendUsed: 10_00, }; + subscription.categories.attachments = { + ...subscription.categories.attachments!, + reserved: 25, // 25 GB + free: 0, + usage: GIGABYTE / 2, + }; subscription.categories.spans = { ...subscription.categories.spans!, reserved: 20_000_000, @@ -143,6 +150,12 @@ describe('UsageOverview', () => { // Errors usage and gifted units expect(screen.getByText('6,000 / 51,000')).toBeInTheDocument(); expect(screen.getByText('$10.00')).toBeInTheDocument(); + expect(screen.getByText('12%')).toBeInTheDocument(); + + // Attachments usage should be in the correct unit + above platform volume + expect(screen.getByText('500 MB / 25 GB')).toBeInTheDocument(); + expect(screen.getByText('50%')).toBeInTheDocument(); + expect(screen.getByText('$6.00')).toBeInTheDocument(); // Reserved spans above platform volume expect(screen.getByText('0 / 20,000,000')).toBeInTheDocument(); diff --git a/static/gsApp/views/subscriptionPage/usageOverview.tsx b/static/gsApp/views/subscriptionPage/usageOverview.tsx index ed8f7d4b18f97b..4283c87f017178 100644 --- a/static/gsApp/views/subscriptionPage/usageOverview.tsx +++ b/static/gsApp/views/subscriptionPage/usageOverview.tsx @@ -30,7 +30,12 @@ import {NavLayout} from 'sentry/views/nav/types'; import ProductTrialTag from 'getsentry/components/productTrial/productTrialTag'; import StartTrialButton from 'getsentry/components/startTrialButton'; -import {RESERVED_BUDGET_QUOTA, UNLIMITED, UNLIMITED_RESERVED} from 'getsentry/constants'; +import { + GIGABYTE, + RESERVED_BUDGET_QUOTA, + UNLIMITED, + UNLIMITED_RESERVED, +} from 'getsentry/constants'; import {useCurrentBillingHistory} from 'getsentry/hooks/useCurrentBillingHistory'; import { AddOnCategory, @@ -47,10 +52,13 @@ import { getPercentage, getPotentialProductTrial, getReservedBudgetCategoryForAddOn, + MILLISECONDS_IN_HOUR, } from 'getsentry/utils/billing'; import { getCategoryInfoFromPlural, getPlanCategoryName, + isByteCategory, + isContinuousProfiling, sortCategories, } from 'getsentry/utils/dataCategory'; import {displayPriceWithCents, getBucket} from 'getsentry/views/amCheckout/utils'; @@ -248,7 +256,8 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi title: true, }); const reserved = metricHistory.reserved ?? 0; - const free = metricHistory.free; + const free = metricHistory.free ?? 0; + const prepaid = metricHistory.prepaid ?? 0; const total = metricHistory.usage; const paygTotal = metricHistory.onDemandSpendUsed; const softCapType = @@ -270,11 +279,16 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi : reserved > 0; const bucket = getBucket({ - events: reserved, + events: reserved, // buckets use the converted unit reserved amount (ie. in GB for byte categories) buckets: subscription.planDetails.planCategories[category], }); const recurringReservedSpend = bucket.price ?? 0; - const reservedTotal = (reserved ?? 0) + (free ?? 0); + // convert prepaid amount to the same unit as usage to accurately calculate percent used + const reservedTotal = isByteCategory(category) + ? prepaid * GIGABYTE + : isContinuousProfiling(category) + ? prepaid * MILLISECONDS_IN_HOUR + : prepaid; const percentUsed = reservedTotal ? getPercentage(total, reservedTotal) : undefined;