From f336c6b1fa426be70ec26c4f073d39e2154011a6 Mon Sep 17 00:00:00 2001 From: Fabian Schindler Date: Fri, 6 Dec 2024 11:02:00 +0100 Subject: [PATCH] fix(dynamic-sampling): enusre that at leas one project has count (#81727) Make sure that at least one project with counts is present before doing a Project Rebalancing run Closes https://github.com/getsentry/sentry/issues/81556 --- .../tasks/boost_low_volume_projects.py | 4 ++++ .../tasks/test_boost_low_volume_projects.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/sentry/dynamic_sampling/tasks/boost_low_volume_projects.py b/src/sentry/dynamic_sampling/tasks/boost_low_volume_projects.py index ab6a4c5c060466..a1f5115f57cc8c 100644 --- a/src/sentry/dynamic_sampling/tasks/boost_low_volume_projects.py +++ b/src/sentry/dynamic_sampling/tasks/boost_low_volume_projects.py @@ -401,6 +401,10 @@ def adjust_sample_rates_of_projects( projects_with_counts = { project_id: count_per_root for project_id, count_per_root, _, _ in projects_with_tx_count } + # The rebalancing will not work (or would make sense) when we have only projects with zero-counts. + if not any(projects_with_counts.values()): + return + # Since we don't mind about strong consistency, we query a replica of the main database with the possibility of # having out of date information. This is a trade-off we accept, since we work under the assumption that eventually # the projects of an org will be replicated consistently across replicas, because no org should continue to create diff --git a/tests/sentry/dynamic_sampling/tasks/test_boost_low_volume_projects.py b/tests/sentry/dynamic_sampling/tasks/test_boost_low_volume_projects.py index 58526a076e5a6c..2453ba9a97b72c 100644 --- a/tests/sentry/dynamic_sampling/tasks/test_boost_low_volume_projects.py +++ b/tests/sentry/dynamic_sampling/tasks/test_boost_low_volume_projects.py @@ -1,5 +1,6 @@ from datetime import timedelta from typing import cast +from unittest.mock import patch from django.utils import timezone @@ -183,6 +184,22 @@ def test_project_mode_sampling_with_query(self): assert get_guarded_project_sample_rate(org1, p1) == 0.2 + @with_feature(["organizations:dynamic-sampling", "organizations:dynamic-sampling-custom"]) + def test_project_mode_sampling_with_query_zero_metrics(self): + organization = self.create_organization("test-org") + project = self.create_project(organization=organization) + + organization.update_option("sentry:sampling_mode", DynamicSamplingMode.PROJECT) + project.update_option("sentry:target_sample_rate", 0.2) + + # make sure that no rebalancing is actually run + with patch( + "sentry.dynamic_sampling.models.projects_rebalancing.ProjectsRebalancingModel._run" + ) as mock_run: + with self.tasks(): + boost_low_volume_projects.delay() + assert not mock_run.called + def test_complex(self): context = TaskContext("rebalancing", 20) org1 = self.create_organization("test-org1")