feat(preprod): Add size monitor UI#108211
feat(preprod): Add size monitor UI#108211chromy wants to merge 1 commit intochromy/2026-03-12-add-issue-type-to-frontendfrom
Conversation
|
🚨 Warning: This pull request contains Frontend and Backend changes! It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently. Have questions? Please ask in the |
static/app/views/detectors/components/forms/mobileBuild/mobileBuildFormData.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 6 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| priority=DetectorPriorityLevel.HIGH, | ||
| occurrence=occurrence, | ||
| event_data=event_data, | ||
| ) |
There was a problem hiding this comment.
Detector ignores configured thresholds
High Severity
PreprodSizeAnalysisDetectorHandler.evaluate_impl always creates a HIGH IssueOccurrence and never evaluates detector.conditionGroup, metric, or measurement. This makes preprod_size_analysis monitors fire on every packet, regardless of configured thresholds.
| measurement: data.measurement, | ||
| }, | ||
| dataSources: [{}], | ||
| }; |
There was a problem hiding this comment.
Filter settings never reach backend
Medium Severity
The form captures filters, but preprodFormDataToEndpointPayload always sends dataSources: [{}], so filter values are dropped. On the backend, SizeAnalysisDataSourceValidator declares no fields and creates SizeAnalysisSubscription with only project, so configured filters are never persisted or applied.
Additional Locations (1)
|
|
||
| const highThreshold = String(bytesToMb(String(highCondition?.comparison ?? ''))); | ||
| const mediumThreshold = String(bytesToMb(String(mediumCondition?.comparison ?? ''))); | ||
| const lowThreshold = String(bytesToMb(String(lowCondition?.comparison ?? ''))); |
There was a problem hiding this comment.
Relative thresholds get converted as bytes
Medium Severity
preprodSavedDetectorToFormData always runs comparison values through bytesToMb, including relative_diff detectors where thresholds are percentages. Editing and saving these detectors rewrites percentage thresholds to tiny MB-converted values, corrupting monitor configuration.
|
|
||
| const highThreshold = String(bytesToMb(String(highCondition?.comparison ?? ''))); | ||
| const mediumThreshold = String(bytesToMb(String(mediumCondition?.comparison ?? ''))); | ||
| const lowThreshold = String(bytesToMb(String(lowCondition?.comparison ?? ''))); |
There was a problem hiding this comment.
Missing thresholds become zero on edit
High Severity
preprodSavedDetectorToFormData converts absent threshold conditions into "0" by passing empty values through bytesToMb. Because "0" is truthy, createPreprodConditions later persists LOW/MEDIUM thresholds at zero, changing monitor behavior after a simple edit.
| 'metric_issue', | ||
| 'monitor_check_in_failure', | ||
| 'uptime_domain_failure', | ||
| 'preprod_size_analysis', |
There was a problem hiding this comment.
Feature gate can be bypassed via query
Medium Severity
preprod_size_analysis is always accepted by detectorType query parsing, while UI gating only hides the option. A user can still set ?detectorType=preprod_size_analysis and reach NewPreprodDetectorForm even without the preprod-size-monitors-frontend feature.
Additional Locations (1)
| def validate_data_sources(self, value: list[Any]) -> list[Any]: | ||
| if not value: | ||
| raise serializers.ValidationError("At least one data source is required") | ||
| return value |
There was a problem hiding this comment.
Missing data source validation on create
Medium Severity
data_sources is marked required=False, so requests that omit dataSources skip validate_data_sources. This allows creating preprod_size_analysis detectors without any SizeAnalysisSubscription, leaving monitors that never receive packets and silently never trigger.
| function mbToBytes(mb: string): number { | ||
| const value = parseFloat(mb); | ||
| if (Number.isNaN(value)) { | ||
| return 0; | ||
| } | ||
| return value * 1024 * 1024; | ||
| } |
There was a problem hiding this comment.
Bug: The detector details page displays the raw byte value of a threshold with an "MB" unit, leading to a nonsensical value like "10485760 MB" instead of "10 MB".
Severity: MEDIUM
Suggested Fix
The display component in detect.tsx should convert the raw byte value from condition.comparison back to megabytes before rendering it. This will ensure the value shown in the UI is consistent with the user's original input.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location:
static/app/views/detectors/components/forms/mobileBuild/mobileBuildFormData.tsx#L60-L66
Potential issue: The new form in `mobileBuildFormData.tsx` converts a user-entered value
in megabytes (MB) to bytes using a binary factor (1024*1024). For example, an input of
"10 MB" is stored as `10485760` bytes. However, the detector details page in
`detect.tsx` later displays this raw byte value directly from `condition.comparison`
while incorrectly appending the "MB" unit. This results in a confusing and incorrect UI
where a threshold set as "10 MB" is displayed as "10485760 MB".
|
This PR has a migration; here is the generated SQL for for --
-- Create model SizeAnalysisSubscription
--
CREATE TABLE "sentry_sizeanalysissubscription" ("id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "date_updated" timestamp with time zone NOT NULL, "date_added" timestamp with time zone NOT NULL, "project_id" bigint NOT NULL);
ALTER TABLE "sentry_sizeanalysissubscription" ADD CONSTRAINT "sentry_sizeanalysiss_project_id_41e3355e_fk_sentry_pr" FOREIGN KEY ("project_id") REFERENCES "sentry_project" ("id") DEFERRABLE INITIALLY DEFERRED NOT VALID;
ALTER TABLE "sentry_sizeanalysissubscription" VALIDATE CONSTRAINT "sentry_sizeanalysiss_project_id_41e3355e_fk_sentry_pr";
CREATE INDEX CONCURRENTLY "sentry_sizeanalysissubscription_project_id_41e3355e" ON "sentry_sizeanalysissubscription" ("project_id"); |
faf4368 to
3f32d87
Compare
759cbb5 to
3117ac8
Compare


Add list, detail, and create/edit views for the preprod_size_analysis
detector type ("Mobile Builds"). Users can configure a metric
(install/download size), measurement (absolute/diff/relative), optional
build filters, and priority thresholds. Includes a live preview section,
detector type selection form, and routes at /detectors/mobile-builds/.
PRs:
Design doc