Skip to content

feat(autofix): Add metrics and logging for filtered-out seer automation issues#111486

Merged
chromy merged 8 commits intomasterfrom
trevorelkins/aiml-2686-add-metrics-for-filtered-out-autofix-issues
Mar 26, 2026
Merged

feat(autofix): Add metrics and logging for filtered-out seer automation issues#111486
chromy merged 8 commits intomasterfrom
trevorelkins/aiml-2686-add-metrics-for-filtered-out-autofix-issues

Conversation

@trevor-e
Copy link
Member

Extracts the filter logic from kick_off_seer_automation() into two helper functions (_get_default_seer_automation_skip_reason and _get_seat_based_seer_automation_skip_reason) that return a string reason when an issue is skipped. This enables a single metrics.incr and logger.info call per filtered issue instead of silent returns.

Previously, ~14 return points in this function silently dropped issues with no observability. Only the 3 rate-limit paths emitted any signal. Now every skip reason is tagged and visible:

  • already_has_fixability_score, not_eligible, lock_already_held, rate_limited (default tier)
  • summary_already_cached, summary_already_dispatched, already_triggered, issue_too_old, fixability_too_low, automation_already_dispatched, no_connected_repos (seat-based tier)

Metric: seer.automation.filtered with reason and tier tags.

Refs AIML-2686

…on issues

Extract filter logic from kick_off_seer_automation into two helper
functions that return skip reasons. This enables a single metrics.incr
and logger.info call per filtered issue, giving visibility into why
issues are being skipped (e.g. fixability too low, issue too old,
no connected repos, already triggered).

Refs AIML-2686
Co-Authored-By: Claude <noreply@anthropic.com>
@linear-code
Copy link

linear-code bot commented Mar 24, 2026

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Mar 24, 2026
Replace bare str return type with a SeerAutomationSkipReason Literal
union for type safety on skip reason values.

Refs AIML-2686
Co-Authored-By: Claude <noreply@anthropic.com>
)
logger.info(
"seer.automation.filtered",
extra={"group_id": group.id, "reason": skip_reason, "tier": "seat_based"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe could have organization_id on the logger call just to have that to hand

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the logger call for now since I think this is called for every occurrence which might be too high-volume. I don't see other logs in this path.

# Check if summary exists in cache
if group.times_seen_with_pending < 10:
generate_issue_summary_only.delay(group.id)
else:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we never get to this case now:

        if group.times_seen_with_pending < 10:
            generate_issue_summary_only.delay(group.id)

because we also check this in _get_seat_based_seer_automation_skip_reason and early return if that returns non-zero.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to be if skip_reason is not None which _get_seat_based_seer_automation_skip_reason should return None in this case and pass.

Move SeerAutomationSkipReason, get_default_seer_automation_skip_reason,
and get_seat_based_seer_automation_skip_reason into a new
src/sentry/seer/autofix/trigger.py file. This makes the trigger
decision logic self-contained and easier to follow.

Refs AIML-2686
Co-Authored-By: Claude <noreply@anthropic.com>
Move lazy imports to top-level in trigger.py since there are no
circular dependency concerns. Pass the locks manager from
post_process.py rather than recreating it.

Refs AIML-2686
Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Restore original comments in trigger.py and post_process.py. Use
`if skip_reason is not None` instead of `if skip_reason` for clarity.

Refs AIML-2686
Co-Authored-By: Claude <noreply@anthropic.com>
Revert to lazy imports in trigger.py to match original post_process.py
behavior and avoid mock patching issues. Move the >= 10 no-summary
rate limit check back to kick_off_seer_automation to avoid a TOCTOU
race from reading the cache twice.

Refs AIML-2686
Co-Authored-By: Claude <noreply@anthropic.com>
@trevor-e trevor-e marked this pull request as ready for review March 26, 2026 01:18
@trevor-e trevor-e requested review from a team as code owners March 26, 2026 01:18
…NCE_THRESHOLD

Co-Authored-By: Claude <noreply@anthropic.com>
@chromy chromy merged commit 126e6a6 into master Mar 26, 2026
74 checks passed
@chromy chromy deleted the trevorelkins/aiml-2686-add-metrics-for-filtered-out-autofix-issues branch March 26, 2026 11:15
trevor-e added a commit that referenced this pull request Mar 26, 2026
…on (#111638)

Adds granular `metrics.incr("seer.automation.filtered")` at every filter
point in `kick_off_seer_automation()`, with specific `reason` and `tier`
tags. Previously ~14 return points silently skipped issues with no
observability.

Extracts filter logic from `kick_off_seer_automation()` into
`src/sentry/seer/autofix/trigger.py` with two helper functions
(`get_default_seer_automation_skip_reason`,
`get_seat_based_seer_automation_skip_reason`) that return typed skip
reasons. The generic `not_eligible` reason is broken down into 5
specific sub-reasons via `get_seer_automation_ineligibility_reason()`:

- `not_eligible.issue_category_ineligible`
- `not_eligible.gen_ai_feature_disabled`
- `not_eligible.ai_features_hidden`
- `not_eligible.scanner_not_enabled`
- `not_eligible.no_budget`

This builds on #111486 which added the initial metrics/refactor — that
PR has already been merged. This PR adds the `not_eligible` breakdown
and moves the eligibility functions from `utils.py` to `trigger.py` to
consolidate trigger decision logic.

Refs AIML-2686

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants