From 1d87c9bfa3b3f3adc22f1f0259628b222869d4d2 Mon Sep 17 00:00:00 2001 From: ArthurKnaus Date: Fri, 29 May 2026 12:36:36 +0200 Subject: [PATCH 01/12] feat(issue-details): Enable Autofix for low-value spans (#116468) Enable Seer Autofix for low-value span configuration issues. Low-value span issues now opt into the issue detail Autofix surface while keeping the existing static configuration issue details behavior. Co-authored-by: OpenAI Codex --- .../utils/issueTypeConfig/configurationIssuesConfig.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/static/app/utils/issueTypeConfig/configurationIssuesConfig.tsx b/static/app/utils/issueTypeConfig/configurationIssuesConfig.tsx index dcf480602663f8..46933185b21bc0 100644 --- a/static/app/utils/issueTypeConfig/configurationIssuesConfig.tsx +++ b/static/app/utils/issueTypeConfig/configurationIssuesConfig.tsx @@ -14,6 +14,11 @@ const staticConfigurationIssueDetails = { }, }; +const lowValueSpanConfigurationIssueDetails = { + ...staticConfigurationIssueDetails, + autofix: true, +}; + export const configurationIssuesConfig: IssueCategoryConfigMapping = { _categoryDefaults: { actions: { @@ -65,5 +70,5 @@ export const configurationIssuesConfig: IssueCategoryConfigMapping = { groupingInfo: {enabled: false}, }, [IssueType.SOURCEMAP_CONFIGURATION]: staticConfigurationIssueDetails, - [IssueType.LOW_VALUE_SPAN_CONFIGURATION]: staticConfigurationIssueDetails, + [IssueType.LOW_VALUE_SPAN_CONFIGURATION]: lowValueSpanConfigurationIssueDetails, }; From 26fc044470179f4b24d4701e80f8fe116ee8d8a9 Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 13:27:26 +0100 Subject: [PATCH 02/12] feat(autofix): add Seer Agent debug button to Autofix header (#116166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Adds an `IconBot` button to the Seer Autofix drawer header (`SeerDrawerHeader`) that opens the Seer Agent pane pre-loaded with the current Autofix `run_id`. **Behaviour:** - Button appears in the Autofix header next to the existing Refresh/Copy buttons - Clicking it calls `openSeerExplorerDrawer({runId})`, which dispatches the run ID into Seer Agent state and opens the pane - Hidden until an Autofix run exists (`runState?.run_id` must be defined) - Only visible to Sentry employees (`useIsSentryEmployee()`), matching the existing debug-UI convention used in the Seer Agent pane's slash commands (`/langfuse`, `/conversations`) ## Files changed - `static/app/components/events/autofix/v3/header.tsx` — adds `onOpenSeerAgent` prop and `IconBot` button gated on `useIsSentryEmployee` - `static/app/components/events/autofix/v3/drawer.tsx` — wires `useHandleOpenSeerAgent` hook via `useSeerExplorerDrawer` ## Verification Imports verified: `IconBot`, `useIsSentryEmployee`, `useSeerExplorerDrawer` all exist at their paths. Typecheck unavailable in sandbox (no `node_modules`); shape follows existing patterns exactly. ## After CleanShot 2026-05-26 at 12 05
20@2x --- [View Session in Sentry](https://sentry.sentry.io/traces/?project=4510944073809921&query=gen_ai.conversation.id%3A%22slack%3AC0B448X3T3J%3A1779792979.178209%22) Action taken on behalf of Hector Dearman. --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: Hector Dearman Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com> --- .../components/events/autofix/v3/drawer.tsx | 19 +++++++++++++++++++ .../components/events/autofix/v3/header.tsx | 15 +++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/static/app/components/events/autofix/v3/drawer.tsx b/static/app/components/events/autofix/v3/drawer.tsx index da89552d27bcc0..8823a9d0b20ecb 100644 --- a/static/app/components/events/autofix/v3/drawer.tsx +++ b/static/app/components/events/autofix/v3/drawer.tsx @@ -20,6 +20,7 @@ import {defined} from 'sentry/utils'; import {useAutoScroll} from 'sentry/utils/useAutoScroll'; import {useCopyToClipboard} from 'sentry/utils/useCopyToClipboard'; import {useAiConfig} from 'sentry/views/issueDetails/hooks/useAiConfig'; +import {useSeerExplorerDrawer} from 'sentry/views/seerExplorer/components/drawer/useSeerExplorerDrawer'; interface SeerDrawerProps { group: Group; @@ -32,6 +33,7 @@ export function SeerDrawer({group, project}: SeerDrawerProps) { const handleCopyMarkdown = useHandleCopyMarkdown({aiAutofix}); const handleRestart = useHandleRestart({aiAutofix}); + const handleOpenSeerAgent = useHandleOpenSeerAgent({aiAutofix}); const referrer = useMemo( () => getReferrerFromBlocks(aiAutofix.runState?.blocks ?? []), @@ -62,6 +64,7 @@ export function SeerDrawer({group, project}: SeerDrawerProps) { > @@ -115,3 +118,19 @@ function useHandleRestart({ startStep('root_cause'); }, [startStep]); } + +function useHandleOpenSeerAgent({ + aiAutofix, +}: { + aiAutofix: ReturnType; +}): (() => void) | undefined { + const {openSeerExplorerDrawer} = useSeerExplorerDrawer(); + const runId = aiAutofix.runState?.run_id; + + return useMemo(() => { + if (!defined(runId)) { + return; + } + return () => openSeerExplorerDrawer({runId}); + }, [openSeerExplorerDrawer, runId]); +} diff --git a/static/app/components/events/autofix/v3/header.tsx b/static/app/components/events/autofix/v3/header.tsx index 67404c07d55765..9165514ee59363 100644 --- a/static/app/components/events/autofix/v3/header.tsx +++ b/static/app/components/events/autofix/v3/header.tsx @@ -7,21 +7,26 @@ import {Flex} from '@sentry/scraps/layout'; import {Text} from '@sentry/scraps/text'; import {getReferrerConfig} from 'sentry/components/events/autofix/autofixReferrer'; +import {IconBot} from 'sentry/icons/iconBot'; import {IconCopy} from 'sentry/icons/iconCopy'; import {IconRefresh} from 'sentry/icons/iconRefresh'; import {t} from 'sentry/locale'; +import {useIsSentryEmployee} from 'sentry/utils/useIsSentryEmployee'; interface SeerDrawerHeaderProps { onCopyMarkdown?: () => void; + onOpenSeerAgent?: () => void; onReset?: () => void; referrer?: string; } export function SeerDrawerHeader({ onCopyMarkdown, + onOpenSeerAgent, onReset, referrer, }: SeerDrawerHeaderProps) { + const isSentryEmployee = useIsSentryEmployee(); const tooltip = useMemo(() => { const config = getReferrerConfig(referrer); return config.tooltip ?? referrer; @@ -53,6 +58,16 @@ export function SeerDrawerHeader({ aria-label={t('Copy analysis as Markdown')} variant="transparent" /> + {isSentryEmployee && onOpenSeerAgent && ( + +``` + +**Props:** + +| Prop | Required | Purpose | +| -------------------- | -------- | ----------------------------------------------- | +| `analyticsEventKey` | Yes | Reload event key (snake_case with dots) | +| `analyticsEventName` | No | Amplitude display name. Omit to skip Amplitude. | +| `analyticsParams` | No | Additional key-value pairs sent with the event | + +**Rules:** + +- Prefer button props over a manual `trackAnalytics` call in an `onClick` handler. +- If you need the event to be type-safe and appear in the typed event registry, also define it in the domain event file. Button props work without registration but lose type safety. +- The tracking fires via `TrackingContext` — the GetSentry override wires it to Reload/Amplitude. + +## Manual `trackAnalytics()` Calls + +Use for interactions that aren't button clicks or page views: toggles, drag actions, form submissions, modal opens, etc. + +```typescript +import {trackAnalytics} from 'sentry/utils/analytics'; + +function handleFilterChange(filterType: string) { + trackAnalytics('feedback.filter-applied', { + organization, + filter_type: filterType, + source: 'list', + }); + // ... actual handler logic +} +``` + +**Rules:** + +- Always pass `organization` (string slug or Organization object). +- The event key must be defined in a `*EventParameters` type and registered in the domain event map. +- Call `trackAnalytics` at the point of user action, not in render or effects (unless tracking a "viewed" event). +- For "viewed" events in components that aren't route-level, use a `useEffect`: + +```typescript +useEffect(() => { + trackAnalytics('feedback.banner-viewed', { + organization, + }); +}, [organization]); +``` + +## Area Context + +Use `AnalyticsArea` to tag events with their UI location. This is useful when the same component appears in multiple contexts. + +```tsx +import {AnalyticsArea, useAnalyticsArea} from 'sentry/components/analyticsArea'; + +// Wrap a section of UI + + + {/* useAnalyticsArea() returns "feedback.details" */} + +; + +// Use in a component +function MyComponent() { + const area = useAnalyticsArea(); + + function handleClick() { + trackAnalytics('feedback.action-clicked', { + organization, + area, // "feedback.details" + }); + } +} +``` + +**Rules:** + +- Areas nest with dot notation: `outer.inner`. +- Use `overrideParent` to strip the outer area (e.g., for modals that should have their own top-level area). +- Do not branch app logic on the area value — it is for analytics metadata only. + +## Choosing Between Patterns + +| Situation | Use | +| -------------------------------------- | ----------------------------------------------- | +| User navigates to a page | Route analytics hooks | +| User clicks a `