Skip to content

Commit b85cd10

Browse files
feat(crons): Allow to upsert monitors (#2929)
Co-authored-by: Daniel Szoke <[email protected]>
1 parent 336f7d5 commit b85cd10

File tree

3 files changed

+85
-12
lines changed

3 files changed

+85
-12
lines changed

sentry_sdk/crons/decorator.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from sentry_sdk.utils import now
66

77
if TYPE_CHECKING:
8-
from typing import Optional, Type
8+
from typing import Any, Optional, Type
99
from types import TracebackType
1010

1111
if PY2:
@@ -47,15 +47,18 @@ def test(arg):
4747
```
4848
"""
4949

50-
def __init__(self, monitor_slug=None):
51-
# type: (Optional[str]) -> None
50+
def __init__(self, monitor_slug=None, monitor_config=None):
51+
# type: (Optional[str], Optional[dict[str, Any]]) -> None
5252
self.monitor_slug = monitor_slug
53+
self.monitor_config = monitor_config
5354

5455
def __enter__(self):
5556
# type: () -> None
5657
self.start_timestamp = now()
5758
self.check_in_id = capture_checkin(
58-
monitor_slug=self.monitor_slug, status=MonitorStatus.IN_PROGRESS
59+
monitor_slug=self.monitor_slug,
60+
status=MonitorStatus.IN_PROGRESS,
61+
monitor_config=self.monitor_config,
5962
)
6063

6164
def __exit__(self, exc_type, exc_value, traceback):
@@ -72,4 +75,5 @@ def __exit__(self, exc_type, exc_value, traceback):
7275
check_in_id=self.check_in_id,
7376
status=status,
7477
duration=duration_s,
78+
monitor_config=self.monitor_config,
7579
)

tests/crons/test_crons.py

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ def _break_world_contextmanager(name):
3333
return "Hello, {}".format(name)
3434

3535

36+
@sentry_sdk.monitor(monitor_slug="ghi789", monitor_config=None)
37+
def _no_monitor_config():
38+
return
39+
40+
41+
@sentry_sdk.monitor(
42+
monitor_slug="ghi789",
43+
monitor_config={
44+
"schedule": {"type": "crontab", "value": "0 0 * * *"},
45+
"failure_issue_threshold": 5,
46+
},
47+
)
48+
def _with_monitor_config():
49+
return
50+
51+
3652
def test_decorator(sentry_init):
3753
sentry_init()
3854

@@ -45,7 +61,9 @@ def test_decorator(sentry_init):
4561
# Check for initial checkin
4662
fake_capture_checkin.assert_has_calls(
4763
[
48-
mock.call(monitor_slug="abc123", status="in_progress"),
64+
mock.call(
65+
monitor_slug="abc123", status="in_progress", monitor_config=None
66+
),
4967
]
5068
)
5169

@@ -70,7 +88,9 @@ def test_decorator_error(sentry_init):
7088
# Check for initial checkin
7189
fake_capture_checkin.assert_has_calls(
7290
[
73-
mock.call(monitor_slug="def456", status="in_progress"),
91+
mock.call(
92+
monitor_slug="def456", status="in_progress", monitor_config=None
93+
),
7494
]
7595
)
7696

@@ -93,7 +113,9 @@ def test_contextmanager(sentry_init):
93113
# Check for initial checkin
94114
fake_capture_checkin.assert_has_calls(
95115
[
96-
mock.call(monitor_slug="abc123", status="in_progress"),
116+
mock.call(
117+
monitor_slug="abc123", status="in_progress", monitor_config=None
118+
),
97119
]
98120
)
99121

@@ -118,7 +140,9 @@ def test_contextmanager_error(sentry_init):
118140
# Check for initial checkin
119141
fake_capture_checkin.assert_has_calls(
120142
[
121-
mock.call(monitor_slug="def456", status="in_progress"),
143+
mock.call(
144+
monitor_slug="def456", status="in_progress", monitor_config=None
145+
),
122146
]
123147
)
124148

@@ -194,6 +218,8 @@ def test_monitor_config(sentry_init, capture_envelopes):
194218

195219
monitor_config = {
196220
"schedule": {"type": "crontab", "value": "0 0 * * *"},
221+
"failure_issue_threshold": 5,
222+
"recovery_threshold": 5,
197223
}
198224

199225
capture_checkin(monitor_slug="abc123", monitor_config=monitor_config)
@@ -211,6 +237,41 @@ def test_monitor_config(sentry_init, capture_envelopes):
211237
assert "monitor_config" not in check_in
212238

213239

240+
def test_decorator_monitor_config(sentry_init, capture_envelopes):
241+
sentry_init()
242+
envelopes = capture_envelopes()
243+
244+
_with_monitor_config()
245+
246+
assert len(envelopes) == 2
247+
248+
for check_in_envelope in envelopes:
249+
assert len(check_in_envelope.items) == 1
250+
check_in = check_in_envelope.items[0].payload.json
251+
252+
assert check_in["monitor_slug"] == "ghi789"
253+
assert check_in["monitor_config"] == {
254+
"schedule": {"type": "crontab", "value": "0 0 * * *"},
255+
"failure_issue_threshold": 5,
256+
}
257+
258+
259+
def test_decorator_no_monitor_config(sentry_init, capture_envelopes):
260+
sentry_init()
261+
envelopes = capture_envelopes()
262+
263+
_no_monitor_config()
264+
265+
assert len(envelopes) == 2
266+
267+
for check_in_envelope in envelopes:
268+
assert len(check_in_envelope.items) == 1
269+
check_in = check_in_envelope.items[0].payload.json
270+
271+
assert check_in["monitor_slug"] == "ghi789"
272+
assert "monitor_config" not in check_in
273+
274+
214275
def test_capture_checkin_sdk_not_initialized():
215276
# Tests that the capture_checkin does not raise an error when Sentry SDK is not initialized.
216277
# sentry_init() is intentionally omitted.

tests/crons/test_crons_async_py3.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ async def test_decorator(sentry_init):
4949
# Check for initial checkin
5050
fake_capture_checkin.assert_has_calls(
5151
[
52-
mock.call(monitor_slug="abc123", status="in_progress"),
52+
mock.call(
53+
monitor_slug="abc123", status="in_progress", monitor_config=None
54+
),
5355
]
5456
)
5557

@@ -75,7 +77,9 @@ async def test_decorator_error(sentry_init):
7577
# Check for initial checkin
7678
fake_capture_checkin.assert_has_calls(
7779
[
78-
mock.call(monitor_slug="def456", status="in_progress"),
80+
mock.call(
81+
monitor_slug="def456", status="in_progress", monitor_config=None
82+
),
7983
]
8084
)
8185

@@ -99,7 +103,9 @@ async def test_contextmanager(sentry_init):
99103
# Check for initial checkin
100104
fake_capture_checkin.assert_has_calls(
101105
[
102-
mock.call(monitor_slug="abc123", status="in_progress"),
106+
mock.call(
107+
monitor_slug="abc123", status="in_progress", monitor_config=None
108+
),
103109
]
104110
)
105111

@@ -125,7 +131,9 @@ async def test_contextmanager_error(sentry_init):
125131
# Check for initial checkin
126132
fake_capture_checkin.assert_has_calls(
127133
[
128-
mock.call(monitor_slug="def456", status="in_progress"),
134+
mock.call(
135+
monitor_slug="def456", status="in_progress", monitor_config=None
136+
),
129137
]
130138
)
131139

0 commit comments

Comments
 (0)