Skip to content

Conversation

@hussam789
Copy link

@hussam789 hussam789 commented Oct 30, 2025

User description

PR #5


PR Type

Enhancement, Bug fix, Tests, Configuration changes


Description

Major changes across multiple systems:

  • Replay system improvements: Added null segment ID handling in replay deletion, updated bulk delete tests, and integrated error context into breadcrumb analysis

  • Browser reporting validation: Refactored API validation using DRF serializers with improved error handling and field constraints

  • PR comment formatting: Updated GitHub and GitLab integrations to use markdown links with environment context instead of culprits, with centralized template utilities

  • Workflow engine enhancements: Added detector owner field support, optimized slow conditions queries, and refactored logger initialization

  • Autofix tuning defaults: Changed default automation tuning from "low" to "off" across constants, project options, and tests

  • Analytics and tracking: Added preprod artifact analytics events, timeline zoom tracking for replays, and webhook delivery task processing deadlines

  • Frontend refactoring: Migrated from custom flex components to Flex component across multiple views for consistency

  • Visualization architecture: Refactored explore visualizations from multi-axis to single-axis model with corresponding hook and utility updates

  • Feedback summarization: Added AI-generated feedback summary component with refined prompt constraints and new hook for fetching summaries

  • Database and migrations: Disabled problematic migrations 0917 and 0920 with reference to corrected version 0921, added DB query injection noise configuration

  • Snuba and logging: Added equations parameter to ourlogs timeseries queries, added logs dataset test coverage for top N events

  • Trace attribute handling: New hooks for fetching trace item attribute keys and values with filtering capabilities

  • Table widget visualization: New component for rendering tabular data with customizable columns and cell renderers

  • Parameterization cleanup: Removed unused regex experiment class and simplified experiment execution logic

  • Devservices configuration: Added snuba-metrics service and Kafka consumer services for subscription results


Diagram Walkthrough

flowchart LR
  A["Replay System<br/>Error Context & Deletion"] --> B["Breadcrumb<br/>Analysis"]
  C["Browser Reporting<br/>Validation"] --> D["DRF Serializers<br/>& Error Handling"]
  E["PR Comment<br/>Formatting"] --> F["Centralized<br/>Templates"]
  G["Workflow Engine<br/>Enhancements"] --> H["Owner Field<br/>& Optimization"]
  I["Frontend<br/>Components"] --> J["Flex Component<br/>Migration"]
  K["Visualization<br/>Architecture"] --> L["Single-Axis<br/>Model"]
  M["Feedback<br/>System"] --> N["AI Summaries<br/>& Constraints"]
  O["Analytics<br/>Tracking"] --> P["Events & Telemetry"]
Loading

File Walkthrough

Relevant files
Tests
12 files
test_browser_reporting_collector.py
Browser reporting collector validation test expansion       

tests/sentry/api/endpoints/test_browser_reporting_collector.py

  • Extracted test data constants (DEPRECATION_REPORT,
    INTERVENTION_REPORT) to module level for reusability
  • Added assert_invalid_report_data helper method to validate error
    responses
  • Refactored existing tests to use new constants and removed logger
    mocking
  • Added comprehensive validation tests for missing fields, invalid
    types, URLs, timestamps, attempts, and mixed field constraints
+119/-73
test_project_replay_summarize_breadcrumbs.py
Replay breadcrumb summarization error context integration

tests/sentry/replays/test_project_replay_summarize_breadcrumbs.py

  • Added @requires_snuba decorator and store_replays method for replay
    data storage
  • Implemented two new test methods (test_get_with_error,
    test_get_with_error_context_disabled) to validate error context
    handling
  • Updated test_get_request_data to include ErrorEvent objects and verify
    chronological ordering of logs and errors
  • Added imports for datetime, requests, nodestore, and event-related
    utilities
+188/-6 
test_organization_events_stats.py
Top N events stats test coverage for logs dataset               

tests/snuba/api/endpoints/test_organization_events_stats.py

  • Renamed test class from OrganizationEventsStatsTopNEvents to
    OrganizationEventsStatsTopNEventsSpans
  • Added new test class OrganizationEventsStatsTopNEventsLogs with
    OurLogTestCase mixin for logs dataset testing
  • Implemented test_simple_top_events method to validate top events query
    on logs dataset
  • Added imports for defaultdict and OurLogTestCase
+110/-3 
test_organization_detector_index.py
Detector creation tests with owner field validation           

tests/sentry/workflow_engine/endpoints/test_organization_detector_index.py

  • Added three new test methods for detector creation with owner:
    test_valid_creation_with_owner, test_valid_creation_with_team_owner,
    test_invalid_owner
  • Added test for owner not in organization scenario
  • Tests validate owner field serialization, team owner assignment, and
    error handling for invalid owners
+86/-0   
test_organization_detector_details.py
Detector update tests with owner field modifications         

tests/sentry/workflow_engine/endpoints/test_organization_detector_details.py

  • Added three new test methods for detector owner updates:
    test_update_owner_to_user, test_update_owner_to_team,
    test_update_clear_owner
  • Tests validate owner field updates from user to team, clearing owners,
    and proper serialization
+89/-0   
test_delayed_workflow.py
Delayed workflow test updates for slow conditions parameter

tests/sentry/workflow_engine/processors/test_delayed_workflow.py

  • Added import for get_slow_conditions_for_groups function
  • Updated test_get_condition_query_groups to compute and pass
    dcg_to_slow_conditions parameter
  • Updated GetGroupsToFireTestCase setUp to precompute
    dcg_to_slow_conditions
  • Updated all get_groups_to_fire calls to include dcg_to_slow_conditions
    parameter
+14/-2   
test_parameterization.py
Parameterization test cleanup after regex experiment removal

tests/sentry/grouping/test_parameterization.py

  • Removed import of ParameterizationRegexExperiment class
  • Removed unused mock import
  • Simplified imports to only include Parameterizer and
    UniqueIdExperiment
+1/-44   
test_project_details.py
Project details test autofix automation tuning default update

tests/sentry/api/endpoints/test_project_details.py

  • Changed default autofix automation tuning value from "low" to "off" in
    test assertions
  • Updated two test cases to expect "off" as the default value
+2/-2     
test_project.py
Project serializer test autofix automation tuning default

tests/sentry/api/serializers/test_project.py

  • Updated test comment from "low" to "off" for default autofix
    automation tuning
  • Updated assertion to expect "off" as the default value
+2/-2     
test_delete_replays_bulk.py
Replay bulk delete test null segment ID update                     

tests/sentry/replays/tasks/test_delete_replays_bulk.py

  • Changed max_segment_id value from 0 to None in test data
+1/-1     
tableWidgetVisualization.spec.tsx
Tests for table widget visualization component                     

static/app/views/dashboards/widgets/tableWidget/tableWidgetVisualization.spec.tsx

  • New test suite for TableWidgetVisualization component
  • Tests basic rendering, custom column ordering, number field
    formatting, and custom renderers
  • Validates proper display of duration, percentage, and rate units
+107/-0 
useGetTraceItemAttributeValues.spec.tsx
Update tests for renamed attribute values hook                     

static/app/views/explore/hooks/useGetTraceItemAttributeValues.spec.tsx

  • Updated import to use renamed useGetTraceItemAttributeValues hook
  • Updated test description to match new hook name
  • Removed attributeKey parameter from hook calls
+4/-6     
Enhancement
33 files
project_replay_summarize_breadcrumbs.py
Error event integration into replay breadcrumb analysis   

src/sentry/replays/endpoints/project_replay_summarize_breadcrumbs.py

  • Introduced ErrorEvent TypedDict to represent error details with id,
    title, message, timestamp, and category
  • Added fetch_error_details function to retrieve error information from
    nodestore using error IDs
  • Refactored get_request_data and created gen_request_data generator to
    merge breadcrumbs and errors chronologically
  • Updated analyze_recording_segments to accept and process error events
    alongside breadcrumb data
  • Added error context fetching from replay instance with optional
    disable flag via query parameter
+118/-18
test_pr_comment.py
GitHub PR comment formatting with environment context       

tests/sentry/integrations/github/tasks/test_pr_comment.py

  • Added environment field to test event data for multiple test cases
  • Updated expected comment formatting from bullet list with culprit to
    markdown links with environment info
  • Removed culprits variable extraction and updated assertion logic to
    use new template format
  • Changed comment body format from - ‼️ **title** \culprit\ to * ‼️
    [**title**](url) in \environment\
+23/-9   
browser_reporting_collector.py
Browser reporting API validation refactoring with serializers

src/sentry/issues/endpoints/browser_reporting_collector.py

  • Replaced BrowserReport dataclass with BrowserReportSerializer for
    validation using DRF serializers
  • Converted BrowserReportType Literal to BROWSER_REPORT_TYPES list
    constant
  • Added validation logic for timestamp/age mutual exclusivity
    constraints
  • Updated response handling to return proper REST framework Response
    objects with validation error details
  • Improved error handling with detailed validation error reporting
+64/-33 
test_pr_comment.py
GitLab PR comment formatting with environment context       

tests/sentry/integrations/gitlab/tasks/test_pr_comment.py

  • Added environment field to test event data for multiple test cases
  • Updated expected comment formatting to use markdown links with
    environment info
  • Removed culprits variable and updated assertion logic for new template
    format
  • Changed comment body format from bullet list with culprit to markdown
    links with optional environment
+29/-11 
delayed_workflow.py
Delayed workflow slow conditions optimization and logging

src/sentry/workflow_engine/processors/delayed_workflow.py

  • Added dcg_to_slow_conditions parameter to get_condition_query_groups
    and get_groups_to_fire functions
  • Moved get_slow_conditions_for_groups call to main processing function
    to avoid redundant queries
  • Added logging for data condition groups without slow conditions
  • Fixed variable name from event_data to workflow_event_data in
    fire_actions_for_groups logging
+17/-5   
detector.py
Detector owner field support in workflow engine validators

src/sentry/workflow_engine/endpoints/validators/base/detector.py

  • Added ActorField import for owner field validation
  • Added owner field to BaseDetectorTypeValidator serializer as optional
    nullable field
  • Implemented owner field handling in update method to set owner_user_id
    or owner_team_id based on actor type
  • Implemented owner field handling in create method to properly
    initialize detector with owner information
+30/-0   
feedback_summaries.py
Feedback summarization prompt refinement with constraints

src/sentry/feedback/usecases/feedback_summaries.py

  • Updated prompt instructions to be more specific about avoiding generic
    statements
  • Added emphasis on identifying broader themes across multiple feedback
    entries
  • Added strict word limit constraint (55 words maximum) and sentence
    limit (2 sentences maximum)
  • Changed feedback separator from newline with dash to newline with
    dashes
+5/-3     
commit_context.py
PR comment template utilities with title truncation and environment

src/sentry/integrations/source_code_management/commit_context.py

  • Added ISSUE_TITLE_MAX_LENGTH constant and
    MERGED_PR_SINGLE_ISSUE_TEMPLATE constant
  • Implemented _truncate_title static method to limit title length with
    ellipsis
  • Implemented get_environment_info method to extract environment from
    recommended event
  • Implemented get_merged_pr_single_issue_template static method for
    consistent issue formatting
+35/-0   
integration.py
GitHub integration PR comment template refactoring             

src/sentry/integrations/github/integration.py

  • Removed MERGED_PR_SINGLE_ISSUE_TEMPLATE constant definition
  • Updated get_comment_body to use get_merged_pr_single_issue_template
    method
  • Changed template parameters from subtitle (culprit) to environment
    info
+2/-4     
integration.py
GitLab integration PR comment template refactoring             

src/sentry/integrations/gitlab/integration.py

  • Removed MERGED_PR_SINGLE_ISSUE_TEMPLATE constant definition
  • Updated get_comment_body to use get_merged_pr_single_issue_template
    method
  • Changed template parameters from subtitle (culprit) to environment
    info
+2/-4     
organization_preprod_artifact_assemble.py
Preprod artifact assemble endpoint analytics tracking       

src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py

  • Added analytics import
  • Added analytics event recording for preprod_artifact.api.assemble with
    organization, project, and user IDs
+9/-1     
workflow.py
Workflow engine logger initialization refactoring               

src/sentry/workflow_engine/processors/workflow.py

  • Removed direct logging import
  • Changed logger initialization to use log_context.get_logger(__name__)
+1/-2     
ourlogs.py
Ourlogs top events timeseries query equations parameter   

src/sentry/snuba/ourlogs.py

  • Added optional equations parameter to run_top_events_timeseries_query
    function
  • Passed equations parameter through to
    rpc_dataset_common.run_top_events_timeseries_query
+2/-0     
analytics.py
Preprod artifact analytics event definition                           

src/sentry/preprod/analytics.py

  • Created new analytics event class PreprodArtifactApiAssembleEvent
  • Defined event type as preprod_artifact.api.assemble
  • Registered event with organization_id, project_id, and optional
    user_id attributes
+14/-0   
toolbarVisualize.tsx
Refactor visualization model from multi-axis to single-axis

static/app/views/explore/toolbar/toolbarVisualize.tsx

  • Removed unused Fragment import
  • Changed Visualize constructor to accept single yAxis string instead of
    array
  • Simplified deleteOverlay to remove entire visualization group instead
    of individual y-axes
  • Refactored visualization rendering to remove nested Fragment structure
  • Updated canDelete logic to check visualization count instead of total
    y-axes
+22/-43 
tableWidgetVisualization.tsx
New table widget visualization component                                 

static/app/views/dashboards/widgets/tableWidget/tableWidgetVisualization.tsx

  • New component for rendering tabular data with customizable columns and
    cell renderers
  • Supports custom head and body cell rendering with fallback to default
    renderers
  • Includes options for scrollable, frameless, and fit-to-content table
    layouts
  • Provides loading placeholder component
+134/-0 
useGetTraceItemAttributeKeys.tsx
New hook for fetching trace item attribute keys                   

static/app/views/explore/hooks/useGetTraceItemAttributeKeys.tsx

  • New hook for fetching trace item attribute keys from the API
  • Supports filtering by attribute type (string/number) and search query
  • Filters out known sentry-prefixed attributes except for
    sentry.message.*
  • Validates attribute keys against allowed character patterns
+133/-0 
chart.tsx
Add feature-flagged table widget visualization                     

static/app/views/dashboards/widgetCard/chart.tsx

  • Added import for TableWidgetVisualization component
  • Added feature flag check for use-table-widget-visualization
  • Conditionally renders new TableWidgetVisualization or falls back to
    StyledSimpleTableChart
  • Currently renders empty table data as placeholder
+34/-22 
defaultTableCellRenderers.tsx
Default cell renderers for table widget                                   

static/app/views/dashboards/widgets/tableWidget/defaultTableCellRenderers.tsx

  • New module providing default cell renderers for table headers and body
    cells
  • Header renderer displays column name with tooltip and alignment
  • Body renderer uses field renderers with unit formatting support
  • Supports custom renderer overrides
+104/-0 
visualizes.tsx
Refactor Visualize model to single-axis architecture         

static/app/views/explore/contexts/pageParamsContext/visualizes.tsx

  • Changed Visualize class to use single yAxis string instead of yAxes
    array
  • Updated constructor, clone, and replace methods to work with single
    axis
  • Modified toJSON() to wrap single yAxis in array for backward
    compatibility
  • Changed fromJSON() to return array of Visualize objects, one per
    y-axis
  • Updated getVisualizesFromLocation() to create separate visualizations
    per y-axis
+15/-14 
timeAndScrubberGrid.tsx
Add analytics tracking for timeline zoom actions                 

static/app/components/replays/timeAndScrubberGrid.tsx

  • Added useCallback import and trackAnalytics tracking
  • Created handleZoomOut and handleZoomIn callbacks with analytics
    tracking
  • Replaced inline onClick handlers with memoized callbacks
  • Tracks replay.timeline.zoom-in and replay.timeline.zoom-out events
+22/-3   
useAnalytics.tsx
Update analytics to work with single-axis visualizations 

static/app/views/explore/hooks/useAnalytics.tsx

  • Removed dedupeArray import and usage
  • Changed analytics tracking to call toJSON() on visualizes
  • Updated computeConfidence and computeEmptyBuckets to use single yAxis
    instead of array
  • Simplified visualization field extraction logic
+5/-7     
times.tsx
Improve text overflow handling and use Flex component       

static/app/components/group/times.tsx

  • Added Flex and TextOverflow component imports
  • Replaced custom FlexWrapper with Flex align="center"
  • Wrapped TimeSince components with TextOverflow for better text
    handling
  • Updated IconClock to use size="xs" instead of legacySize
  • Added min-width to StyledIconClock for proper alignment
+16/-13 
index.tsx
Update charts to work with single-axis visualizations       

static/app/views/explore/charts/index.tsx

  • Removed dedupeArray import
  • Changed getChartInfo to accept single yAxis string instead of array
  • Updated visualization processing to use visualize.yAxis instead of
    visualize.yAxes
  • Simplified y-axes deduplication logic
+5/-6     
feedbackSummary.tsx
New feedback summary component with AI integration             

static/app/components/feedback/feedbackSummary.tsx

  • New component displaying AI-generated feedback summary
  • Shows summary only if feature flag enabled and sufficient feedbacks
    exist
  • Displays loading placeholder while fetching summary
  • Includes icon, header, and summary content with styled layout
+64/-0   
aggregateFields.tsx
Update aggregate fields for single-axis visualizations     

static/app/views/explore/contexts/pageParamsContext/aggregateFields.tsx

  • Exported isBaseVisualize function for external use
  • Updated isVisualize check to look for yAxis string instead of yAxes
    array
  • Updated getAggregateFieldsFromLocation to create single-axis
    visualizations
  • Modified updateLocationWithAggregateFields to flatten visualize arrays
    and handle new structure
+7/-6     
feedbackListPage.tsx
Integrate feedback summary into feedback list page             

static/app/views/feedback/feedbackListPage.tsx

  • Added FeedbackSummary component import
  • Wrapped feedback list with new SummaryListContainer to include summary
    above list
  • Added SummaryListContainer styled component with flex column layout
  • Updated grid template columns for better responsive layout
+14/-4   
useFeedbackSummary.tsx
New hook for fetching feedback summary                                     

static/app/components/feedback/list/useFeedbackSummary.tsx

  • New hook for fetching AI-generated feedback summary from API
  • Supports date range and project filtering via page filters
  • Returns summary text, loading state, error state, and insufficient
    data flag
  • Includes feature flag check for user-feedback-ai-summaries
+67/-0   
utils.tsx
Update explore utils for single-axis visualizations           

static/app/views/explore/utils.tsx

  • Removed dedupeArray import
  • Updated viewSamplesTarget to iterate single yAxis instead of array
  • Updated computeVisualizeSampleTotals to use single yAxis
  • Simplified field extraction logic
+10/-13 
aggregateColumnEditorModal.tsx
Update column editor for single-axis visualizations           

static/app/views/explore/tables/aggregateColumnEditorModal.tsx

  • Updated handleApply to call toJSON() on visualize objects
  • Changed insertColumn call to use single yAxis string
  • Updated VisualizeSelector to access visualize.yAxis instead of array
  • Updated onChange calls to use single yAxis parameter
+5/-5     
replayAnalyticsEvents.tsx
Add timeline zoom analytics events                                             

static/app/utils/analytics/replayAnalyticsEvents.tsx

  • Added replay.timeline.zoom-in and replay.timeline.zoom-out event types
  • Added corresponding event map entries for analytics tracking
+4/-0     
index.tsx
Update page params context for single-axis visualizations

static/app/views/explore/contexts/pageParamsContext/index.tsx

  • Added isBaseVisualize import
  • Updated defaultSortBys call to use single yAxis instead of array
  • Updated findAllFieldRefs to use single yAxis and isBaseVisualize
    filter
+4/-3     
toolbarSaveAs.tsx
Update toolbar save as for single-axis visualizations       

static/app/views/explore/toolbar/toolbarSaveAs.tsx

  • Removed dedupeArray import
  • Updated visualizeYAxes to map single yAxis instead of flattening array
  • Updated chart options processing to use single yAxis
+2/-3     
Bug fix
5 files
parameterization.py
Parameterization regex experiment removal and simplification

src/sentry/grouping/parameterization.py

  • Removed ParameterizationRegexExperiment class that was unused
  • Updated ParameterizationExperiment type alias to only include
    ParameterizationCallableExperiment
  • Simplified experiment execution logic to only handle callable
    experiments
  • Removed conditional branching for regex vs callable experiment types
+3/-15   
0920_convert_org_saved_searches_to_views_revised.py
Migration 0920 disabled with reference to corrected version

src/sentry/migrations/0920_convert_org_saved_searches_to_views_revised.py

  • Replaced migration implementation with no-op function and comment
  • Removed all SavedSearch to GroupSearchView conversion logic
  • Added reference to corrected migration 0921
+3/-20   
0917_convert_org_saved_searches_to_views.py
Migration 0917 disabled with reference to corrected version

src/sentry/migrations/0917_convert_org_saved_searches_to_views.py

  • Replaced migration implementation with no-op function and comment
  • Removed all SavedSearch to GroupSearchView conversion logic
  • Added reference to corrected migration 0921
+3/-18   
delete.py
Replay deletion null segment ID handling                                 

src/sentry/replays/usecases/delete.py

  • Added null check for max_segment_id in _make_recording_filenames
    function
  • Updated MatchedRow TypedDict to allow max_segment_id to be None
  • Added early return when segment IDs are null to prevent processing
    errors
+6/-1     
index.tsx
Simplify project retrieval in replay AI view                         

static/app/views/replays/detail/ai/index.tsx

  • Removed decodeScalar and useLocationQuery imports
  • Simplified project retrieval to use replayRecord?.project_id directly
  • Added error handling for missing project
+9/-6     
Configuration changes
6 files
deliver_webhooks.py
Webhook delivery task processing deadline configuration   

src/sentry/hybridcloud/tasks/deliver_webhooks.py

  • Added processing_deadline_duration=30 to schedule_webhook_delivery
    task configuration
  • Added processing_deadline_duration=300 to drain_mailbox task
    configuration
  • Added processing_deadline_duration=120 to drain_mailbox_parallel task
    configuration
+3/-0     
defaults.py
Autofix automation tuning default value change                     

src/sentry/projectoptions/defaults.py

  • Changed default value for sentry:autofix_automation_tuning from "low"
    to "off"
+1/-1     
constants.py
Constants autofix automation tuning default update             

src/sentry/constants.py

  • Changed DEFAULT_AUTOFIX_AUTOMATION_TUNING_DEFAULT constant from "low"
    to "off"
+1/-1     
check_auth.py
Auth check identities task processing deadline configuration

src/sentry/tasks/auth/check_auth.py

  • Added processing_deadline_duration=60 to check_auth_identities task
    configuration
+3/-1     
grouptype.py
DB query injection vulnerability noise configuration         

src/sentry/issues/grouptype.py

  • Added noise_config = NoiseConfig(ignore_limit=5) to
    DBQueryInjectionVulnerabilityGroupType
+1/-0     
config.yml
Add metrics service and subscription result consumers       

devservices/config.yml

  • Added snuba-metrics service configuration for fast aggregation and
    query capabilities
  • Added four new Kafka consumer services for subscription results
    (eap-spans, eap-items, metrics, generic-metrics)
  • Added comprehensive tracing profile with all required services for
    trace processing
  • Added consumer commands for the four new subscription result services
+47/-0   
Refactoring
14 files
newTraceDetailsHeader.tsx
Replace custom flex components with Flex component             

static/app/components/events/interfaces/spans/newTraceDetailsHeader.tsx

  • Replaced custom FlexBox and BreakDownRow styled components with Flex
    component
  • Updated layout to use Flex with align="center" and
    justify="space-between" props
  • Simplified styled component definitions
+18/-25 
integratedOrgSelector.tsx
Replace custom flex containers with Flex component             

static/app/components/codecov/integratedOrgSelector/integratedOrgSelector.tsx

  • Replaced custom FlexContainer styled components with Flex component
  • Updated to use Flex with justify and gap props
  • Removed custom styled component definitions
+5/-19   
row.tsx
Replace custom flex center components with Flex                   

static/app/views/alerts/list/rules/row.tsx

  • Replaced custom FlexCenter styled components with Flex component
  • Updated to use Flex align="center" for all alignment needs
  • Removed custom styled component definitions
+9/-14   
codeOwnerFileTable.tsx
Replace custom flex components with Flex                                 

static/app/views/settings/project/projectOwnership/codeOwnerFileTable.tsx

  • Replaced custom FlexCenter styled components with Flex component
  • Updated to use Flex align="center" gap={space(1)} for consistent
    spacing
  • Removed custom styled component definitions
+13/-18 
addUploadToken.tsx
Replace custom flex containers with Flex component             

static/app/views/codecov/tests/onboardingSteps/addUploadToken.tsx

  • Removed styled import from emotion
  • Replaced custom FlexContainer styled components with Flex component
  • Updated to use Flex justify="space-between" gap={space(1)}
  • Removed custom styled component definitions
+9/-16   
traceTabsAndVitals.tsx
Replace custom flex components with Flex                                 

static/app/views/performance/newTraceDetails/traceTabsAndVitals.tsx

  • Added Flex component import
  • Replaced custom FlexBox and Container styled components with Flex
  • Updated placeholder and main layout to use Flex with appropriate props
  • Removed custom styled component definitions
+9/-18   
teamMisery.tsx
Replace custom flex components with Flex                                 

static/app/views/organizationStats/teamInsights/teamMisery.tsx

  • Added Flex component import
  • Replaced custom FlexCenter styled components with Flex align="center"
  • Updated table header and data cells to use Flex component
+7/-11   
organizationSampleRateInput.tsx
Replace custom flex components with Flex                                 

static/app/views/settings/dynamicSampling/organizationSampleRateInput.tsx

  • Added Flex component import
  • Replaced custom FlexRow and Wrapper styled components with Flex
  • Updated to use Flex gap={space(1)} for consistent spacing
  • Renamed Wrapper to SampleRateRow for clarity
+6/-9     
alertRuleStatus.tsx
Replace custom flex component with Flex                                   

static/app/views/alerts/list/rules/alertRuleStatus.tsx

  • Added Flex component import
  • Replaced custom FlexCenter styled component with Flex align="center"
+3/-8     
branchSelector.tsx
Replace custom flex container with Flex                                   

static/app/components/codecov/branchSelector/branchSelector.tsx

  • Added Flex component import
  • Replaced custom FlexContainer with Flex align="center"
    gap={space(0.75)}
+3/-8     
useGetTraceItemAttributeValues.tsx
Refactor trace item attribute values hook                               

static/app/views/explore/hooks/useGetTraceItemAttributeValues.tsx

  • Renamed hook from useTraceItemAttributeValues to
    useGetTraceItemAttributeValues
  • Renamed interface from UseTraceItemAttributeValuesProps to
    UseGetTraceItemAttributeValuesProps
  • Removed attributeKey, enabled, and search parameters
  • Updated imports to use types from explore/types
+7/-11   
codeSnippet.tsx
Replace custom flex spacer with Flex.Item                               

static/app/components/codeSnippet.tsx

  • Added Flex component import
  • Replaced custom FlexSpacer styled component with Flex.Item grow={1}
+3/-6     
repoSelector.tsx
Replace custom flex container with Flex                                   

static/app/components/codecov/repoPicker/repoSelector.tsx

  • Added Flex component import
  • Replaced custom FlexContainer with Flex align="center"
    gap={space(0.75)}
+3/-8     
eventAttachments.tsx
Replace custom flex component with Flex                                   

static/app/components/events/eventAttachments.tsx

  • Added Flex component import
  • Replaced custom FlexCenter with Flex align="center"
  • Added spacing between attachment name and size
+4/-8     
Additional files
35 files
defaults.py +0/-5     
__init__.py +1/-0     
dateSelector.tsx +3/-8     
styles.chonk.tsx +1/-1     
groupingVariant.tsx +1/-63   
breadcrumbItem.tsx +1/-1     
scrollCarousel.tsx +1/-1     
types.tsx +7/-0     
sampleHTTPRequestTableData.ts +41/-0   
tableWidgetVisualization.stories.tsx +141/-0 
traceItemSearchQueryBuilder.tsx +2/-4     
index.spec.tsx +21/-21 
sortBys.tsx +2/-2     
visualizes.spec.tsx +18/-35 
useAddToDashboard.tsx +3/-4     
useExploreAggregatesTable.tsx +3/-5     
useTopEvents.tsx +1/-7     
useTraceItemAttributeKeys.tsx +37/-85 
spansTab.tsx +1/-2     
aggregateColumnEditorModal.spec.tsx +22/-23 
index.spec.tsx +19/-19 
toolbarSortBy.tsx +1/-1     
types.tsx +17/-0   
utils.spec.tsx +1/-1     
chartActionDropdown.tsx +1/-0     
transactionNameSearchBar.tsx +2/-4     
attributes.tsx +6/-2     
traceWaterfall.tsx +3/-9     
index.tsx +3/-3     
auditLogList.tsx +4/-9     
integrationLayout.tsx +2/-6     
instanceLevelOAuthDetails.tsx +3/-8     
tabularColumn.ts +11/-0   
tabularColumns.ts +9/-0     
test_0917_convert_org_saved_searches_to_views.py +0/-34   

