Skip to content

Conversation

@roaga
Copy link
Member

@roaga roaga commented Nov 13, 2025

Adds an RPC that gets a profile flamegraph given just a profile id (8 char or 32 char). Automatically finds the full ID and distinguishes between transaction and continuous profiles. The caveat is we require tracing for profiling to work, but this is true in 99% of cases already.

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 13, 2025
@codecov
Copy link

codecov bot commented Nov 13, 2025

Codecov Report

❌ Patch coverage is 83.33333% with 8 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/sentry/seer/explorer/tools.py 83.33% 8 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master   #103293      +/-   ##
===========================================
- Coverage   80.67%    80.67%   -0.01%     
===========================================
  Files        9243      9243              
  Lines      394826    394912      +86     
  Branches    25152     25152              
===========================================
+ Hits       318538    318596      +58     
- Misses      75841     75869      +28     
  Partials      447       447              

@roaga roaga marked this pull request as ready for review November 13, 2025 17:00
@roaga roaga requested a review from a team as a code owner November 13, 2025 17:00
@roaga roaga requested a review from aliu39 November 13, 2025 17:00
project_id = row.get("project.id")
min_start_ts = row.get("min(precise.start_ts)")
max_end_ts = row.get("max(precise.finish_ts)")
break
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Aggregate Query Mixes Profile Data

The aggregate query at lines 349-367 doesn't use GROUP BY when selecting non-aggregated columns (profile.id, profiler.id, project.id) alongside aggregation functions (min(precise.start_ts), max(precise.finish_ts)). When the wildcard query matches spans with different full profile IDs sharing the same prefix, the aggregates compute min/max timestamps across all profiles while returning an arbitrary profile ID. This causes fetch_profile_data to receive timestamps from different profiles than the one being fetched, potentially leading to incorrect or missing profile data.

Fix in Cursor Fix in Web

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretty sure it automatically applies the group by



@pytest.mark.django_db(databases=["default", "control"])
class TestRpcGetProfileFlamegraph(APITransactionTestCase, SpanTestCase, SnubaTestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm wondering if a transaction test case is actually necessary? (it is much slower than the regular APITestCase)

assert result["external_id"] == "12345678"


@pytest.mark.django_db(databases=["default", "control"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think this decorator is necessary?

@semgrep-code-getsentry
Copy link

Semgrep found 1 ssc-e23b0a49-86b3-48bc-b82c-03656ca7eaee finding:

Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious _connector entry. This bypasses the normal query parameterization and lets an attacker inject arbitrary SQL into the WHERE clause.

Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305.

Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459

return {"error": "Organization not found"}

# Get all projects for the organization
projects = list(Project.objects.filter(organization=organization, status=ObjectStatus.ACTIVE))
Copy link

@semgrep-code-getsentry semgrep-code-getsentry bot Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious _connector entry. This bypasses the normal query parameterization and lets an attacker inject arbitrary SQL into the WHERE clause.

Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305.

Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459

🎈 Fixed in commit a12ee26 🎈

@roaga roaga merged commit e4534e7 into master Nov 15, 2025
66 checks passed
@roaga roaga deleted the explorer/flamegraph-tool branch November 15, 2025 01:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants