Skip to content

feat(profiling): Add endpoint to download profile chunk attachments#117617

Draft
markushi wants to merge 2 commits into
masterfrom
feat/profiling-chunk-attachment-download
Draft

feat(profiling): Add endpoint to download profile chunk attachments#117617
markushi wants to merge 2 commits into
masterfrom
feat/profiling-chunk-attachment-download

Conversation

@markushi

@markushi markushi commented Jun 14, 2026

Copy link
Copy Markdown
Member

Summary

Adds ProjectProfilingChunkAttachmentEndpoint to download an attachment (e.g. a perfetto trace) of a profile chunk.

GET .../projects/{project}/profiling/chunks/{profiler_id}/{chunk_id}/attachments/{attachment_name}/

The client supplies only the profiler/chunk IDs and the attachment name. The endpoint loads the chunk from the profiles object store and resolves the attachment's object store id and content type from the chunk itself.

⚠️ Depends on (merge first)

This endpoint relies on the chunk attachments API that is added by the following PRs. Both must be merged and released before this can land, otherwise vroomrs.decompress_profile_chunk(...).get_attachments() is unavailable:

Test plan

  • pytest tests/sentry/api/endpoints/test_project_profiling_profile.py — covers happy-path download, content-type fallback, unknown attachment name, chunk without attachments, missing chunk, missing attachment file, and feature-flag-disabled (all 404 paths).

Add ProjectProfilingChunkAttachmentEndpoint to download an attachment (e.g.
a perfetto trace) of a profile chunk.

The client supplies only the profiler/chunk IDs and the attachment name. The
endpoint loads the chunk from the profiles object store and resolves the
attachment's object store id and content type from the chunk itself, so no
client-supplied storage key or content type is reflected back. The download is
served as an attachment and the file handle is closed once the stream is
exhausted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jun 14, 2026
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Jun 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.


import orjson
from django.http import HttpResponse
import vroomrs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

vroomrs.decompress_profile_chunk corrupt-data exception escapes narrow OSError catch (500)

In ProjectProfilingChunkAttachmentEndpoint.get, the stored chunk blob is decompressed via vroomrs.decompress_profile_chunk(f.read()) inside a try/except OSError (lines 176-180). OSError only covers I/O failures from storage.open/f.read(). If the stored chunk blob is corrupt, truncated, or otherwise malformed, the vroomrs Rust binding raises a non-OSError exception (e.g. ValueError or a binding-specific error), which is not caught here and propagates as an unhandled HTTP 500. The intended fallback (Http404) is bypassed. The codebase already treats vroomrs decode failures as broad exceptions: src/sentry/profiles/task.py wraps every vroomrs.profile_chunk_from_json_str(...)/profile_from_json_str(...) call in except Exception (lines 1410, 1480), confirming these bindings raise non-OSError errors on invalid input. Fix by catching the broader exception around the decode and raising Http404.

Evidence
  • Endpoint get (lines 176-180) wraps vroomrs.decompress_profile_chunk(f.read()) in try/except OSError: raise Http404, so only I/O errors map to 404.
  • src/sentry/profiles/task.py lines 1433/1480 and 1340/1410 wrap vroomrs decode calls in except Exception, showing the bindings raise non-OSError exceptions on malformed data.
  • A corrupt or truncated chunk blob in object storage (partial write, storage corruption) is a realistic input that reaches decompress_profile_chunk directly, so a non-OSError exception escapes to an unhandled 500.
Also found at 1 additional location
  • src/sentry/api/endpoints/project_profiling_profile.py:175-179

Identified by Warden sentry-backend-bugs · TUA-UAA

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 Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant