feat(profiling): Add endpoint to download profile chunk attachments#117617
feat(profiling): Add endpoint to download profile chunk attachments#117617markushi wants to merge 2 commits into
Conversation
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>
|
🚨 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 |
|
|
||
| import orjson | ||
| from django.http import HttpResponse | ||
| import vroomrs |
There was a problem hiding this comment.
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) wrapsvroomrs.decompress_profile_chunk(f.read())intry/except OSError: raise Http404, so only I/O errors map to 404. src/sentry/profiles/task.pylines 1433/1480 and 1340/1410 wrap vroomrs decode calls inexcept Exception, showing the bindings raise non-OSErrorexceptions on malformed data.- A corrupt or truncated chunk blob in object storage (partial write, storage corruption) is a realistic input that reaches
decompress_profile_chunkdirectly, 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
Summary
Adds
ProjectProfilingChunkAttachmentEndpointto 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.
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).