From d04730720c114037ba0f498d0ab7c4466e8a95f7 Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 14:23:24 +0200 Subject: [PATCH 1/8] ref(profiling): use chunked approach to query profile candidates for flamegraph --- src/sentry/options/defaults.py | 18 +++ src/sentry/profiles/flamegraph.py | 220 ++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) diff --git a/src/sentry/options/defaults.py b/src/sentry/options/defaults.py index af1b90f1abfafa..caf38dcffab976 100644 --- a/src/sentry/options/defaults.py +++ b/src/sentry/options/defaults.py @@ -2556,6 +2556,24 @@ flags=FLAG_AUTOMATOR_MODIFIABLE, ) +# the duration of the first datetime chunk of data queried +# expressed in hours. +register( + "profiling.flamegraph.query.initial_chunk_delta.hours", + type=Int, + default=12, + flags=FLAG_AUTOMATOR_MODIFIABLE, +) + +# the max duration of any datetime chunk of data queried +# expressed in hours. +register( + "profiling.flamegraph.query.max_delta.hours", + type=Int, + default=48, + flags=FLAG_AUTOMATOR_MODIFIABLE, +) + # list of platform names for which we allow using unsampled profiles for the purpose # of improving profile (function) metrics register( diff --git a/src/sentry/profiles/flamegraph.py b/src/sentry/profiles/flamegraph.py index 745bb723daf98c..aac97d4e4e92e9 100644 --- a/src/sentry/profiles/flamegraph.py +++ b/src/sentry/profiles/flamegraph.py @@ -222,6 +222,64 @@ def get_profile_candidates_from_transactions(self) -> ProfileCandidates: "continuous": continuous_profile_candidates, } + def get_profile_candidates_from_transactions_v2(self) -> ProfileCandidates: + max_profiles = options.get("profiling.flamegraph.profile-set.size") + initial_chunk_delta = options.get("profiling.flamegraph.query.initial_chunk_delta.hours") + max_chunk_delta = options.get("profiling.flamegraph.query.max_delta.hours") + + transaction_profile_candidates: list[TransactionProfileCandidate] = [] + + for start, end in split_datetime_range_exponential( + self.snuba_params.start, self.snuba_params.end, initial_chunk_delta, max_chunk_delta + ): + builder = self.get_transactions_based_candidate_query( + query=self.query, limit=max_profiles + ) + + results = builder.run_query( + Referrer.API_PROFILING_PROFILE_FLAMEGRAPH_TRANSACTION_CANDIDATES.value, + ) + results = builder.process_results(results) + + for row in results["data"]: + if row["profile.id"] is not None: + transaction_profile_candidates.append( + { + "project_id": row["project.id"], + "profile_id": row["profile.id"], + } + ) + if len(transaction_profile_candidates) >= max_profiles: + break + + max_continuous_profile_candidates = max( + max_profiles - len(transaction_profile_candidates), 0 + ) + + continuous_profile_candidates: list[ContinuousProfileCandidate] = [] + + if max_continuous_profile_candidates > 0: + continuous_profile_candidates, _ = self.get_chunks_for_profilers( + [ + ProfilerMeta( + project_id=row["project.id"], + profiler_id=row["profiler.id"], + thread_id=row["thread.id"], + start=row["precise.start_ts"], + end=row["precise.finish_ts"], + transaction_id=row["id"], + ) + for row in results["data"] + if row["profiler.id"] is not None and row["thread.id"] + ], + max_continuous_profile_candidates, + ) + + return { + "transaction": transaction_profile_candidates, + "continuous": continuous_profile_candidates, + } + def get_transactions_based_candidate_query( self, query: str | None, limit: int ) -> DiscoverQueryBuilder: @@ -547,6 +605,168 @@ def get_profile_candidates_from_profiles(self) -> ProfileCandidates: "continuous": continuous_profile_candidates, } + def get_profile_candidates_from_profiles_v2(self) -> ProfileCandidates: + if self.snuba_params.organization is None: + raise ValueError("`organization` is required and cannot be `None`") + + max_profiles = options.get("profiling.flamegraph.profile-set.size") + initial_chunk_delta = options.get("profiling.flamegraph.query.initial_chunk_delta.hours") + max_chunk_delta = options.get("profiling.flamegraph.query.max_delta.hours") + + referrer = Referrer.API_PROFILING_PROFILE_FLAMEGRAPH_PROFILE_CANDIDATES.value + transaction_profile_candidates: list[TransactionProfileCandidate] = [] + profiler_metas: list[ProfilerMeta] = [] + + for start, end in split_datetime_range_exponential( + self.snuba_params.start, self.snuba_params.end, initial_chunk_delta, max_chunk_delta + ): + builder = self.get_transactions_based_candidate_query( + query=self.query, limit=max_profiles + ) + results = builder.run_query(referrer) + results = builder.process_results(results) + + for row in results["data"]: + if row["profile.id"] is not None: + transaction_profile_candidates.append( + { + "project_id": row["project.id"], + "profile_id": row["profile.id"], + } + ) + elif row["profiler.id"] is not None and row["thread.id"]: + profiler_metas.append( + ProfilerMeta( + project_id=row["project.id"], + profiler_id=row["profiler.id"], + thread_id=row["thread.id"], + start=row["precise.start_ts"], + end=row["precise.finish_ts"], + transaction_id=row["id"], + ) + ) + + if len(transaction_profile_candidates) + len(profiler_metas) >= max_profiles: + break + + max_continuous_profile_candidates = max( + max_profiles - len(transaction_profile_candidates), 0 + ) + + continuous_profile_candidates: list[ContinuousProfileCandidate] = [] + continuous_duration = 0.0 + + # If there are continuous profiles attached to transactions, we prefer those as + # the active thread id gives us more user friendly flamegraphs than without. + if profiler_metas and max_continuous_profile_candidates > 0: + continuous_profile_candidates, continuous_duration = self.get_chunks_for_profilers( + profiler_metas, max_continuous_profile_candidates + ) + + seen_chunks = { + (candidate["profiler_id"], candidate["chunk_id"]) + for candidate in continuous_profile_candidates + } + + always_use_direct_chunks = features.has( + "organizations:profiling-flamegraph-always-use-direct-chunks", + self.snuba_params.organization, + actor=self.request.user, + ) + + # If we still don't have enough continuous profile candidates + transaction profile candidates, + # we'll fall back to directly using the continuous profiling data + if ( + len(continuous_profile_candidates) + len(transaction_profile_candidates) < max_profiles + and always_use_direct_chunks + ): + total_duration = continuous_duration if always_use_direct_chunks else 0.0 + max_duration = options.get("profiling.continuous-profiling.flamegraph.max-seconds") + + conditions = [] + conditions.append(Condition(Column("project_id"), Op.IN, self.snuba_params.project_ids)) + conditions.append( + Condition( + Column("start_timestamp"), Op.LT, resolve_datetime64(self.snuba_params.end) + ) + ) + conditions.append( + Condition( + Column("end_timestamp"), Op.GTE, resolve_datetime64(self.snuba_params.start) + ) + ) + environments = self.snuba_params.environment_names + if environments: + conditions.append(Condition(Column("environment"), Op.IN, environments)) + + continuous_profiles_query = Query( + match=Storage(StorageKey.ProfileChunks.value), + select=[ + Column("project_id"), + Column("profiler_id"), + Column("chunk_id"), + Column("start_timestamp"), + Column("end_timestamp"), + ], + where=conditions, + orderby=[OrderBy(Column("start_timestamp"), Direction.DESC)], + limit=Limit(max_profiles), + ) + + all_results = bulk_snuba_queries( + [ + Request( + dataset=Dataset.Profiles.value, + app_id="default", + query=continuous_profiles_query, + tenant_ids={ + "referrer": referrer, + "organization_id": self.snuba_params.organization.id, + }, + ), + ], + referrer, + ) + + continuous_profile_results = all_results[0] + + for row in continuous_profile_results["data"]: + + # Make sure to dedupe profile chunks so we don't reuse chunks + if (row["profiler_id"], row["chunk_id"]) in seen_chunks: + continue + + start = datetime.fromisoformat(row["start_timestamp"]).timestamp() + end = datetime.fromisoformat(row["end_timestamp"]).timestamp() + + candidate: ContinuousProfileCandidate = { + "project_id": row["project_id"], + "profiler_id": row["profiler_id"], + "chunk_id": row["chunk_id"], + "start": str(int(start * 1e9)), + "end": str(int(end * 1e9)), + } + + continuous_profile_candidates.append(candidate) + + total_duration += end - start + + # can set max duration to negative to skip this check + if ( + max_duration >= 0 + and total_duration >= max_duration + or ( + len(continuous_profile_candidates) + len(transaction_profile_candidates) + >= max_profiles + ) + ): + break + + return { + "transaction": transaction_profile_candidates, + "continuous": continuous_profile_candidates, + } + def get_profile_candidates_from_spans(self) -> ProfileCandidates: max_profiles = options.get("profiling.flamegraph.profile-set.size") results = self.get_spans_based_candidates(query=self.query, limit=max_profiles) From c9676d72a7b13ee5f708e35b80d61f35a686808d Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 15:10:28 +0200 Subject: [PATCH 2/8] ref(profiling): support querying profile candidates in chunked time ranges --- src/sentry/features/temporary.py | 2 ++ src/sentry/profiles/flamegraph.py | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/sentry/features/temporary.py b/src/sentry/features/temporary.py index 2a51ebb37c159a..7f4ed5d74686bc 100644 --- a/src/sentry/features/temporary.py +++ b/src/sentry/features/temporary.py @@ -88,6 +88,8 @@ def register_temporary_features(manager: FeatureManager): manager.add("projects:continuous-profiling-vroomrs-processing", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False) # Enable transaction profiles processing with vroomrs manager.add("projects:transaction-profiling-vroomrs-processing", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False) + # Enable querying profile candidates with exponentially growing datetime range chunks + manager.add("organizations:profiling-flamegraph-use-increased-chunks-query-strategy", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False) # Enable daily summary manager.add("organizations:daily-summary", OrganizationFeature, FeatureHandlerStrategy.INTERNAL, api_expose=False) # Enables import/export functionality for dashboards diff --git a/src/sentry/profiles/flamegraph.py b/src/sentry/profiles/flamegraph.py index aac97d4e4e92e9..c5b53747024981 100644 --- a/src/sentry/profiles/flamegraph.py +++ b/src/sentry/profiles/flamegraph.py @@ -21,6 +21,7 @@ ) from sentry import features, options +from sentry.models.organization import Organization from sentry.search.eap.types import EAPResponse, SearchResolverConfig from sentry.search.events.builder.discover import DiscoverQueryBuilder from sentry.search.events.builder.profile_functions import ProfileFunctionsQueryBuilder @@ -102,8 +103,20 @@ def get_profile_candidates(self) -> ProfileCandidates: if self.data_source == "functions": return self.get_profile_candidates_from_functions() elif self.data_source == "transactions": + organization = Organization.objects.get_from_cache(id=self.snuba_params.organization_id) + if features.has( + "organizations:profiling-flamegraph-use-increased-chunks-query-strategy", + organization, + ): + return self.get_profile_candidates_from_transactions_v2 return self.get_profile_candidates_from_transactions() elif self.data_source == "profiles": + organization = Organization.objects.get_from_cache(id=self.snuba_params.organization_id) + if features.has( + "organizations:profiling-flamegraph-use-increased-chunks-query-strategy", + organization, + ): + return self.get_profile_candidates_from_profiles_v2() return self.get_profile_candidates_from_profiles() elif self.data_source == "spans": return self.get_profile_candidates_from_spans() From 568a036e2fe028d4478147b952f6a12ad0b41d28 Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 15:16:45 +0200 Subject: [PATCH 3/8] add parenthesis for better clarity --- src/sentry/profiles/flamegraph.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/sentry/profiles/flamegraph.py b/src/sentry/profiles/flamegraph.py index c5b53747024981..99e7cd4e32a9fa 100644 --- a/src/sentry/profiles/flamegraph.py +++ b/src/sentry/profiles/flamegraph.py @@ -765,13 +765,9 @@ def get_profile_candidates_from_profiles_v2(self) -> ProfileCandidates: total_duration += end - start # can set max duration to negative to skip this check - if ( - max_duration >= 0 - and total_duration >= max_duration - or ( - len(continuous_profile_candidates) + len(transaction_profile_candidates) - >= max_profiles - ) + if (max_duration >= 0 and total_duration >= max_duration) or ( + len(continuous_profile_candidates) + len(transaction_profile_candidates) + >= max_profiles ): break From 78a3490d0f479939f2b24f340d9d7dd77b022147 Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 15:44:31 +0200 Subject: [PATCH 4/8] fix --- src/sentry/profiles/flamegraph.py | 53 ++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/sentry/profiles/flamegraph.py b/src/sentry/profiles/flamegraph.py index 99e7cd4e32a9fa..0ae678fe24f0b2 100644 --- a/src/sentry/profiles/flamegraph.py +++ b/src/sentry/profiles/flamegraph.py @@ -108,7 +108,7 @@ def get_profile_candidates(self) -> ProfileCandidates: "organizations:profiling-flamegraph-use-increased-chunks-query-strategy", organization, ): - return self.get_profile_candidates_from_transactions_v2 + return self.get_profile_candidates_from_transactions_v2() return self.get_profile_candidates_from_transactions() elif self.data_source == "profiles": organization = Organization.objects.get_from_cache(id=self.snuba_params.organization_id) @@ -237,14 +237,24 @@ def get_profile_candidates_from_transactions(self) -> ProfileCandidates: def get_profile_candidates_from_transactions_v2(self) -> ProfileCandidates: max_profiles = options.get("profiling.flamegraph.profile-set.size") - initial_chunk_delta = options.get("profiling.flamegraph.query.initial_chunk_delta.hours") - max_chunk_delta = options.get("profiling.flamegraph.query.max_delta.hours") + initial_chunk_delta_hours = options.get( + "profiling.flamegraph.query.initial_chunk_delta.hours" + ) + max_chunk_delta_hours = options.get("profiling.flamegraph.query.max_delta.hours") + + initial_chunk_delta = timedelta(hours=initial_chunk_delta_hours) + max_chunk_delta = timedelta(hours=max_chunk_delta_hours) transaction_profile_candidates: list[TransactionProfileCandidate] = [] - for start, end in split_datetime_range_exponential( + assert self.snuba_params.start is not None and self.snuba_params.end is not None + + for chunk_start, chunk_end in split_datetime_range_exponential( self.snuba_params.start, self.snuba_params.end, initial_chunk_delta, max_chunk_delta ): + self.snuba_params.start = chunk_start + self.snuba_params.end = chunk_end + builder = self.get_transactions_based_candidate_query( query=self.query, limit=max_profiles ) @@ -623,16 +633,27 @@ def get_profile_candidates_from_profiles_v2(self) -> ProfileCandidates: raise ValueError("`organization` is required and cannot be `None`") max_profiles = options.get("profiling.flamegraph.profile-set.size") - initial_chunk_delta = options.get("profiling.flamegraph.query.initial_chunk_delta.hours") - max_chunk_delta = options.get("profiling.flamegraph.query.max_delta.hours") + initial_chunk_delta_hours = options.get( + "profiling.flamegraph.query.initial_chunk_delta.hours" + ) + max_chunk_delta_hours = options.get("profiling.flamegraph.query.max_delta.hours") + + initial_chunk_delta = timedelta(hours=initial_chunk_delta_hours) + max_chunk_delta = timedelta(hours=max_chunk_delta_hours) referrer = Referrer.API_PROFILING_PROFILE_FLAMEGRAPH_PROFILE_CANDIDATES.value transaction_profile_candidates: list[TransactionProfileCandidate] = [] profiler_metas: list[ProfilerMeta] = [] - for start, end in split_datetime_range_exponential( + assert self.snuba_params.start is not None and self.snuba_params.end is not None + original_start, original_end = self.snuba_params.start, self.snuba_params.end + + for chunk_start, chunk_end in split_datetime_range_exponential( self.snuba_params.start, self.snuba_params.end, initial_chunk_delta, max_chunk_delta ): + self.snuba_params.start = chunk_start + self.snuba_params.end = chunk_end + builder = self.get_transactions_based_candidate_query( query=self.query, limit=max_profiles ) @@ -699,14 +720,10 @@ def get_profile_candidates_from_profiles_v2(self) -> ProfileCandidates: conditions = [] conditions.append(Condition(Column("project_id"), Op.IN, self.snuba_params.project_ids)) conditions.append( - Condition( - Column("start_timestamp"), Op.LT, resolve_datetime64(self.snuba_params.end) - ) + Condition(Column("start_timestamp"), Op.LT, resolve_datetime64(original_end)) ) conditions.append( - Condition( - Column("end_timestamp"), Op.GTE, resolve_datetime64(self.snuba_params.start) - ) + Condition(Column("end_timestamp"), Op.GTE, resolve_datetime64(original_start)) ) environments = self.snuba_params.environment_names if environments: @@ -749,20 +766,20 @@ def get_profile_candidates_from_profiles_v2(self) -> ProfileCandidates: if (row["profiler_id"], row["chunk_id"]) in seen_chunks: continue - start = datetime.fromisoformat(row["start_timestamp"]).timestamp() - end = datetime.fromisoformat(row["end_timestamp"]).timestamp() + start_timestamp = datetime.fromisoformat(row["start_timestamp"]).timestamp() + end_timestamp = datetime.fromisoformat(row["end_timestamp"]).timestamp() candidate: ContinuousProfileCandidate = { "project_id": row["project_id"], "profiler_id": row["profiler_id"], "chunk_id": row["chunk_id"], - "start": str(int(start * 1e9)), - "end": str(int(end * 1e9)), + "start": str(int(start_timestamp * 1e9)), + "end": str(int(end_timestamp * 1e9)), } continuous_profile_candidates.append(candidate) - total_duration += end - start + total_duration += end_timestamp - start_timestamp # can set max duration to negative to skip this check if (max_duration >= 0 and total_duration >= max_duration) or ( From 6d2c53b61e58fa37908b8e8bfdc35c756c366905 Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 16:47:11 +0200 Subject: [PATCH 5/8] fix feature type --- src/sentry/features/temporary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/features/temporary.py b/src/sentry/features/temporary.py index 7f4ed5d74686bc..38963f1cd98a7e 100644 --- a/src/sentry/features/temporary.py +++ b/src/sentry/features/temporary.py @@ -89,7 +89,7 @@ def register_temporary_features(manager: FeatureManager): # Enable transaction profiles processing with vroomrs manager.add("projects:transaction-profiling-vroomrs-processing", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False) # Enable querying profile candidates with exponentially growing datetime range chunks - manager.add("organizations:profiling-flamegraph-use-increased-chunks-query-strategy", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False) + manager.add("organizations:profiling-flamegraph-use-increased-chunks-query-strategy", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False) # Enable daily summary manager.add("organizations:daily-summary", OrganizationFeature, FeatureHandlerStrategy.INTERNAL, api_expose=False) # Enables import/export functionality for dashboards From 303897511b52cc0123efcd9b8335b62ceeecdc5f Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 16:53:47 +0200 Subject: [PATCH 6/8] fix collecting profiler_metas for get_profile_candidates_from_transactions_v2 --- src/sentry/profiles/flamegraph.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/sentry/profiles/flamegraph.py b/src/sentry/profiles/flamegraph.py index 0ae678fe24f0b2..6e56f87a4a66ec 100644 --- a/src/sentry/profiles/flamegraph.py +++ b/src/sentry/profiles/flamegraph.py @@ -246,6 +246,7 @@ def get_profile_candidates_from_transactions_v2(self) -> ProfileCandidates: max_chunk_delta = timedelta(hours=max_chunk_delta_hours) transaction_profile_candidates: list[TransactionProfileCandidate] = [] + profiler_metas: list[ProfilerMeta] = [] assert self.snuba_params.start is not None and self.snuba_params.end is not None @@ -272,6 +273,17 @@ def get_profile_candidates_from_transactions_v2(self) -> ProfileCandidates: "profile_id": row["profile.id"], } ) + elif row["profiler.id"] is not None and row["thread.id"]: + profiler_metas.append( + ProfilerMeta( + project_id=row["project.id"], + profiler_id=row["profiler.id"], + thread_id=row["thread.id"], + start=row["precise.start_ts"], + end=row["precise.finish_ts"], + transaction_id=row["id"], + ) + ) if len(transaction_profile_candidates) >= max_profiles: break @@ -283,18 +295,7 @@ def get_profile_candidates_from_transactions_v2(self) -> ProfileCandidates: if max_continuous_profile_candidates > 0: continuous_profile_candidates, _ = self.get_chunks_for_profilers( - [ - ProfilerMeta( - project_id=row["project.id"], - profiler_id=row["profiler.id"], - thread_id=row["thread.id"], - start=row["precise.start_ts"], - end=row["precise.finish_ts"], - transaction_id=row["id"], - ) - for row in results["data"] - if row["profiler.id"] is not None and row["thread.id"] - ], + profiler_metas, max_continuous_profile_candidates, ) From b646ea9238eff19790b6ceca1320b74054856411 Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 16:55:34 +0200 Subject: [PATCH 7/8] use unambiguous start and end datetime while overwriting snuba params --- src/sentry/profiles/flamegraph.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sentry/profiles/flamegraph.py b/src/sentry/profiles/flamegraph.py index 6e56f87a4a66ec..936cd61eb3aaf8 100644 --- a/src/sentry/profiles/flamegraph.py +++ b/src/sentry/profiles/flamegraph.py @@ -249,9 +249,10 @@ def get_profile_candidates_from_transactions_v2(self) -> ProfileCandidates: profiler_metas: list[ProfilerMeta] = [] assert self.snuba_params.start is not None and self.snuba_params.end is not None + original_start, original_end = self.snuba_params.start, self.snuba_params.end for chunk_start, chunk_end in split_datetime_range_exponential( - self.snuba_params.start, self.snuba_params.end, initial_chunk_delta, max_chunk_delta + original_start, original_end, initial_chunk_delta, max_chunk_delta ): self.snuba_params.start = chunk_start self.snuba_params.end = chunk_end @@ -650,7 +651,7 @@ def get_profile_candidates_from_profiles_v2(self) -> ProfileCandidates: original_start, original_end = self.snuba_params.start, self.snuba_params.end for chunk_start, chunk_end in split_datetime_range_exponential( - self.snuba_params.start, self.snuba_params.end, initial_chunk_delta, max_chunk_delta + original_start, original_end, initial_chunk_delta, max_chunk_delta ): self.snuba_params.start = chunk_start self.snuba_params.end = chunk_end From c0da52d020ec9b5258f0127048b6ffc0699d8965 Mon Sep 17 00:00:00 2001 From: Francesco Vigliaturo Date: Fri, 18 Jul 2025 16:57:29 +0200 Subject: [PATCH 8/8] fix how the organization is fetched --- src/sentry/profiles/flamegraph.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sentry/profiles/flamegraph.py b/src/sentry/profiles/flamegraph.py index 936cd61eb3aaf8..523cb1866bfe00 100644 --- a/src/sentry/profiles/flamegraph.py +++ b/src/sentry/profiles/flamegraph.py @@ -21,7 +21,6 @@ ) from sentry import features, options -from sentry.models.organization import Organization from sentry.search.eap.types import EAPResponse, SearchResolverConfig from sentry.search.events.builder.discover import DiscoverQueryBuilder from sentry.search.events.builder.profile_functions import ProfileFunctionsQueryBuilder @@ -103,18 +102,16 @@ def get_profile_candidates(self) -> ProfileCandidates: if self.data_source == "functions": return self.get_profile_candidates_from_functions() elif self.data_source == "transactions": - organization = Organization.objects.get_from_cache(id=self.snuba_params.organization_id) if features.has( "organizations:profiling-flamegraph-use-increased-chunks-query-strategy", - organization, + self.snuba_params.organization, ): return self.get_profile_candidates_from_transactions_v2() return self.get_profile_candidates_from_transactions() elif self.data_source == "profiles": - organization = Organization.objects.get_from_cache(id=self.snuba_params.organization_id) if features.has( "organizations:profiling-flamegraph-use-increased-chunks-query-strategy", - organization, + self.snuba_params.organization, ): return self.get_profile_candidates_from_profiles_v2() return self.get_profile_candidates_from_profiles()