diff --git a/src/sentry/seer/anomaly_detection/delete_rule.py b/src/sentry/seer/anomaly_detection/delete_rule.py index 0be8feab60805d..bcf85f75009606 100644 --- a/src/sentry/seer/anomaly_detection/delete_rule.py +++ b/src/sentry/seer/anomaly_detection/delete_rule.py @@ -1,12 +1,10 @@ import logging from typing import TYPE_CHECKING, cast -from django.conf import settings from urllib3.exceptions import MaxRetryError, TimeoutError from sentry.conf.server import SEER_ALERT_DELETION_URL from sentry.models.organization import Organization -from sentry.net.http import connection_from_url from sentry.seer.anomaly_detection.types import DeleteAlertDataRequest from sentry.seer.signed_seer_api import make_signed_seer_api_request from sentry.utils import json @@ -14,9 +12,6 @@ logger = logging.getLogger(__name__) -seer_anomaly_detection_connection_pool = connection_from_url( - settings.SEER_ANOMALY_DETECTION_URL, timeout=settings.SEER_DEFAULT_TIMEOUT -) if TYPE_CHECKING: from sentry.incidents.models.alert_rule import AlertRule @@ -26,6 +21,8 @@ def delete_rule_in_seer(alert_rule: "AlertRule") -> bool: """ Send a request to delete an alert rule from Seer. Returns True if the request was successful. """ + from sentry.seer.anomaly_detection.utils import SEER_ANOMALY_DETECTION_CONNECTION_POOL + body = DeleteAlertDataRequest( organization_id=cast(Organization, alert_rule.organization).id, alert={"id": alert_rule.id}, @@ -36,7 +33,7 @@ def delete_rule_in_seer(alert_rule: "AlertRule") -> bool: try: response = make_signed_seer_api_request( - connection_pool=seer_anomaly_detection_connection_pool, + connection_pool=SEER_ANOMALY_DETECTION_CONNECTION_POOL, path=SEER_ALERT_DELETION_URL, body=json.dumps(body).encode("utf-8"), ) diff --git a/src/sentry/seer/anomaly_detection/get_anomaly_data.py b/src/sentry/seer/anomaly_detection/get_anomaly_data.py index c1504e3d884439..a79f411c570a4c 100644 --- a/src/sentry/seer/anomaly_detection/get_anomaly_data.py +++ b/src/sentry/seer/anomaly_detection/get_anomaly_data.py @@ -1,11 +1,9 @@ import logging -from django.conf import settings from urllib3.exceptions import MaxRetryError, TimeoutError from sentry.conf.server import SEER_ANOMALY_DETECTION_ENDPOINT_URL from sentry.incidents.models.alert_rule import AlertRule -from sentry.net.http import connection_from_url from sentry.seer.anomaly_detection.types import ( AlertInSeer, AnomalyDetectionConfig, @@ -13,7 +11,10 @@ DetectAnomaliesResponse, TimeSeriesPoint, ) -from sentry.seer.anomaly_detection.utils import translate_direction +from sentry.seer.anomaly_detection.utils import ( + SEER_ANOMALY_DETECTION_CONNECTION_POOL, + translate_direction, +) from sentry.seer.signed_seer_api import make_signed_seer_api_request from sentry.snuba.models import QuerySubscription from sentry.utils import json @@ -21,11 +22,6 @@ logger = logging.getLogger(__name__) -SEER_ANOMALY_DETECTION_CONNECTION_POOL = connection_from_url( - settings.SEER_ANOMALY_DETECTION_URL, - timeout=settings.SEER_ANOMALY_DETECTION_TIMEOUT, -) - def get_anomaly_data_from_seer( alert_rule: AlertRule, diff --git a/src/sentry/seer/anomaly_detection/get_historical_anomalies.py b/src/sentry/seer/anomaly_detection/get_historical_anomalies.py index 16a921eb8d3621..1bc7a94d6f9a02 100644 --- a/src/sentry/seer/anomaly_detection/get_historical_anomalies.py +++ b/src/sentry/seer/anomaly_detection/get_historical_anomalies.py @@ -1,14 +1,12 @@ import logging from datetime import datetime, timedelta -from django.conf import settings from urllib3.exceptions import MaxRetryError, TimeoutError from sentry.api.bases.organization_events import get_query_columns from sentry.conf.server import SEER_ANOMALY_DETECTION_ENDPOINT_URL from sentry.incidents.models.alert_rule import AlertRule, AlertRuleStatus from sentry.models.project import Project -from sentry.net.http import connection_from_url from sentry.seer.anomaly_detection.store_data import _get_start_and_end_indices from sentry.seer.anomaly_detection.types import ( AnomalyDetectionConfig, @@ -19,6 +17,7 @@ TimeSeriesPoint, ) from sentry.seer.anomaly_detection.utils import ( + SEER_ANOMALY_DETECTION_CONNECTION_POOL, fetch_historical_data, format_historical_data, translate_direction, @@ -31,11 +30,6 @@ logger = logging.getLogger(__name__) -seer_anomaly_detection_connection_pool = connection_from_url( - settings.SEER_ANOMALY_DETECTION_URL, - timeout=settings.SEER_ANOMALY_DETECTION_TIMEOUT, -) - def handle_seer_error_responses(response, config, context, log_params): def log_statement(log_level, text, extra_data=None): @@ -127,7 +121,7 @@ def get_historical_anomaly_data_from_seer_preview( } try: response = make_signed_seer_api_request( - connection_pool=seer_anomaly_detection_connection_pool, + connection_pool=SEER_ANOMALY_DETECTION_CONNECTION_POOL, path=SEER_ANOMALY_DETECTION_ENDPOINT_URL, body=json.dumps(body).encode("utf-8"), ) @@ -225,7 +219,7 @@ def get_historical_anomaly_data_from_seer( ) try: response = make_signed_seer_api_request( - seer_anomaly_detection_connection_pool, + SEER_ANOMALY_DETECTION_CONNECTION_POOL, SEER_ANOMALY_DETECTION_ENDPOINT_URL, json.dumps(body).encode("utf-8"), ) diff --git a/src/sentry/seer/anomaly_detection/store_data.py b/src/sentry/seer/anomaly_detection/store_data.py index f5a752562db19a..ac6e6c3c69c29a 100644 --- a/src/sentry/seer/anomaly_detection/store_data.py +++ b/src/sentry/seer/anomaly_detection/store_data.py @@ -3,7 +3,6 @@ from enum import StrEnum from typing import Any -from django.conf import settings from django.core.exceptions import ValidationError from parsimonious.exceptions import ParseError from urllib3.exceptions import MaxRetryError, TimeoutError @@ -12,7 +11,6 @@ from sentry.conf.server import SEER_ANOMALY_DETECTION_STORE_DATA_URL from sentry.incidents.models.alert_rule import AlertRule, AlertRuleDetectionType, AlertRuleStatus from sentry.models.project import Project -from sentry.net.http import connection_from_url from sentry.seer.anomaly_detection.types import ( AlertInSeer, AnomalyDetectionConfig, @@ -21,6 +19,7 @@ TimeSeriesPoint, ) from sentry.seer.anomaly_detection.utils import ( + SEER_ANOMALY_DETECTION_CONNECTION_POOL, fetch_historical_data, format_historical_data, get_dataset_from_label, @@ -33,11 +32,6 @@ from sentry.utils.json import JSONDecodeError logger = logging.getLogger(__name__) - -seer_anomaly_detection_connection_pool = connection_from_url( - settings.SEER_ANOMALY_DETECTION_URL, - timeout=settings.SEER_ANOMALY_DETECTION_TIMEOUT, -) MIN_DAYS = 7 @@ -218,7 +212,7 @@ def send_historical_data_to_seer( ) try: response = make_signed_seer_api_request( - connection_pool=seer_anomaly_detection_connection_pool, + connection_pool=SEER_ANOMALY_DETECTION_CONNECTION_POOL, path=SEER_ANOMALY_DETECTION_STORE_DATA_URL, body=json.dumps(body).encode("utf-8"), ) diff --git a/src/sentry/seer/anomaly_detection/utils.py b/src/sentry/seer/anomaly_detection/utils.py index 472c5b04fc8a24..a0afa81136213b 100644 --- a/src/sentry/seer/anomaly_detection/utils.py +++ b/src/sentry/seer/anomaly_detection/utils.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta from typing import Any +from django.conf import settings from django.utils import timezone from django.utils.datastructures import MultiValueDict from rest_framework.exceptions import ParseError @@ -11,6 +12,7 @@ from sentry.incidents.models.alert_rule import AlertRule, AlertRuleThresholdType from sentry.models.organization import Organization from sentry.models.project import Project +from sentry.net.http import connection_from_url from sentry.search.events.types import SnubaParams from sentry.seer.anomaly_detection.types import AnomalyType, TimeSeriesPoint from sentry.snuba import metrics_performance @@ -23,6 +25,11 @@ NUM_DAYS = 28 +SEER_ANOMALY_DETECTION_CONNECTION_POOL = connection_from_url( + settings.SEER_ANOMALY_DETECTION_URL, + timeout=settings.SEER_ANOMALY_DETECTION_TIMEOUT, +) + SNUBA_QUERY_EVENT_TYPE_TO_STRING = { SnubaQueryEventType.EventType.ERROR: "error", SnubaQueryEventType.EventType.DEFAULT: "default", diff --git a/tests/sentry/incidents/test_logic.py b/tests/sentry/incidents/test_logic.py index f59da692ec8862..3433af144c7afc 100644 --- a/tests/sentry/incidents/test_logic.py +++ b/tests/sentry/incidents/test_logic.py @@ -94,8 +94,8 @@ from sentry.integrations.pagerduty.utils import add_service from sentry.integrations.services.integration.serial import serialize_integration from sentry.models.group import GroupStatus -from sentry.seer.anomaly_detection.store_data import seer_anomaly_detection_connection_pool from sentry.seer.anomaly_detection.types import StoreDataResponse +from sentry.seer.anomaly_detection.utils import SEER_ANOMALY_DETECTION_CONNECTION_POOL from sentry.shared_integrations.exceptions import ApiRateLimitedError, ApiTimeoutError from sentry.silo.base import SiloMode from sentry.snuba.dataset import Dataset @@ -840,9 +840,7 @@ def test_create_alert_load_shedding_comparison(self): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_create_alert_rule_anomaly_detection(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -890,9 +888,7 @@ def test_create_alert_rule_anomaly_detection(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_create_alert_rule_anomaly_detection_not_enough_data(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -913,9 +909,7 @@ def test_create_alert_rule_anomaly_detection_not_enough_data(self, mock_seer_req @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_create_alert_rule_anomaly_detection_no_data(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -933,9 +927,7 @@ def test_create_alert_rule_anomaly_detection_no_data(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") @patch("sentry.seer.anomaly_detection.store_data.logger") def test_create_alert_rule_anomaly_detection_seer_timeout_max_retry( self, mock_logger, mock_seer_request @@ -956,13 +948,13 @@ def test_create_alert_rule_anomaly_detection_seer_timeout_max_retry( time_window=self.dynamic_metric_alert_settings["time_window"], ).exists() assert mock_logger.warning.call_count == 1 - assert mock_seer_request.call_count == 1 + assert mock_seer_request.call_count == 2 # 1 for create, 1 for delete because create failed mock_seer_request.reset_mock() mock_logger.reset_mock() mock_seer_request.side_effect = MaxRetryError( - seer_anomaly_detection_connection_pool, SEER_ANOMALY_DETECTION_STORE_DATA_URL + SEER_ANOMALY_DETECTION_CONNECTION_POOL, SEER_ANOMALY_DETECTION_STORE_DATA_URL ) with pytest.raises(TimeoutError): @@ -978,11 +970,9 @@ def test_create_alert_rule_anomaly_detection_seer_timeout_max_retry( time_window=self.dynamic_metric_alert_settings["time_window"], ).exists() assert mock_logger.warning.call_count == 1 - assert mock_seer_request.call_count == 1 + assert mock_seer_request.call_count == 2 # 1 for create, 1 for delete because create failed - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_create_alert_rule_anomaly_detection_no_feature(self, mock_seer_request): with pytest.raises(ResourceDoesNotExist): create_alert_rule( @@ -1490,18 +1480,11 @@ def test_update_alert_load_shedding_on_comparison_and_window(self): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) - @patch( - "sentry.seer.anomaly_detection.delete_rule.seer_anomaly_detection_connection_pool.urlopen" - ) - def test_update_detection_type(self, mock_seer_delete_request, mock_seer_request): + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") + def test_update_detection_type(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) - mock_seer_delete_request.return_value = HTTPResponse( - orjson.dumps(seer_return_value), status=200 - ) + comparison_delta = 60 # test percent to dynamic rule = self.create_alert_rule( @@ -1607,9 +1590,7 @@ def test_update_detection_type(self, mock_seer_delete_request, mock_seer_request @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_infer_detection_type(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -1667,9 +1648,7 @@ def test_update_infer_detection_type(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_dynamic_alerts(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -1695,7 +1674,9 @@ def test_update_dynamic_alerts(self, mock_seer_request): assert mock_seer_request.call_count == 0 mock_seer_request.reset_mock() # update name - update_alert_rule(dynamic_rule, name="everything is broken") + update_alert_rule( + dynamic_rule, detection_type=AlertRuleDetectionType.DYNAMIC, name="everything is broken" + ) dynamic_rule.refresh_from_db() assert dynamic_rule.name == "everything is broken" assert mock_seer_request.call_count == 0 @@ -1722,9 +1703,7 @@ def test_update_dynamic_alerts(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_dynamic_alert_static_to_dynamic(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -1741,9 +1720,7 @@ def test_update_dynamic_alert_static_to_dynamic(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_dynamic_alert_percent_to_dynamic(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -1761,9 +1738,7 @@ def test_update_dynamic_alert_percent_to_dynamic(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_alert_rule_static_to_dynamic_enough_data(self, mock_seer_request): """ Assert that the status is PENDING if enough data exists. @@ -1790,9 +1765,7 @@ def test_update_alert_rule_static_to_dynamic_enough_data(self, mock_seer_request @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_dynamic_alert_not_enough_to_pending(self, mock_seer_request): """ Update a dynamic rule's aggregate so the rule's status changes from not enough data to enough/pending @@ -1829,9 +1802,7 @@ def test_update_dynamic_alert_not_enough_to_pending(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_dynamic_alert_pending_to_not_enough(self, mock_seer_request): """ Update a dynamic rule's aggregate so the rule's status changes from enough/pending to not enough data @@ -1871,9 +1842,7 @@ def test_update_dynamic_alert_pending_to_not_enough(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_alert_rule_static_to_dynamic_not_enough_data(self, mock_seer_request): """ Assert that the status is NOT_ENOUGH_DATA if we don't have 7 days of data. @@ -1900,9 +1869,7 @@ def test_update_alert_rule_static_to_dynamic_not_enough_data(self, mock_seer_req @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_alert_rule_dynamic_to_static_status(self, mock_seer_request): """ Assert that the alert rule status changes to PENDING if we switch from a dynamic alert to another type of alert. @@ -1937,9 +1904,7 @@ def test_update_alert_rule_dynamic_to_static_status(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") @patch("sentry.seer.anomaly_detection.store_data.logger") def test_update_alert_rule_anomaly_detection_seer_timeout_max_retry( self, mock_logger, mock_seer_request @@ -1975,7 +1940,7 @@ def test_update_alert_rule_anomaly_detection_seer_timeout_max_retry( mock_logger.reset_mock() mock_seer_request.side_effect = MaxRetryError( - seer_anomaly_detection_connection_pool, SEER_ANOMALY_DETECTION_STORE_DATA_URL + SEER_ANOMALY_DETECTION_CONNECTION_POOL, SEER_ANOMALY_DETECTION_STORE_DATA_URL ) with pytest.raises(TimeoutError): # attempt to update query @@ -1993,15 +1958,13 @@ def test_update_alert_rule_anomaly_detection_seer_timeout_max_retry( @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") @patch("sentry.seer.anomaly_detection.store_data.logger") def test_update_alert_rule_static_to_anomaly_detection_seer_timeout( self, mock_logger, mock_seer_request ): mock_seer_request.side_effect = MaxRetryError( - seer_anomaly_detection_connection_pool, SEER_ANOMALY_DETECTION_STORE_DATA_URL + SEER_ANOMALY_DETECTION_CONNECTION_POOL, SEER_ANOMALY_DETECTION_STORE_DATA_URL ) static_rule = self.create_alert_rule(time_window=30) with pytest.raises(TimeoutError): @@ -2017,18 +1980,10 @@ def test_update_alert_rule_static_to_anomaly_detection_seer_timeout( @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.delete_rule.seer_anomaly_detection_connection_pool.urlopen" - ) - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) - def test_update_alert_rule_dynamic_to_static_delete_call( - self, mock_store_request, mock_delete_request - ): + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") + def test_update_alert_rule_dynamic_to_static_delete_call(self, mock_seer_request): seer_return_value = {"success": True} - mock_store_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) - mock_delete_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) + mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) alert_rule = self.create_alert_rule( sensitivity=AlertRuleSensitivity.HIGH, @@ -2039,11 +1994,9 @@ def test_update_alert_rule_dynamic_to_static_delete_call( update_alert_rule(alert_rule, detection_type=AlertRuleDetectionType.STATIC) - assert mock_delete_request.call_count == 1 + assert mock_seer_request.call_count == 2 # 1 for update, 1 for delete - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_alert_rule_anomaly_detection_no_feature(self, mock_seer_request): static_rule = self.create_alert_rule(time_window=30) @@ -2061,9 +2014,7 @@ def test_update_alert_rule_anomaly_detection_no_feature(self, mock_seer_request) @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_update_invalid_time_window(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -2113,9 +2064,7 @@ def alert_rule(self): return self.create_alert_rule() @cached_property - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def dynamic_alert_rule(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -2162,9 +2111,7 @@ def test_on_demand_metric_alert(self, mocked_schedule_update_project_config): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.delete_rule.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_delete_anomaly_detection_rule(self, mock_seer_request): alert_rule = self.dynamic_alert_rule alert_rule_id = alert_rule.id @@ -2187,9 +2134,7 @@ def test_delete_anomaly_detection_rule(self, mock_seer_request): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.delete_rule.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") @patch("sentry.seer.anomaly_detection.delete_rule.logger") @patch("sentry.incidents.models.alert_rule.logger") def test_delete_anomaly_detection_rule_timeout( @@ -2221,9 +2166,7 @@ def test_delete_anomaly_detection_rule_timeout( @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.delete_rule.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") @patch("sentry.seer.anomaly_detection.delete_rule.logger") @patch("sentry.incidents.models.alert_rule.logger") def test_delete_anomaly_detection_rule_error( @@ -2255,9 +2198,7 @@ def test_delete_anomaly_detection_rule_error( @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.delete_rule.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") @patch("sentry.seer.anomaly_detection.delete_rule.logger") @patch("sentry.incidents.models.alert_rule.logger") def test_delete_anomaly_detection_rule_attribute_error( @@ -2289,9 +2230,7 @@ def test_delete_anomaly_detection_rule_attribute_error( @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.delete_rule.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") @patch("sentry.seer.anomaly_detection.delete_rule.logger") @patch("sentry.incidents.models.alert_rule.logger") def test_delete_anomaly_detection_rule_failure( @@ -2412,9 +2351,7 @@ def test_existing_label(self): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_invalid_threshold_dynamic_alert(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200) @@ -2485,9 +2422,7 @@ def test_excluded_projects_not_associated_with_rule(self): @with_feature("organizations:anomaly-detection-alerts") @with_feature("organizations:anomaly-detection-rollout") - @patch( - "sentry.seer.anomaly_detection.store_data.seer_anomaly_detection_connection_pool.urlopen" - ) + @patch("sentry.seer.anomaly_detection.utils.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen") def test_invalid_threshold_dynamic_alert(self, mock_seer_request): seer_return_value: StoreDataResponse = {"success": True} mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200)