-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
feat(profiling): Add banner to set budget for profile hours #91661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9f251ef
2743556
1059c4d
2d5c7da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -17,8 +17,8 @@ import {openAM2ProfilingUpsellModal} from 'getsentry/actionCreators/modal'; | |||||||||||||||
import AddEventsCTA, {type EventType} from 'getsentry/components/addEventsCTA'; | ||||||||||||||||
import withSubscription from 'getsentry/components/withSubscription'; | ||||||||||||||||
import type {Subscription} from 'getsentry/types'; | ||||||||||||||||
import {PlanTier} from 'getsentry/types'; | ||||||||||||||||
import {isAm2Plan, isEnterprise} from 'getsentry/utils/billing'; | ||||||||||||||||
import {OnDemandBudgetMode, PlanTier} from 'getsentry/types'; | ||||||||||||||||
import {isAm2Plan, isAm3Plan, isEnterprise} from 'getsentry/utils/billing'; | ||||||||||||||||
import trackGetsentryAnalytics from 'getsentry/utils/trackGetsentryAnalytics'; | ||||||||||||||||
|
||||||||||||||||
export function makeLinkToOwnersAndBillingMembers( | ||||||||||||||||
|
@@ -372,6 +372,170 @@ export function ContinuousProfilingBetaSDKAlertBanner() { | |||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
interface ContinuousProfilingNoQuotaAlertBannerProps { | ||||||||||||||||
organization: Organization; | ||||||||||||||||
subscription: Subscription; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
function ContinuousProfilingNoQuotaAlertAm2Banner({ | ||||||||||||||||
organization, | ||||||||||||||||
subscription, | ||||||||||||||||
}: ContinuousProfilingNoQuotaAlertBannerProps) { | ||||||||||||||||
const hasBudget = hasBudgetConfiguredForContinuousOrUiProfilesHours(subscription); | ||||||||||||||||
|
||||||||||||||||
// As long as they have a budget set, don't show this banner. | ||||||||||||||||
if (hasBudget) { | ||||||||||||||||
return null; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// For AM2 plans, if they haven't tried to send any continuous/ui profiles, don't | ||||||||||||||||
// show this banner because they can still use transaction profiles. | ||||||||||||||||
if ( | ||||||||||||||||
!subscription.categories.profileDuration?.usageExceeded && | ||||||||||||||||
!subscription.categories.profileDurationUI?.usageExceeded | ||||||||||||||||
) { | ||||||||||||||||
return null; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
const eventTypes: EventType[] = [ | ||||||||||||||||
DataCategoryExact.PROFILE_DURATION, | ||||||||||||||||
DataCategoryExact.PROFILE_DURATION_UI, | ||||||||||||||||
]; | ||||||||||||||||
|
||||||||||||||||
return ( | ||||||||||||||||
<Alert.Container> | ||||||||||||||||
<Alert | ||||||||||||||||
system | ||||||||||||||||
type="warning" | ||||||||||||||||
showIcon | ||||||||||||||||
trailingItems={ | ||||||||||||||||
<AddEventsCTA | ||||||||||||||||
organization={organization} | ||||||||||||||||
subscription={subscription} | ||||||||||||||||
buttonProps={{ | ||||||||||||||||
priority: 'default', | ||||||||||||||||
size: 'xs', | ||||||||||||||||
style: {marginBlock: `-${space(0.25)}`}, | ||||||||||||||||
}} | ||||||||||||||||
eventTypes={eventTypes} | ||||||||||||||||
notificationType="overage_critical" | ||||||||||||||||
referrer={`no-profiling-quota-${eventTypes.join('-')}`} | ||||||||||||||||
source="continuous-profiling-no-quota-banner" | ||||||||||||||||
/> | ||||||||||||||||
} | ||||||||||||||||
> | ||||||||||||||||
{t( | ||||||||||||||||
'Continuous Profiling and UI Profiling requires you to set your On-demand budget.' | ||||||||||||||||
)} | ||||||||||||||||
Comment on lines
+427
to
+429
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
if you use this looks like you won't need to split into the different tier banners? not sure if there were any other changes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. im tempted to say let's leave it as separate components as this feels like something that we're likely to iterate on a few times before getting it right and the differences between AM2 and AM3 plans makes it annoying to handle if we have to litter |
||||||||||||||||
</Alert> | ||||||||||||||||
</Alert.Container> | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
function ContinuousProfilingNoQuotaAlertAm3Banner({ | ||||||||||||||||
organization, | ||||||||||||||||
subscription, | ||||||||||||||||
}: ContinuousProfilingNoQuotaAlertBannerProps) { | ||||||||||||||||
const hasBudget = hasBudgetConfiguredForContinuousOrUiProfilesHours(subscription); | ||||||||||||||||
|
||||||||||||||||
// As long as they have a budget set, don't show this banner. | ||||||||||||||||
if (hasBudget) { | ||||||||||||||||
return null; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
const eventTypes: EventType[] = [ | ||||||||||||||||
DataCategoryExact.PROFILE_DURATION, | ||||||||||||||||
DataCategoryExact.PROFILE_DURATION_UI, | ||||||||||||||||
]; | ||||||||||||||||
|
||||||||||||||||
return ( | ||||||||||||||||
<Alert.Container> | ||||||||||||||||
<Alert | ||||||||||||||||
system | ||||||||||||||||
type="warning" | ||||||||||||||||
showIcon | ||||||||||||||||
trailingItems={ | ||||||||||||||||
<AddEventsCTA | ||||||||||||||||
organization={organization} | ||||||||||||||||
subscription={subscription} | ||||||||||||||||
buttonProps={{ | ||||||||||||||||
priority: 'default', | ||||||||||||||||
size: 'xs', | ||||||||||||||||
style: {marginBlock: `-${space(0.25)}`}, | ||||||||||||||||
}} | ||||||||||||||||
eventTypes={eventTypes} | ||||||||||||||||
referrer={`no-profiling-quota-${eventTypes.join('-')}`} | ||||||||||||||||
source="continuous-profiling-no-quota-banner" | ||||||||||||||||
/> | ||||||||||||||||
} | ||||||||||||||||
> | ||||||||||||||||
{t( | ||||||||||||||||
'Continuous Profiling and UI Profiling requires you to set your Pay-as-you-go budget.' | ||||||||||||||||
)} | ||||||||||||||||
</Alert> | ||||||||||||||||
</Alert.Container> | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
function hasBudgetConfiguredForContinuousOrUiProfilesHours( | ||||||||||||||||
subscription: Subscription | ||||||||||||||||
): boolean { | ||||||||||||||||
if ( | ||||||||||||||||
subscription.categories.profileDuration?.reserved || | ||||||||||||||||
subscription.categories.profileDurationUI?.reserved | ||||||||||||||||
) { | ||||||||||||||||
return true; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
if (subscription.onDemandBudgets) { | ||||||||||||||||
if (subscription.onDemandBudgets.budgetMode === OnDemandBudgetMode.SHARED) { | ||||||||||||||||
if (subscription.onDemandBudgets.sharedMaxBudget) { | ||||||||||||||||
return true; | ||||||||||||||||
} | ||||||||||||||||
} else if ( | ||||||||||||||||
subscription.onDemandBudgets.budgetMode === OnDemandBudgetMode.PER_CATEGORY | ||||||||||||||||
) { | ||||||||||||||||
if ( | ||||||||||||||||
subscription.onDemandBudgets.profileDurationBudget || | ||||||||||||||||
subscription.onDemandBudgets.profileDurationUIBudget | ||||||||||||||||
) { | ||||||||||||||||
return true; | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
return false; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
function ContinuousProfilingNoQuotaAlertBannerComponent({ | ||||||||||||||||
organization, | ||||||||||||||||
subscription, | ||||||||||||||||
}: ContinuousProfilingNoQuotaAlertBannerProps) { | ||||||||||||||||
if (isAm2Plan(subscription.plan)) { | ||||||||||||||||
return ( | ||||||||||||||||
<ContinuousProfilingNoQuotaAlertAm2Banner | ||||||||||||||||
organization={organization} | ||||||||||||||||
subscription={subscription} | ||||||||||||||||
/> | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
if (isAm3Plan(subscription.plan)) { | ||||||||||||||||
return ( | ||||||||||||||||
<ContinuousProfilingNoQuotaAlertAm3Banner | ||||||||||||||||
organization={organization} | ||||||||||||||||
subscription={subscription} | ||||||||||||||||
/> | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
return null; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
export const ContinuousProfilingNoQuotaAlertBanner = withSubscription( | ||||||||||||||||
ContinuousProfilingNoQuotaAlertBannerComponent | ||||||||||||||||
); | ||||||||||||||||
|
||||||||||||||||
interface SDKDeprecation { | ||||||||||||||||
minimumVersion: string; | ||||||||||||||||
projectId: string; | ||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i believe customers without PAYG that aren't using transaction profiles will fall under this condition too since having usage is not exceeded for profile hour categories unless they have PAYG set up and it's all used up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure i understand what you're saying here.