Skip to content

Commit 547c13a

Browse files
getsentry-botk-fish
andcommitted
Revert "ref(metrics-extraction): Reduce cold cache peak w/ rolling cache (#68727)"
This reverts commit 489a1d0. Co-authored-by: k-fish <6111995+k-fish@users.noreply.github.com>
1 parent 7e2cea7 commit 547c13a

File tree

3 files changed

+30
-54
lines changed

3 files changed

+30
-54
lines changed

src/sentry/relay/config/metric_extraction.py

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from sentry.search.events.types import ParamsType, QueryBuilderConfig
3636
from sentry.snuba.dataset import Dataset
3737
from sentry.snuba.metrics.extraction import (
38-
WIDGET_QUERY_CACHE_MAX_CHUNKS,
3938
MetricSpec,
4039
MetricSpecType,
4140
OnDemandMetricSpec,
@@ -205,39 +204,20 @@ def _get_alert_metric_specs(
205204
return specs
206205

207206

208-
def _bulk_cache_query_key(project: Project, chunk: int) -> str:
209-
return f"on-demand.bulk-query-cache.{chunk}.{project.organization.id}"
207+
def _bulk_cache_query_key(project: Project) -> str:
208+
return f"on-demand.bulk-query-cache.{project.organization.id}"
210209

211210

212-
def _get_bulk_cached_query(project: Project) -> tuple[dict[int, dict[str, bool]], list[int]]:
213-
cache_result = {}
214-
cold_cache_chunks = []
215-
for i in range(WIDGET_QUERY_CACHE_MAX_CHUNKS):
216-
query_bulk_cache_key = _bulk_cache_query_key(project, i)
217-
chunk_result = cache.get(query_bulk_cache_key, None)
218-
if chunk_result is None:
219-
cold_cache_chunks.append(i)
220-
sentry_sdk.set_tag(f"on_demand_metrics.query_cache.{i}", chunk_result is None)
221-
cache_result[i] = chunk_result or {}
222-
sentry_sdk.set_extra("cold_cache_chunks", cold_cache_chunks)
223-
metrics.incr("on_demand_metrics.query_cache_cold_keys", amount=len(cold_cache_chunks))
224-
return cache_result, cold_cache_chunks
211+
def _get_bulk_cached_query(project: Project) -> dict[str, Any]:
212+
query_bulk_cache_key = _bulk_cache_query_key(project)
213+
cache_result = cache.get(query_bulk_cache_key, None)
214+
sentry_sdk.set_tag("on_demand_metrics.query_cache", cache_result is None)
215+
return cache_result
225216

226217

227-
def _set_bulk_cached_query_chunk(
228-
project: Project, chunk_cache: dict[str, bool], chunk: int
229-
) -> None:
230-
query_bulk_cache_key = _bulk_cache_query_key(project, chunk)
231-
cache.set(
232-
query_bulk_cache_key, chunk_cache, timeout=900 + (137 * chunk)
233-
) # Add prime number jitter per cache. All cache turns over between 15-25 mins
234-
235-
236-
def _set_bulk_cached_query(
237-
project: Project, query_cache: dict[int, dict[str, bool]], cold_cache_chunks: list[int]
238-
) -> None:
239-
for i in cold_cache_chunks:
240-
_set_bulk_cached_query_chunk(project, query_cache[i], i)
218+
def _set_bulk_cached_query(project: Project, query_cache: dict[str, Any]) -> None:
219+
query_bulk_cache_key = _bulk_cache_query_key(project)
220+
cache.set(query_bulk_cache_key, query_cache, timeout=5400)
241221

242222

243223
@metrics.wraps("on_demand_metrics._get_widget_metric_specs")
@@ -267,7 +247,9 @@ def _get_widget_metric_specs(
267247
"on_demand_metrics.widgets_to_process", amount=len(widget_queries), sample_rate=1.0
268248
)
269249

270-
organization_bulk_query_cache, cold_bulk_cache_chunks = _get_bulk_cached_query(project)
250+
organization_bulk_query_cache = _get_bulk_cached_query(project)
251+
save_organization_bulk_cache = not bool(organization_bulk_query_cache)
252+
organization_bulk_query_cache = {}
271253

272254
ignored_widget_ids: dict[int, bool] = {}
273255
specs_for_widget: dict[int, list[HashedMetricSpec]] = defaultdict(list)
@@ -327,7 +309,8 @@ def _get_widget_metric_specs(
327309
_update_state_with_spec_limit(trimmed_specs, widget_query_for_spec_hash)
328310
metrics.incr("on_demand_metrics.widget_query_specs", amount=len(specs))
329311
if in_random_rollout("on_demand_metrics.cache_should_use_on_demand"):
330-
_set_bulk_cached_query(project, organization_bulk_query_cache, cold_bulk_cache_chunks)
312+
if save_organization_bulk_cache:
313+
_set_bulk_cached_query(project, organization_bulk_query_cache)
331314
return specs
332315

333316

@@ -456,7 +439,7 @@ def convert_widget_query_to_metric(
456439
project: Project,
457440
widget_query: DashboardWidgetQuery,
458441
prefilling: bool,
459-
organization_bulk_query_cache: dict[int, dict[str, bool]] | None = None,
442+
organization_bulk_query_cache: dict[str, Any] | None = None,
460443
) -> list[HashedMetricSpec]:
461444
"""
462445
Converts a passed metrics widget query to one or more MetricSpecs.
@@ -484,7 +467,7 @@ def _generate_metric_specs(
484467
project: Project,
485468
prefilling: bool,
486469
groupbys: Sequence[str] | None = None,
487-
organization_bulk_query_cache: dict[int, dict[str, bool]] | None = None,
470+
organization_bulk_query_cache: dict[str, Any] | None = None,
488471
) -> list[HashedMetricSpec]:
489472
metrics_specs = []
490473
metrics.incr("on_demand_metrics.before_widget_spec_generation")
@@ -756,7 +739,7 @@ def _convert_aggregate_and_query_to_metrics(
756739
prefilling: bool,
757740
spec_type: MetricSpecType = MetricSpecType.SIMPLE_QUERY,
758741
groupbys: Sequence[str] | None = None,
759-
organization_bulk_query_cache: dict[int, dict[str, bool]] | None = None,
742+
organization_bulk_query_cache: dict[str, Any] | None = None,
760743
) -> Sequence[HashedMetricSpec] | None:
761744
"""
762745
Converts an aggregate and a query to a metric spec with its hash value.

src/sentry/snuba/metrics/extraction.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@
5959
"user_misery": SPEC_VERSION_TWO_FLAG,
6060
}
6161

62-
# Splits the bulk cache for on-demand resolution into N chunks
63-
WIDGET_QUERY_CACHE_MAX_CHUNKS = 6
64-
6562

6663
# This helps us control the different spec versions
6764
# in order to migrate customers from invalid specs
@@ -673,22 +670,18 @@ def should_use_on_demand_metrics(
673670
query: str | None,
674671
groupbys: Sequence[str] | None = None,
675672
prefilling: bool = False,
676-
organization_bulk_query_cache: dict[int, dict[str, bool]] | None = None,
673+
organization_bulk_query_cache: dict[str, Any] | None = None,
677674
) -> bool:
678675
if in_random_rollout("on_demand_metrics.cache_should_use_on_demand"):
679676
if organization_bulk_query_cache is None:
680677
organization_bulk_query_cache = {}
681678

682679
dataset_str = dataset.value if isinstance(dataset, Enum) else str(dataset or "")
683680
groupbys_str = ",".join(sorted(groupbys)) if groupbys else ""
684-
local_cache_md5 = md5_text(
681+
local_cache_key = md5_text(
685682
f"{dataset_str}-{aggregate}-{query or ''}-{groupbys_str}-prefilling={prefilling}"
686-
)
687-
local_cache_digest_chunk = local_cache_md5.digest()[0] % WIDGET_QUERY_CACHE_MAX_CHUNKS
688-
local_cache_key = local_cache_md5.hexdigest()
689-
cached_result = organization_bulk_query_cache.get(local_cache_digest_chunk, {}).get(
690-
local_cache_key, None
691-
)
683+
).hexdigest()
684+
cached_result = organization_bulk_query_cache.get(local_cache_key, None)
692685
if cached_result:
693686
metrics.incr("on_demand_metrics.should_use_on_demand_metrics.cache_hit")
694687
return cached_result
@@ -707,7 +700,7 @@ def should_use_on_demand_metrics(
707700
prefilling=prefilling,
708701
)
709702
metrics.incr("on_demand_metrics.should_use_on_demand_metrics.cache_miss")
710-
organization_bulk_query_cache[local_cache_digest_chunk][local_cache_key] = result
703+
organization_bulk_query_cache[local_cache_key] = result
711704
return result
712705

713706
return _should_use_on_demand_metrics(

tests/sentry/relay/config/test_metric_extraction.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from sentry.models.transaction_threshold import ProjectTransactionThreshold, TransactionMetric
1313
from sentry.relay.config.experimental import TimeChecker
1414
from sentry.relay.config.metric_extraction import (
15-
_set_bulk_cached_query_chunk,
15+
_set_bulk_cached_query,
1616
get_current_widget_specs,
1717
get_metric_extraction_config,
1818
)
@@ -766,24 +766,24 @@ def test_get_metric_extraction_config_alerts_and_widgets_off(default_project: Pr
766766
@django_db_all
767767
def test_get_metric_extraction_config_uses_cache_for_widgets(default_project: Project) -> None:
768768
# widgets should be skipped if the feature is off
769-
original_set_bulk_cached_query = _set_bulk_cached_query_chunk
769+
original_set_bulk_cached_query = _set_bulk_cached_query
770770

771771
with (
772772
Feature({ON_DEMAND_METRICS: True, ON_DEMAND_METRICS_WIDGETS: True}),
773773
override_options({"on_demand_metrics.cache_should_use_on_demand": 1.0}),
774774
mock.patch(
775-
"sentry.relay.config.metric_extraction._set_bulk_cached_query_chunk"
776-
) as mock_set_cache_chunk_spy,
775+
"sentry.relay.config.metric_extraction._set_bulk_cached_query"
776+
) as mock_set_cache_spy,
777777
):
778-
mock_set_cache_chunk_spy.side_effect = original_set_bulk_cached_query
778+
mock_set_cache_spy.side_effect = original_set_bulk_cached_query
779779
create_widget(["count()"], "transaction.duration:>=1000", default_project)
780780

781781
get_metric_extraction_config(TimeChecker(timedelta(seconds=0)), default_project)
782782

783-
assert mock_set_cache_chunk_spy.call_count == 6 # One for each chunk
783+
assert mock_set_cache_spy.call_count == 1
784784

785785
get_metric_extraction_config(TimeChecker(timedelta(seconds=0)), default_project)
786-
assert mock_set_cache_chunk_spy.call_count == 6
786+
assert mock_set_cache_spy.call_count == 1
787787

788788

789789
@django_db_all

0 commit comments

Comments
 (0)