Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions static/gsAdmin/components/addGiftEventsAction.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import {DataCategory, DataCategoryExact} from 'sentry/types/core';

import {AddGiftEventsAction} from 'admin/components/addGiftEventsAction';
import {openAdminConfirmModal} from 'admin/components/adminConfirmationModal';
import {BILLED_DATA_CATEGORY_INFO} from 'getsentry/constants';
import {getCategoryInfoFromPlural} from 'getsentry/utils/dataCategory';
import {
getBilledDataCategoryInfo,
getCategoryInfoFromPlural,
} from 'getsentry/utils/dataCategory';

describe('AddGiftEventsAction', () => {
const mockOrg = OrganizationFixture();
Expand All @@ -18,7 +20,7 @@ describe('AddGiftEventsAction', () => {
const triggerGiftModal = () => {
const billedCategoryInfo = categoryOverride
? getCategoryInfoFromPlural(categoryOverride)
: BILLED_DATA_CATEGORY_INFO[DataCategoryExact.SPAN];
: getBilledDataCategoryInfo()[DataCategoryExact.SPAN];
openAdminConfirmModal({
renderModalSpecificContent: deps => (
<AddGiftEventsAction
Expand Down
5 changes: 3 additions & 2 deletions static/gsAdmin/components/customers/customerOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {DetailList} from 'admin/components/detailList';
import {DetailsContainer} from 'admin/components/detailsContainer';
import {ExtendProductTrialAction} from 'admin/components/extendProductTrialAction';
import {getLogQuery} from 'admin/utils';
import {BILLED_DATA_CATEGORY_INFO, UNLIMITED} from 'getsentry/constants';
import {UNLIMITED} from 'getsentry/constants';
import type {
Plan,
ReservedBudget,
Expand All @@ -46,6 +46,7 @@ import {
RETENTION_SETTINGS_CATEGORIES,
} from 'getsentry/utils/billing';
import {
getBilledDataCategoryInfo,
getPlanCategoryName,
getReservedBudgetDisplayName,
sortCategories,
Expand Down Expand Up @@ -482,7 +483,7 @@ export function CustomerOverview({customer, onAction, organization}: Props) {
// TODO(cells) We also should show the customer's cell.
const locality = localityMap[organization.links.regionUrl] ?? '??';

const productTrialCategories = Object.values(BILLED_DATA_CATEGORY_INFO).filter(
const productTrialCategories = Object.values(getBilledDataCategoryInfo()).filter(
categoryInfo => {
// Category must be in the plan's categories
if (!customer.planDetails?.categories.includes(categoryInfo.plural)) {
Expand Down
10 changes: 6 additions & 4 deletions static/gsApp/components/gsBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import {ProductTrialAlert} from 'getsentry/components/productTrial/productTrialA
import {getProductForPath} from 'getsentry/components/productTrial/productTrialPaths';
import {makeLinkToOwnersAndBillingMembers} from 'getsentry/components/profiling/alerts';
import {withSubscription} from 'getsentry/components/withSubscription';
import {BILLED_DATA_CATEGORY_INFO} from 'getsentry/constants';
import {SubscriptionStore} from 'getsentry/stores/subscriptionStore';
import {
type BilledDataCategoryInfo,
Expand All @@ -62,7 +61,10 @@ import {
partnerPlanEndingModalIsDismissed,
trialPromptIsDismissed,
} from 'getsentry/utils/billing';
import {getCategoryInfoFromPlural} from 'getsentry/utils/dataCategory';
import {
getBilledDataCategoryInfo,
getCategoryInfoFromPlural,
} from 'getsentry/utils/dataCategory';
import {getPendoAccountFields} from 'getsentry/utils/pendo';
import {claimAvailablePromotion} from 'getsentry/utils/promotionUtils';
import {trackGetsentryAnalytics} from 'getsentry/utils/trackGetsentryAnalytics';
Expand All @@ -80,7 +82,7 @@ enum ModalType {
const TRIAL_ENDING_DAY_WINDOW = 3;

function objectFromBilledCategories(callback: (c: BilledDataCategoryInfo) => any) {
return Object.values(BILLED_DATA_CATEGORY_INFO).reduce(
return Object.values(getBilledDataCategoryInfo()).reduce(
(acc, c) => {
if (c.isBilledCategory) {
acc[c.singular as EventType] = callback(c);
Expand Down Expand Up @@ -634,7 +636,7 @@ class GSBanner extends Component<Props, State> {
const category_warning_prompts: string[] = [];
const category_product_trial_prompts: string[] = [];

Object.values(BILLED_DATA_CATEGORY_INFO)
Object.values(getBilledDataCategoryInfo())
.filter(
categoryInfo =>
categoryInfo.isBilledCategory &&
Expand Down
192 changes: 0 additions & 192 deletions static/gsApp/constants.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
import {DATA_CATEGORY_INFO} from 'sentry/constants';
import {t} from 'sentry/locale';
import {DataCategoryExact} from 'sentry/types/core';

import type {BilledDataCategoryInfo} from 'getsentry/types';

export const MONTHLY = 'monthly';
export const ANNUAL = 'annual';

Expand Down Expand Up @@ -48,189 +42,3 @@ export enum AllocationTargetTypes {
PROJECT = 'Project',
ORGANIZATION = 'Organization',
}

// XXX: initialize the BilledDataCategoryInfo-specific field for all non-billed
// `categories and make TS happy so we can access the BilledDataCategoryInfo
// fields directly without needing to check that they exist on the object
const DEFAULT_BILLED_DATA_CATEGORY_INFO = {
...DATA_CATEGORY_INFO,
} as Record<DataCategoryExact, BilledDataCategoryInfo>;
Object.entries(DEFAULT_BILLED_DATA_CATEGORY_INFO).forEach(
([categoryExact, categoryInfo]) => {
DEFAULT_BILLED_DATA_CATEGORY_INFO[categoryExact as DataCategoryExact] = {
...categoryInfo,
canAllocate: false,
canProductTrial: false,
freeEventsMultiple: 0,
feature: null,
hasSpikeProtection: false,
checkoutTooltip: null,
tallyType: 'usage',
hasPerCategory: false,
adminOnlyProductTrialFeature: null,
};
}
);

/**
* Extension of DATA_CATEGORY_INFO with billing info for billed categories.
* All categories with isBilledCategory: true, should be explicitly
* added to this object with billing info.
*/
export const BILLED_DATA_CATEGORY_INFO = {
...DEFAULT_BILLED_DATA_CATEGORY_INFO,
[DataCategoryExact.ERROR]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.ERROR],
canAllocate: true,
freeEventsMultiple: 1_000,
hasSpikeProtection: true,
checkoutTooltip: t(
'Errors are sent every time an SDK catches a bug. You can send them manually too, if you want.'
),
hasPerCategory: true,
},
[DataCategoryExact.TRANSACTION]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.TRANSACTION],
canAllocate: true,
canProductTrial: true,
freeEventsMultiple: 1_000,
feature: 'performance-view',
hasSpikeProtection: true,
checkoutTooltip: t(
'Transactions are sent when your service receives a request and sends a response.'
),
hasPerCategory: true,
shortenedUnitName: t('unit'),
},
[DataCategoryExact.ATTACHMENT]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.ATTACHMENT],
canAllocate: true,
freeEventsMultiple: 1,
feature: 'event-attachments',
hasSpikeProtection: true,
checkoutTooltip: t('Attachments are files attached to errors, such as minidumps.'),
hasPerCategory: true,
shortenedUnitName: 'GB',
},
[DataCategoryExact.REPLAY]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.REPLAY],
canProductTrial: true,
freeEventsMultiple: 1,
feature: 'session-replay',
checkoutTooltip: t(
'Session Replays are video-like reproductions of your users’ sessions navigating your app or website.'
),
hasPerCategory: true,
},
[DataCategoryExact.SPAN]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.SPAN],
canProductTrial: true,
freeEventsMultiple: 100_000,
feature: 'spans-usage-tracking',
hasSpikeProtection: true,
checkoutTooltip: t(
'Tracing is enabled by spans. A span represents a single operation of work within a trace.'
),
},
[DataCategoryExact.SPAN_INDEXED]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.SPAN_INDEXED],
canProductTrial: true,
freeEventsMultiple: 100_000,
feature: 'spans-usage-tracking',
},
[DataCategoryExact.MONITOR_SEAT]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.MONITOR_SEAT],
freeEventsMultiple: 1,
feature: 'monitor-seat-billing',
tallyType: 'seat',
hasPerCategory: true,
checkoutTooltip: t(
'Crons monitors scheduled jobs to confirm they run on time and alert you when they fail or misfire.'
),
shortenedUnitName: t('monitor'),
},
[DataCategoryExact.UPTIME]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.UPTIME],
freeEventsMultiple: 1,
feature: 'uptime-billing',
tallyType: 'seat',
hasPerCategory: true,
checkoutTooltip: t(
'Uptime monitoring checks your application’s availability and alerts you when services go down so you can respond quickly.'
),
shortenedUnitName: t('monitor'),
},
[DataCategoryExact.PROFILE_DURATION]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.PROFILE_DURATION],
canProductTrial: true,
freeEventsMultiple: 1, // in hours
hasPerCategory: true,
checkoutTooltip: t(
'Continuous profiling tracks how code runs while your service is active, helping you find bottlenecks and improve efficiency.'
),
shortenedUnitName: t('hour'),
},
[DataCategoryExact.PROFILE_DURATION_UI]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.PROFILE_DURATION_UI],
canProductTrial: true,
freeEventsMultiple: 1, // in hours
hasPerCategory: true,
checkoutTooltip: t(
'UI profiling tracks code performance during user sessions in frontend or mobile apps, helping you spot slowdowns and improve experience.'
),
shortenedUnitName: t('hour'),
},
// Seer categories have product trials through ReservedBudgetCategoryType.SEER, not as individual categories
[DataCategoryExact.SEER_AUTOFIX]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.SEER_AUTOFIX],
feature: 'seer-billing',
shortenedUnitName: t('fix'),
},
[DataCategoryExact.SEER_SCANNER]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.SEER_SCANNER],
feature: 'seer-billing',
shortenedUnitName: t('scan'),
},
[DataCategoryExact.LOG_BYTE]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.LOG_BYTE],
canAllocate: false,
canProductTrial: true,
freeEventsMultiple: 1,
hasSpikeProtection: false,
feature: 'logs-billing',
checkoutTooltip: t(
'A log records events from your application, giving you the context to debug issues and understand system behavior.'
),
shortenedUnitName: 'GB',
},
[DataCategoryExact.TRACE_METRIC_BYTE]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.TRACE_METRIC_BYTE],
canProductTrial: true,
freeEventsMultiple: 1,
feature: 'expose-category-trace-metric-byte',
shortenedUnitName: 'GB',
checkoutTooltip: t(
'Application Metrics capture key signals from your application using counters, gauges, and distributions.'
),
},
[DataCategoryExact.SEER_USER]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.SEER_USER],
feature: 'seer-user-billing-launch',
canProductTrial: false,
freeEventsMultiple: 1,
tallyType: 'seat',
shortenedUnitName: t('contributor'),
},
[DataCategoryExact.SIZE_ANALYSIS]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.SIZE_ANALYSIS],
freeEventsMultiple: 1,
shortenedUnitName: t('build'),
adminOnlyProductTrialFeature: true,
},
[DataCategoryExact.INSTALLABLE_BUILD]: {
...DEFAULT_BILLED_DATA_CATEGORY_INFO[DataCategoryExact.INSTALLABLE_BUILD],
freeEventsMultiple: 1,
shortenedUnitName: t('install'),
adminOnlyProductTrialFeature: 'expose-category-installable-build',
},
} as const satisfies Record<DataCategoryExact, BilledDataCategoryInfo>;
Loading
Loading