armenzg and others added 30 commits June 20, 2025 12:49
…o 'low' (#93927)"

This reverts commit 8d04522.

Co-authored-by: roaga <[email protected]>
Missed in the initial commit, leading to some relevant logs being
unannotated.
We have had a few tasks get killed at 10% rollout.
Also add a test, so that this doesn't happen again
Fixes DE-129 and DE-156

---------

Co-authored-by: Cursor Agent <[email protected]>
These transitions should be matching
…` (#93946)

Use `project_id` on the replay record instead of the URL (where it does
not always exist).

---------

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
Also fixed `replay.view_html` -> `replay.view-html`

---------

Co-authored-by: Michelle Zhang <[email protected]>
…948)

gets `npx @typescript/native-preview` passing again
The conditions associated with a DCG can change over time, and it's good
if we can be completely confident that they're consistent within a given
task execution.
This is unused and most regex experiments have required broader changes
to ensure that regexes are evaluated in a specific order (ex:
traceparent). Removing this for now to simplify the code and very
slightly improve runtime performance.
From some testing (on feedback lists of all different lengths), this
prompt seems to work better. It doesn't write overly long sentences and
also does a better job at "summarizing" versus just mentioning a few
specific topics and leaving out others.
Just remove a couple custom Flex* classes in favor of the Flex primitive
This has been killed a few times.

Refs SENTRY-42M7
…n table (#93892)

<!-- Describe your PR here. -->

[ticket](https://linear.app/getsentry/issue/ID-156/grouping-info-remove-type-field-from-ui)
The Type field in the Grouping Info section of the issue details page
was redundant.
This removes the Type row from all variant types while keeping the
underlying data structure intact.

before
![Screenshot 2025-06-20 at 12 00
54 PM](https://github.com/user-attachments/assets/97ca72da-0a52-4446-9825-cd4fcb505adf)

after
![Screenshot 2025-06-20 at 11 59
29 AM](https://github.com/user-attachments/assets/a4284d2b-c9f5-442f-b010-7fe72a598e39)
### Changes
Related to this PR: getsentry/sentry#93810. This
is part 1 of the change, which is pulling out the new component and just
adding it to the repo. Also includes some simplification of the logic in
the base component.

Part 2 will be replacing tables in widgets.

### Before/After

There is no UI change as the table is not being used yet. There is a new
story page for the component.
…93943)

to prevent this issue from becoming too noisy, add a noise config
Unfortunately, 'event_data' went from being the variable for current
event context to being the complete parsed data from Redis, and we
continued logging it per group.
That's more data than we should be logging even arguably once, let alone
per group.
Adds some simple analytics to our endpoint so we can begin building a
dashboard in Amplitude.
Previously, explore supported multiple y axis per chart, so each
visualize supported multiple y axis. That functionality has since been
removed for simplicity so update the types here to match. Keep in mind
that saved queries still store them as an array so when
serializing/deserializing, we still need to treat it as an array.
We'll need the `useGetTraceItemAttributeKeys` hook in other places so
refactoring it so that it can exported.
mrduncan and others added 2 commits June 20, 2025 13:20
When the max segment ID is null the process fails. We should exit early
since if there aren't any segments to delete there's nothing to do.
@qodo-code-review
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Sensitive information exposure

Description: Untrusted event data and generated error messages are concatenated into a single
prompt-like "logs" payload sent to an external service, which can leak sensitive error
details; consider redacting PII or enforcing scrubbing before assembling request_data.
project_replay_summarize_breadcrumbs.py [146-168]

Referred Code
error_idx = 0

# Process segments
for _, segment in iterator:
    events = json.loads(segment.tobytes().decode("utf-8"))
    for event in events:
        # Check if we need to yield any error messages that occurred before this event
        while error_idx < len(error_events) and error_events[error_idx][
            "timestamp"
        ] < event.get("timestamp", 0):
            error = error_events[error_idx]
            yield generate_error_log_message(error)
            error_idx += 1

        # Yield the current event's log message
        if message := as_log_message(event):
            yield message

# Yield any remaining error messages
while error_idx < len(error_events):
    error = error_events[error_idx]


 ... (clipped 2 lines)
Sensitive information exposure

Description: The endpoint logs full raw request bodies on validation failure and receipt, potentially
storing sensitive browser-reported URLs or messages in logs; reduce log detail or redact
fields before logging.
browser_reporting_collector.py [93-121]

Referred Code
logger.info("browser_report_received", extra={"request_body": request.data})

# Browser Reporting API sends an array of reports
# request.data could be any type, so we need to validate and cast
raw_data: Any = request.data

if not isinstance(raw_data, list):
    logger.warning(
        "browser_report_invalid_format",
        extra={"data_type": type(raw_data).__name__, "data": raw_data},
    )
    return Response(status=HTTP_422_UNPROCESSABLE_ENTITY)

# Validate each report in the array
validated_reports = []
for report in raw_data:
    serializer = BrowserReportSerializer(data=report)
    if not serializer.is_valid():
        logger.warning(
            "browser_report_validation_failed",
            extra={"validation_errors": serializer.errors, "raw_report": report},


 ... (clipped 8 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Audit coverage: While an analytics event is recorded for artifact assembly, it is unclear if all critical
actions across the changes (e.g., replay deletions, workflow engine actions) are
consistently audit-logged with user and outcome context.

Referred Code
"""
Assembles a preprod artifact (mobile build, etc.) and stores it in the database.
"""

analytics.record(
    "preprod_artifact.api.assemble",
    organization_id=project.organization_id,
    project_id=project.id,
    user_id=request.user.id,
)
Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Error details exposure: Generated log messages include error titles and messages which may be surfaced externally
depending on downstream handling, requiring verification that these are not exposed to
end-users.

Referred Code
def generate_error_log_message(error: ErrorEvent) -> str:
    title = error["title"]
    message = error["message"]
    timestamp = error["timestamp"]

    return f"User experienced an error: '{title}: {message}' at {timestamp}"
Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Raw data logging: The endpoint logs the full request body for browser reports which may contain sensitive
fields; confirm logs are scrubbed or fields are safe.

Referred Code
logger.info("browser_report_received", extra={"request_body": request.data})

# Browser Reporting API sends an array of reports
# request.data could be any type, so we need to validate and cast
raw_data: Any = request.data

if not isinstance(raw_data, list):
    logger.warning(
        "browser_report_invalid_format",
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix incorrect event data mapping

Fix a potential bug in fetch_error_details by using a node_id to event_id map to
correctly associate event data, instead of relying on the order of
nodestore.backend.get_multi results.

src/sentry/replays/endpoints/project_replay_summarize_breadcrumbs.py [104-123]

 def fetch_error_details(project_id: int, error_ids: list[str]) -> list[ErrorEvent]:
     """Fetch error details given error IDs and return a list of ErrorEvent objects."""
     try:
-        node_ids = [Event.generate_node_id(project_id, event_id=id) for id in error_ids]
-        events = nodestore.backend.get_multi(node_ids)
+        node_id_map = {
+            Event.generate_node_id(project_id, event_id=eid): eid for eid in error_ids
+        }
+        events_data = nodestore.backend.get_multi(list(node_id_map.keys()))
 
-        return [
-            ErrorEvent(
-                category="error",
-                id=event_id,
-                title=data.get("title", ""),
-                timestamp=data.get("timestamp", 0.0),
-                message=data.get("message", ""),
-            )
-            for event_id, data in zip(error_ids, events.values())
-            if data is not None
-        ]
+        results = []
+        for node_id, data in events_data.items():
+            if data is not None:
+                event_id = node_id_map[node_id]
+                results.append(
+                    ErrorEvent(
+                        category="error",
+                        id=event_id,
+                        title=data.get("title", ""),
+                        timestamp=data.get("timestamp", 0.0),
+                        message=data.get("message", ""),
+                    )
+                )
+        return results
     except Exception as e:
         sentry_sdk.capture_exception(e)
         return []
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical bug where event_id and event data could be mismatched due to reliance on dictionary value order, which is not guaranteed and would lead to incorrect data processing.

High
Fix incomplete feature implementation

Replace the hardcoded empty data in TableWidgetVisualization with actual data
from tableResults to complete the feature implementation.

static/app/views/dashboards/widgetCard/chart.tsx [164-175]

 {organization.features.includes('use-table-widget-visualization') ? (
   <TableWidgetVisualization
-    columns={[]}
+    columns={eventView.fields.map(field => ({
+      key: field.field,
+      name: field.field,
+      type: result.meta.fields[field.field],
+    }))}
     tableData={{
-      data: [],
-      meta: {
-        fields: {},
-        units: {},
-      },
+      data: result.data,
+      meta: result.meta,
     }}
   />
 ) : (
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly points out that a new feature behind a flag is incomplete because it uses placeholder data, and provides a correct implementation to make it functional.

Medium
Enforce presence of a time field

Add a validate method to BrowserReportSerializer to ensure that either the age
or timestamp field is present in the report data, preventing reports from being
accepted without any time information.

src/sentry/issues/endpoints/browser_reporting_collector.py [36-60]

 class BrowserReportSerializer(serializers.Serializer[Any]):
     """Serializer for validating browser report data structure."""
 
     body = serializers.DictField()
     type = serializers.ChoiceField(choices=BROWSER_REPORT_TYPES)
     url = serializers.URLField()
     user_agent = serializers.CharField()
     destination = serializers.CharField()
     attempts = serializers.IntegerField(min_value=1)
     # Fields that do not overlap between specs
     # We need to support both specs
     age = serializers.IntegerField(required=False)
     timestamp = serializers.IntegerField(required=False, min_value=0)
 
+    def validate(self, data: dict[str, Any]) -> dict[str, Any]:
+        """Validate that either age or timestamp is present."""
+        if "age" not in data and "timestamp" not in data:
+            raise serializers.ValidationError("Either 'age' or 'timestamp' must be present.")
+        return data
+
     def validate_timestamp(self, value: int) -> int:
         """Validate that age is absent, but timestamp is present."""
         if self.initial_data.get("age"):
             raise serializers.ValidationError("If timestamp is present, age must be absent")
         return value
 
     def validate_age(self, value: int) -> int:
         """Validate that age is present, but not timestamp."""
         if self.initial_data.get("timestamp"):
             raise serializers.ValidationError("If age is present, timestamp must be absent")
         return value
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that neither age nor timestamp are required, which could lead to reports without time information. Adding validation to ensure at least one is present improves data integrity.

Medium
Prevent potential runtime error

Add a fallback empty object to Object.keys(tableData?.meta?.fields) to prevent a
potential TypeError if tableData or its nested properties are undefined.

static/app/views/dashboards/widgets/tableWidget/tableWidgetVisualization.tsx [92-99]

 // Fallback to extracting fields from the tableData if no columns are provided
 const columnOrder: TabularColumn[] =
   columns ??
-  Object.keys(tableData?.meta.fields).map((key: string) => ({
+  Object.keys(tableData?.meta?.fields ?? {}).map((key: string) => ({
     key,
     name: key,
     width: -1,
-    type: tableData?.meta.fields[key],
+    type: tableData?.meta?.fields?.[key],
   }));

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a potential TypeError if tableData or tableData.meta is falsy and provides a robust fix, improving code safety.

Medium
General
Optimize data fetching logic

Enable the useApiQuery based on the presence of replayRecord?.project_id instead
of the asynchronously loaded project object to start fetching data earlier.

static/app/views/replays/detail/ai/index.tsx [56-75]

 function AiContent({replayRecord}: Props) {
   const {replay} = useReplayContext();
   const organization = useOrganization();
   const project = useProjectFromId({project_id: replayRecord?.project_id});
 
   const {
     data: summaryData,
     isPending,
     isError,
     isRefetching,
   } = useApiQuery<SummaryResponse>(
     makeGetReplaySummaryQueryKey(organization.slug, replay?.getId()),
     {
       staleTime: Infinity,
       enabled:
         organization.features.includes('replay-ai-summary') &&
         !replay?.isSampled() &&
-        !!project,
+        !!replayRecord?.project_id,
     }
   );

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a performance issue where an API call is unnecessarily delayed and provides a fix to enable the query sooner.

Medium
Handle negative max segment ID values

In _make_recording_filenames, add a check to handle cases where max_segment_id
might be negative. Log a warning and return an empty list to prevent silent
failures and improve debugging.

src/sentry/replays/usecases/delete.py [86-95]

 def _make_recording_filenames(project_id: int, row: MatchedRow) -> list[str]:
     # Null segment_ids can cause this to fail. If no segments were ingested then we can skip
     # deleting the segements.
     if row["max_segment_id"] is None:
+        return []
+
+    if row["max_segment_id"] < 0:
+        logger.warning(
+            "replays.usecases.delete.invalid_max_segment_id",
+            extra={"replay_id": row["replay_id"], "max_segment_id": row["max_segment_id"]},
+        )
         return []
 
     # We assume every segment between 0 and the max_segment_id exists. Its a waste of time to
     # delete a non-existent segment but its not so significant that we'd want to query ClickHouse
     # to verify it exists.
     return [
         make_filename(project_id, row["replay_id"], segment_id)
         for segment_id in range(row["max_segment_id"] + 1)
     ]

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 5

__

Why: The suggestion adds a defensive check for a negative max_segment_id, which is a valid edge case to consider for robustness, and adds logging to make potential data inconsistencies visible.

Low
  • More

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.