From e4c1c3fe7de1395f7900189086fbf16c5fd7d767 Mon Sep 17 00:00:00 2001 From: Chris Klochek Date: Mon, 6 Oct 2025 14:45:20 -0400 Subject: [PATCH 1/3] feat(uptime): have results consumer disabled disallowed uptime detecctors --- pyproject.toml | 2 +- .../uptime/consumers/results_consumer.py | 11 ++++++++ .../uptime/consumers/test_results_consumer.py | 26 +++++++++++++++++++ uv.lock | 6 ++--- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c527003667c047..d6b09c56e85573 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,7 +79,7 @@ dependencies = [ # [end] jsonschema format validators "sentry-arroyo>=2.29.6", "sentry-forked-email-reply-parser>=0.5.12.post1", - "sentry-kafka-schemas>=2.1.6", + "sentry-kafka-schemas>=2.1.7", "sentry-ophio>=1.1.3", "sentry-protos>=0.4.1", "sentry-redis-tools>=0.5.0", diff --git a/src/sentry/uptime/consumers/results_consumer.py b/src/sentry/uptime/consumers/results_consumer.py index b84d38dba92983..a0d4371fc7a523 100644 --- a/src/sentry/uptime/consumers/results_consumer.py +++ b/src/sentry/uptime/consumers/results_consumer.py @@ -11,6 +11,7 @@ from sentry_kafka_schemas.codecs import Codec from sentry_kafka_schemas.schema_types.snuba_uptime_results_v1 import SnubaUptimeResult from sentry_kafka_schemas.schema_types.uptime_results_v1 import ( + CHECKSTATUS_DISALLOWED_BY_ROBOTS, CHECKSTATUS_MISSED_WINDOW, CheckResult, ) @@ -34,6 +35,7 @@ ) from sentry.uptime.subscriptions.subscriptions import ( check_and_update_regions, + disable_uptime_detector, remove_uptime_subscription_if_unused, ) from sentry.uptime.subscriptions.tasks import ( @@ -296,6 +298,15 @@ def handle_result(self, subscription: UptimeSubscription | None, result: CheckRe } subscription_regions = load_regions_for_uptime_subscription(subscription.id) + if result["status"] == CHECKSTATUS_DISALLOWED_BY_ROBOTS: + try: + detector = get_detector(subscription) + logger.info("disallowed_by_robots", extra=result) + disable_uptime_detector(detector) + except Exception as e: + logger.info("disallowed_by_robots.error", extra={"error": e, "result": result}) + return + # Discard shadow mode region results if is_shadow_region_result(result, subscription_regions): metrics.incr( diff --git a/tests/sentry/uptime/consumers/test_results_consumer.py b/tests/sentry/uptime/consumers/test_results_consumer.py index 222310b4e9b38c..9fc793ed84d751 100644 --- a/tests/sentry/uptime/consumers/test_results_consumer.py +++ b/tests/sentry/uptime/consumers/test_results_consumer.py @@ -32,6 +32,7 @@ from sentry.testutils.thread_leaks.pytest import thread_leak_allowlist from sentry.uptime.consumers.eap_converter import convert_uptime_result_to_trace_items from sentry.uptime.consumers.results_consumer import ( + CHECKSTATUS_DISALLOWED_BY_ROBOTS, UptimeResultsStrategyFactory, build_last_seen_interval_key, build_last_update_key, @@ -523,6 +524,31 @@ def test_missed(self) -> None: with pytest.raises(Group.DoesNotExist): Group.objects.get(grouphash__hash=hashed_fingerprint) + @override_options({"uptime.snuba_uptime_results.enabled": False}) + def test_disallowed(self) -> None: + features = [ + "organizations:uptime", + "organizations:uptime-create-issues", + ] + result = self.create_uptime_result( + self.subscription.subscription_id, status=CHECKSTATUS_DISALLOWED_BY_ROBOTS + ) + with ( + mock.patch("sentry.uptime.consumers.results_consumer.logger") as logger, + self.feature(features), + ): + assert self.detector.enabled + + self.send_result(result) + + logger.info.assert_any_call( + "disallowed_by_robots", + extra={**result}, + ) + + self.detector.refresh_from_db() + assert not self.detector.enabled + def test_onboarding_failure(self) -> None: features = [ "organizations:uptime", diff --git a/uv.lock b/uv.lock index 64c2ce400a9342..2f9c3189102409 100644 --- a/uv.lock +++ b/uv.lock @@ -2101,7 +2101,7 @@ requires-dist = [ { name = "rfc3986-validator", specifier = ">=0.1.1" }, { name = "sentry-arroyo", specifier = ">=2.29.6" }, { name = "sentry-forked-email-reply-parser", specifier = ">=0.5.12.post1" }, - { name = "sentry-kafka-schemas", specifier = ">=2.1.6" }, + { name = "sentry-kafka-schemas", specifier = ">=2.1.7" }, { name = "sentry-ophio", specifier = ">=1.1.3" }, { name = "sentry-protos", specifier = ">=0.4.1" }, { name = "sentry-redis-tools", specifier = ">=0.5.0" }, @@ -2272,7 +2272,7 @@ wheels = [ [[package]] name = "sentry-kafka-schemas" -version = "2.1.6" +version = "2.1.7" source = { registry = "https://pypi.devinfra.sentry.io/simple" } dependencies = [ { name = "fastjsonschema", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, @@ -2283,7 +2283,7 @@ dependencies = [ { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] wheels = [ - { url = "https://pypi.devinfra.sentry.io/wheels/sentry_kafka_schemas-2.1.6-py2.py3-none-any.whl", hash = "sha256:385e43b268c81a822fd88fc797f6143d79e3b4c9de86ce67a974b07ddbdcb25f" }, + { url = "https://pypi.devinfra.sentry.io/wheels/sentry_kafka_schemas-2.1.7-py2.py3-none-any.whl", hash = "sha256:b58f20ef5228c48c8061f90e863825a609040c73512b8bd2aa50747d0ba0e89e" }, ] [[package]] From 9d513b383f9f223a998f9e5df9a7936533a93125 Mon Sep 17 00:00:00 2001 From: Chris Klochek Date: Fri, 10 Oct 2025 14:36:50 -0400 Subject: [PATCH 2/3] adjust logging; add metric --- src/sentry/uptime/consumers/results_consumer.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sentry/uptime/consumers/results_consumer.py b/src/sentry/uptime/consumers/results_consumer.py index a0d4371fc7a523..9cde85bb26fa67 100644 --- a/src/sentry/uptime/consumers/results_consumer.py +++ b/src/sentry/uptime/consumers/results_consumer.py @@ -302,9 +302,14 @@ def handle_result(self, subscription: UptimeSubscription | None, result: CheckRe try: detector = get_detector(subscription) logger.info("disallowed_by_robots", extra=result) + metrics.incr( + "uptime.result_processor.disallowed_by_robots", + sample_rate=1.0, + tags={"uptime_region": result.get("region", "default")}, + ) disable_uptime_detector(detector) except Exception as e: - logger.info("disallowed_by_robots.error", extra={"error": e, "result": result}) + logger.exception("disallowed_by_robots.error", extra={"error": e, "result": result}) return # Discard shadow mode region results From c5451275c41a442214b8e70aab740a24adb6e78a Mon Sep 17 00:00:00 2001 From: Chris Klochek Date: Tue, 14 Oct 2025 10:15:15 -0400 Subject: [PATCH 3/3] fix import --- tests/sentry/uptime/consumers/test_results_consumer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sentry/uptime/consumers/test_results_consumer.py b/tests/sentry/uptime/consumers/test_results_consumer.py index 9fc793ed84d751..878ee04bc8edb6 100644 --- a/tests/sentry/uptime/consumers/test_results_consumer.py +++ b/tests/sentry/uptime/consumers/test_results_consumer.py @@ -13,6 +13,7 @@ from arroyo.types import BrokerValue, Partition, Topic from django.test import override_settings from sentry_kafka_schemas.schema_types.uptime_results_v1 import ( + CHECKSTATUS_DISALLOWED_BY_ROBOTS, CHECKSTATUS_FAILURE, CHECKSTATUS_MISSED_WINDOW, CHECKSTATUS_SUCCESS, @@ -32,7 +33,6 @@ from sentry.testutils.thread_leaks.pytest import thread_leak_allowlist from sentry.uptime.consumers.eap_converter import convert_uptime_result_to_trace_items from sentry.uptime.consumers.results_consumer import ( - CHECKSTATUS_DISALLOWED_BY_ROBOTS, UptimeResultsStrategyFactory, build_last_seen_interval_key, build_last_update_key,