Skip to content

Commit 0cd96b5

Browse files
author
David Wang
authored
feat(crons): Add cron monitor created metric (#58017)
Modify the first_monitor_created metric to also record whenever a monitor is created. Fixes: https://github.com/getsentry/team-crons/issues/95
1 parent a0b928d commit 0cd96b5

File tree

9 files changed

+51
-13
lines changed

9 files changed

+51
-13
lines changed

src/sentry/analytics/events/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
from .codeowners_created import * # noqa: F401,F403
1010
from .codeowners_updated import * # noqa: F401,F403
1111
from .comment_webhooks import * # noqa: F401,F403
12+
from .cron_monitor_created import * # noqa: F401,F403
1213
from .eventuser_endpoint_request import * # noqa: F401,F403
1314
from .first_cron_checkin_sent import * # noqa: F401,F403
14-
from .first_cron_monitor_created import * # noqa: F401,F403
1515
from .first_event_sent import * # noqa: F401,F403
1616
from .first_profile_sent import * # noqa: F401,F403
1717
from .first_release_tag_sent import * # noqa: F401,F403
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
from sentry import analytics
22

33

4-
class FirstCronMonitorCreated(analytics.Event):
5-
type = "first_cron_monitor.created"
6-
4+
class CronMonitorEvent(analytics.Event):
75
attributes = (
86
analytics.Attribute("organization_id"),
97
analytics.Attribute("project_id"),
@@ -12,4 +10,13 @@ class FirstCronMonitorCreated(analytics.Event):
1210
)
1311

1412

13+
class CronMonitorCreated(CronMonitorEvent):
14+
type = "cron_monitor.created"
15+
16+
17+
class FirstCronMonitorCreated(CronMonitorEvent):
18+
type = "first_cron_monitor.created"
19+
20+
1521
analytics.register(FirstCronMonitorCreated)
22+
analytics.register(CronMonitorCreated)

src/sentry/monitors/consumers/monitor_consumer.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
get_new_timeout_at,
4141
get_timeout_at,
4242
signal_first_checkin,
43-
signal_first_monitor_created,
43+
signal_monitor_created,
4444
valid_duration,
4545
)
4646
from sentry.monitors.validators import ConfigValidator, MonitorCheckInValidator
@@ -107,7 +107,7 @@ def _ensure_monitor_with_config(
107107
"config": validated_config,
108108
},
109109
)
110-
signal_first_monitor_created(project, None, True)
110+
signal_monitor_created(project, None, True)
111111

112112
# Update existing monitor
113113
if monitor and not created and monitor.config != validated_config:

src/sentry/monitors/endpoints/monitor_ingest_checkin_index.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
MonitorLimitsExceeded,
3131
)
3232
from sentry.monitors.serializers import MonitorCheckInSerializer
33-
from sentry.monitors.utils import get_timeout_at, signal_first_checkin, signal_first_monitor_created
33+
from sentry.monitors.utils import get_timeout_at, signal_first_checkin, signal_monitor_created
3434
from sentry.monitors.validators import MonitorCheckInValidator
3535
from sentry.ratelimits.config import RateLimitConfig
3636
from sentry.types.ratelimit import RateLimit, RateLimitCategory
@@ -163,7 +163,7 @@ def post(
163163
)
164164

165165
if created:
166-
signal_first_monitor_created(project, request.user, True)
166+
signal_monitor_created(project, request.user, True)
167167
except MonitorLimitsExceeded as e:
168168
return self.respond({type(e).__name__: str(e)}, status=400)
169169

src/sentry/monitors/endpoints/organization_monitor_index.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
MonitorType,
3131
)
3232
from sentry.monitors.serializers import MonitorSerializer, MonitorSerializerResponse
33-
from sentry.monitors.utils import create_alert_rule, signal_first_monitor_created
33+
from sentry.monitors.utils import create_alert_rule, signal_monitor_created
3434
from sentry.monitors.validators import MonitorValidator
3535
from sentry.search.utils import tokenize_query
3636

@@ -227,7 +227,7 @@ def post(self, request: Request, organization) -> Response:
227227
)
228228

229229
project = result["project"]
230-
signal_first_monitor_created(project, request.user, False)
230+
signal_monitor_created(project, request.user, False)
231231

232232
validated_alert_rule = result.get("alert_rule")
233233
if validated_alert_rule:

