Skip to content

Commit 6bf5126

Browse files
committed
fix(uptime): Don't consume a seat or create audit log when onboarding an auto detected monitor
Users don't see onboarding monitors, and so they shouldn't consume a quota seat or create an audit log. This pr moves this to the point where the monitor graduates from onboarding.
1 parent 712d8c7 commit 6bf5126

File tree

4 files changed

+64
-31
lines changed

4 files changed

+64
-31
lines changed

src/sentry/uptime/detectors/result_handler.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
CheckResult,
1010
)
1111

12+
from sentry import audit_log
1213
from sentry.uptime.detectors.ranking import _get_cluster
1314
from sentry.uptime.detectors.tasks import set_failed_url
1415
from sentry.uptime.models import UptimeSubscription, get_project_subscription
@@ -18,6 +19,7 @@
1819
)
1920
from sentry.uptime.types import ProjectUptimeSubscriptionMode
2021
from sentry.utils import metrics
22+
from sentry.utils.audit import create_system_audit_entry
2123
from sentry.workflow_engine.models.detector import Detector
2224

2325
logger = logging.getLogger(__name__)
@@ -90,6 +92,13 @@ def handle_onboarding_result(
9092
interval_seconds=int(AUTO_DETECTED_ACTIVE_SUBSCRIPTION_INTERVAL.total_seconds()),
9193
mode=ProjectUptimeSubscriptionMode.AUTO_DETECTED_ACTIVE,
9294
)
95+
create_system_audit_entry(
96+
organization=detector.project.organization,
97+
target_object=project_subscription.id,
98+
event=audit_log.get_event_id("UPTIME_MONITOR_ADD"),
99+
data=project_subscription.get_audit_log_data(),
100+
)
101+
93102
metrics.incr(
94103
"uptime.result_processor.autodetection.graduated_onboarding",
95104
sample_rate=1.0,

src/sentry/uptime/detectors/tasks.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from dateutil.parser import parse as parse_datetime
88
from django.utils import timezone
99

10-
from sentry import audit_log, features
10+
from sentry import features
1111
from sentry.locks import locks
1212
from sentry.models.organization import Organization
1313
from sentry.models.project import Project
@@ -34,7 +34,6 @@
3434
)
3535
from sentry.uptime.types import ProjectUptimeSubscriptionMode
3636
from sentry.utils import metrics
37-
from sentry.utils.audit import create_system_audit_entry
3837
from sentry.utils.hashlib import md5_text
3938
from sentry.utils.locking import UnableToAcquireLock
4039

@@ -240,16 +239,10 @@ def process_candidate_url(
240239
"organizations:uptime-automatic-subscription-creation", project.organization
241240
) and features.has("organizations:uptime", project.organization):
242241
# If we hit this point, then the url looks worth monitoring. Create an uptime subscription in monitor mode.
243-
uptime_monitor = monitor_url_for_project(project, url)
242+
monitor_url_for_project(project, url)
244243
# Disable auto-detection on this project and organization now that we've successfully found a hostname
245244
project.update_option("sentry:uptime_autodetection", False)
246245
project.organization.update_option("sentry:uptime_autodetection", False)
247-
create_system_audit_entry(
248-
organization=project.organization,
249-
target_object=uptime_monitor.id,
250-
event=audit_log.get_event_id("UPTIME_MONITOR_ADD"),
251-
data=uptime_monitor.get_audit_log_data(),
252-
)
253246

254247
metrics.incr("uptime.detectors.candidate_url.succeeded", sample_rate=1.0)
255248
return True

src/sentry/uptime/subscriptions/subscriptions.py

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -244,20 +244,22 @@ def create_project_uptime_subscription(
244244
)
245245
detector = create_detector_from_project_subscription(uptime_monitor)
246246

247-
# Update status. This may have the side effect of removing or creating a
248-
# remote subscription. When a new monitor is created we will ensure seat
249-
# assignment, which may cause the monitor to be disabled if there are no
250-
# available seat assignments.
251-
match status:
252-
case ObjectStatus.ACTIVE:
253-
try:
254-
enable_uptime_detector(detector, ensure_assignment=True)
255-
except UptimeMonitorNoSeatAvailable:
256-
# No need to do anything if we failed to handle seat
257-
# assignment. The monitor will be created, but not enabled
258-
pass
259-
case ObjectStatus.DISABLED:
260-
disable_uptime_detector(detector)
247+
# Don't consume a seat if we're still in onboarding mode
248+
if mode != ProjectUptimeSubscriptionMode.AUTO_DETECTED_ONBOARDING:
249+
# Update status. This may have the side effect of removing or creating a
250+
# remote subscription. When a new monitor is created we will ensure seat
251+
# assignment, which may cause the monitor to be disabled if there are no
252+
# available seat assignments.
253+
match status:
254+
case ObjectStatus.ACTIVE:
255+
try:
256+
enable_uptime_detector(detector, ensure_assignment=True)
257+
except UptimeMonitorNoSeatAvailable:
258+
# No need to do anything if we failed to handle seat
259+
# assignment. The monitor will be created, but not enabled
260+
pass
261+
case ObjectStatus.DISABLED:
262+
disable_uptime_detector(detector)
261263

262264
# ProjectUptimeSubscription may have been updated as part of
263265
# {enable,disable}_uptime_detector
@@ -333,14 +335,16 @@ def update_project_uptime_subscription(
333335
},
334336
)
335337

336-
# Update status. This may have the side effect of removing or creating a
337-
# remote subscription. Will raise a UptimeMonitorNoSeatAvailable if seat
338-
# assignment fails.
339-
match status:
340-
case ObjectStatus.DISABLED:
341-
disable_uptime_detector(detector)
342-
case ObjectStatus.ACTIVE:
343-
enable_uptime_detector(detector)
338+
# Don't consume a seat if we're still in onboarding mode
339+
if mode != ProjectUptimeSubscriptionMode.AUTO_DETECTED_ONBOARDING:
340+
# Update status. This may have the side effect of removing or creating a
341+
# remote subscription. Will raise a UptimeMonitorNoSeatAvailable if seat
342+
# assignment fails.
343+
match status:
344+
case ObjectStatus.DISABLED:
345+
disable_uptime_detector(detector)
346+
case ObjectStatus.ACTIVE:
347+
enable_uptime_detector(detector)
344348

345349
# ProjectUptimeSubscription may have been updated as part of
346350
# {enable,disable}_uptime_detector

tests/sentry/uptime/subscriptions/test_subscriptions.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,19 @@ def test_status_disable(self, mock_disable_uptime_detector):
361361
)
362362
mock_disable_uptime_detector.assert_called()
363363

364+
@mock.patch("sentry.uptime.subscriptions.subscriptions.disable_uptime_detector")
365+
def test_status_disable_not_called_onboarding(self, mock_disable_uptime_detector):
366+
create_project_uptime_subscription(
367+
self.project,
368+
self.environment,
369+
url="https://sentry.io",
370+
interval_seconds=3600,
371+
timeout_ms=1000,
372+
mode=ProjectUptimeSubscriptionMode.AUTO_DETECTED_ONBOARDING,
373+
status=ObjectStatus.DISABLED,
374+
)
375+
mock_disable_uptime_detector.assert_not_called()
376+
364377
@mock.patch("sentry.uptime.subscriptions.subscriptions.enable_uptime_detector")
365378
def test_status_enable(self, mock_enable_uptime_detector):
366379
with self.tasks():
@@ -377,6 +390,20 @@ def test_status_enable(self, mock_enable_uptime_detector):
377390
assert detector
378391
mock_enable_uptime_detector.assert_called_with(detector, ensure_assignment=True)
379392

393+
@mock.patch("sentry.uptime.subscriptions.subscriptions.enable_uptime_detector")
394+
def test_status_enable_not_called_onboarding(self, mock_enable_uptime_detector):
395+
with self.tasks():
396+
create_project_uptime_subscription(
397+
self.project,
398+
self.environment,
399+
url="https://sentry.io",
400+
interval_seconds=3600,
401+
timeout_ms=1000,
402+
mode=ProjectUptimeSubscriptionMode.AUTO_DETECTED_ONBOARDING,
403+
status=ObjectStatus.ACTIVE,
404+
)
405+
mock_enable_uptime_detector.assert_not_called()
406+
380407
@mock.patch(
381408
"sentry.quotas.backend.check_assign_seat",
382409
return_value=SeatAssignmentResult(assignable=False, reason="Testing"),

0 commit comments

Comments
 (0)