Skip to content

Commit 61b42e4

Browse files
thetruecpaulmchen-sentry
authored andcommitted
feat(rollouts): Add comparator with timings (#109104)
It would be helpful if we had timing data on control / experimental branches. This PR adds that capability to the SafeRolloutComparator class. This is also logged into DataDog so the information can be included in the consistent dashboard.
1 parent d5ddcfd commit 61b42e4

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/sentry/utils/rollout.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,55 @@ def check_and_choose(
216216

217217
# Part 2: determine what to return
218218
return experimental_data if use_experimental else control_data
219+
220+
@classmethod
221+
def check_and_choose_with_timings(
222+
cls,
223+
control_thunk: Callable[[], TData],
224+
experimental_thunk: Callable[[], TData],
225+
callsite: str,
226+
null_result_determiner: Callable[[TData], bool] | None = None,
227+
reasonable_match_comparator: Callable[[TData, TData], bool] | None = None,
228+
) -> TData:
229+
"""
230+
This method is essentially the same as check_and_choose, but captures timing
231+
information around the control/experimental branches.
232+
233+
This information is captured with Sentry spans, not in Datadog.
234+
"""
235+
if not cls.should_check_experiment(callsite):
236+
# Don't bother collecting data in the case where we're only evaluating the
237+
# control branch.
238+
return control_thunk()
239+
240+
with metrics.timer(
241+
"SafeRolloutComparator.check_and_choose_with_timings",
242+
tags={
243+
"rollout_name": cls.ROLLOUT_NAME,
244+
"callsite": callsite,
245+
"branch": "control",
246+
},
247+
):
248+
control_data = control_thunk()
249+
250+
with metrics.timer(
251+
"SafeRolloutComparator.check_and_choose_with_timings",
252+
tags={
253+
"rollout_name": cls.ROLLOUT_NAME,
254+
"callsite": callsite,
255+
"branch": "experimental",
256+
},
257+
):
258+
experimental_data = experimental_thunk()
259+
260+
is_experimental_data_a_null_result = None
261+
if null_result_determiner is not None:
262+
is_experimental_data_a_null_result = null_result_determiner(experimental_data)
263+
264+
return cls.check_and_choose(
265+
control_data,
266+
experimental_data,
267+
callsite,
268+
is_experimental_data_a_null_result,
269+
reasonable_match_comparator,
270+
)

0 commit comments

Comments
 (0)