feat(metric-issues): Add observed value to occurrence evidence_display - #120713
Draft
isaacwang-sentry wants to merge 2 commits into
Draft
feat(metric-issues): Add observed value to occurrence evidence_display#120713isaacwang-sentry wants to merge 2 commits into
isaacwang-sentry wants to merge 2 commits into
Conversation
Metric issue occurrences shipped an empty evidence_display, so the value that actually breached was never exposed as curated evidence - it existed only inside the internal evidence_data payload. Emit a single important row carrying the observed value labeled with the metric it measures. One row by design: the monitor definition (threshold, query, environment, detection type) is current detector state served by the detector-context path, while this is the point-in-time breach value, the one fact only the occurrence has. Keeping it to one row honors the one-important-row-per-occurrence convention, since space-constrained integrations surface only the first. The value is read from values["value"] directly rather than through extract_value(), whose anomaly-detection branch wraps the result in a group-keyed dict. The aggregate-display logic is factored out of construct_title into format_aggregate(), which returns both the display label and the normalized aggregate key - the crash-rate branch strips an alias suffix off the key, and it is that stripped key, not the label, that dynamic alert classification consumes. No UI change: metricConfig.tsx sets evidence to null for the METRIC category, so the Evidence section stays hidden. Applies to newly created occurrences only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e union DataPacket is invariant in its type parameter, so DataPacket[AnomalyDetectionUpdate] is not assignable to the DataPacket[MetricUpdate] that build_evidence_display accepts. Annotate the variable with the union instead, matching the existing pattern in tests/sentry/issues/test_ingest.py. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Metric issue occurrences shipped
evidence_display=[](with anXXX: may need to pass more info here for the front endnote), so the value that actually breached was never exposed as curated evidence — it existed only inside the internalevidence_datapayload. This is the Sentry half of the AIML-3164 work in the Autofix Support for Metric Issues project.This emits a single
important=Truerow:Why exactly one row, and why only the value
The monitor's definition — threshold, query, environment, detection type — is current detector state, served by the
detector_contextpath (#120370 + its Seer-side rendering). The observed value is the point-in-time breach value, the one fact only the occurrence has. Duplicating the definition here would put two blocks in one LLM prompt that contradict each other as soon as a detector is edited after the occurrence was created.One row also honors the
IssueEvidence"only one important row per occurrence" convention, since space-constrained integrations surface only the first.Two implementation details worth a look
Reading the value.
build_evidence_displayreadsdata_packet.packet.values["value"]directly rather than callingself.extract_value(), whose anomaly-detection branch wraps the result in a group-keyed dict. BothMetricUpdatevariants (ProcessedSubscriptionUpdate,AnomalyDetectionUpdate) definevalueswith avalue: floatkey, so direct access is uniform. A test drives a realAnomalyDetectionUpdatethrough this path — asserting ondetection_type="dynamic"in a title test would not have exercised it.The aggregate helper returns two values.
format_aggregate()is factored out ofconstruct_titleand returns(display label, normalized aggregate key). These diverge: the crash-rate branch strips theAS <CRASH_RATE_ALERT_AGGREGATE_ALIAS>suffix off the key, and it is that stripped key — not the display label — thatget_alert_type_from_aggregate_datasetconsumes. A display-only helper would have silently changed dynamic alert titles. The logic moved verbatim;construct_titlebehavior is unchanged.Impact
MetricIssue.category = GroupCategory.METRICroutes tometricConfig.tsx, which setsevidence: nullin_categoryDefaultsand does not re-enable it forIssueType.METRIC_ISSUE, soEventEvidencereturns null regardless. (metricIssueConfig.tsxservesIssueCategory.METRIC_ALERT— a different category.) Enabling that section is a separate product/design call.jira/integration.pyreadsimportant_evidence_display. Slack/Discord/MSTeams/PagerDuty/Opsgenie/Email route throughmetric_alert_registryand are unaffected.evidence_display=[]; there is no backfill.Tests
tests/sentry/incidents/test_metric_issue_detector_handler.pyhad noevidence_displayassertions — the sharedverify_issue_occurrencehelper checks onlyevidence_data. Added coverage for the row's name/value, exactly-one-important, static / comparison-delta / dynamic variants, and all fourformat_aggregatebranches (mapped, unmapped, MRI, equation, crash-rate alias).46 passed. Reverting
evidence_displayto[]fails 9 of the new tests, so they check behavior rather than restate the implementation.🤖 Generated with Claude Code