src/sentry/monitors/utils.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414
from sentry.models.project import Project
1515
from sentry.models.rule import Rule, RuleActivity, RuleActivityType, RuleSource
1616
from sentry.models.user import User
17-
from sentry.signals import first_cron_checkin_received, first_cron_monitor_created
17+
from sentry.signals import (
18+
cron_monitor_created,
19+
first_cron_checkin_received,
20+
first_cron_monitor_created,
21+
)
1822

1923
from .constants import MAX_TIMEOUT, TIMEOUT
2024
from .models import CheckInStatus, Monitor, MonitorCheckIn
@@ -23,7 +27,7 @@
2327
def signal_first_checkin(project: Project, monitor: Monitor):
2428
if not project.flags.has_cron_checkins:
2529
# Backfill users that already have cron monitors
26-
signal_first_monitor_created(project, None, False)
30+
check_and_signal_first_monitor_created(project, None, False)
2731
transaction.on_commit(
2832
lambda: first_cron_checkin_received.send_robust(
2933
project=project, monitor_id=str(monitor.guid), sender=Project
@@ -32,13 +36,20 @@ def signal_first_checkin(project: Project, monitor: Monitor):
3236
)
3337

3438

35-
def signal_first_monitor_created(project: Project, user, from_upsert: bool):
39+
def check_and_signal_first_monitor_created(project: Project, user, from_upsert: bool):
3640
if not project.flags.has_cron_monitors:
3741
first_cron_monitor_created.send_robust(
3842
project=project, user=user, from_upsert=from_upsert, sender=Project
3943
)
4044

4145

46+
def signal_monitor_created(project: Project, user, from_upsert: bool):
47+
cron_monitor_created.send_robust(
48+
project=project, user=user, from_upsert=from_upsert, sender=Project
49+
)
50+
check_and_signal_first_monitor_created(project, user, from_upsert)
51+
52+
4253
# Generates a timeout_at value for new check-ins
4354
def get_timeout_at(
4455
monitor_config: dict, status: CheckInStatus, date_added: Optional[datetime]

src/sentry/receivers/onboarding.py

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from sentry.services.hybrid_cloud.user import RpcUser
2222
from sentry.signals import (
2323
alert_rule_created,
24+
cron_monitor_created,
2425
event_processed,
2526
first_cron_checkin_received,
2627
first_cron_monitor_created,
@@ -267,6 +268,17 @@ def record_first_cron_monitor(project, user, from_upsert, **kwargs):
267268
)
268269

269270

271+
@cron_monitor_created.connect(weak=False)
272+
def record_cron_monitor_created(project, user, from_upsert, **kwargs):
273+
analytics.record(
274+
"cron_monitor.created",
275+
user_id=user.id if user else project.organization.default_owner_id,
276+
organization_id=project.organization_id,
277+
project_id=project.id,
278+
from_upsert=from_upsert,
279+
)
280+
281+
270282
@first_cron_checkin_received.connect(weak=False)
271283
def record_first_cron_checkin(project, monitor_id, **kwargs):
272284
project.update(flags=F("flags").bitor(Project.flags.has_cron_checkins))

src/sentry/signals.py

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ def send_robust(self, sender, **named) -> List[Tuple[Receiver, Union[Exception,
132132
first_profile_received = BetterSignal() # ["project"]
133133
first_replay_received = BetterSignal() # ["project"]
134134
first_cron_monitor_created = BetterSignal() # ["project", "user", "from_upsert"]
135+
cron_monitor_created = BetterSignal() # ["project", "user", "from_upsert"]
135136
first_cron_checkin_received = BetterSignal() # ["project", "monitor_id"]
136137
member_invited = BetterSignal() # ["member", "user"]
137138
member_joined = BetterSignal() # ["organization_member_id", "organization_id", "user_id"]

tests/sentry/monitors/endpoints/test_organization_monitor_index.py

+7
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ def test_simple(self, mock_record):
192192
self.project.refresh_from_db()
193193
assert self.project.flags.has_cron_monitors
194194

195+
mock_record.assert_any_call(
196+
"cron_monitor.created",
197+
user_id=self.user.id,
198+
organization_id=self.organization.id,
199+
project_id=self.project.id,
200+
from_upsert=False,
201+
)
195202
mock_record.assert_called_with(
196203
"first_cron_monitor.created",
197204
user_id=self.user.id,

0 commit comments

Comments
 (0)