From 68b25c7401d3fa800f56d00ac20f68bd18e0ec6a Mon Sep 17 00:00:00 2001 From: Matt Hammerly Date: Wed, 1 Apr 2026 15:18:28 -0700 Subject: [PATCH 1/4] feat(symbolicator): pass objectstore token to symbolicator --- src/sentry/lang/native/symbolicator.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sentry/lang/native/symbolicator.py b/src/sentry/lang/native/symbolicator.py index 9e2d701837d5e1..5b5848ad0b2499 100644 --- a/src/sentry/lang/native/symbolicator.py +++ b/src/sentry/lang/native/symbolicator.py @@ -190,6 +190,7 @@ def process_minidump( if minidump.stored_id: session = get_attachments_session(self.project.organization_id, self.project.id) storage_url = get_symbolicator_url(session, minidump.stored_id) + storage_token = session.mint_token() json: dict[str, Any] = { "platform": platform, "sources": sources, @@ -198,6 +199,7 @@ def process_minidump( "symbolicate": { "type": "minidump", "storage_url": storage_url, + "storage_token": storage_token, "rewrite_first_module": rewrite_first_module, }, } @@ -223,6 +225,7 @@ def process_applecrashreport(self, platform: str, report: CachedAttachment): if report.stored_id: session = get_attachments_session(self.project.organization_id, self.project.id) storage_url = get_symbolicator_url(session, report.stored_id) + storage_token = session.mint_token() json: dict[str, Any] = { "platform": platform, "sources": sources, @@ -231,6 +234,7 @@ def process_applecrashreport(self, platform: str, report: CachedAttachment): "symbolicate": { "type": "applecrashreport", "storage_url": storage_url, + "storage_token": storage_token, }, } res = self._process("process_applecrashreport", "symbolicate-any", json=json) From 57fc5909f0400347f7c60ca7509ce492afe33827 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Thu, 2 Apr 2026 12:50:29 +0200 Subject: [PATCH 2/4] build: Bump objectstore-client to 0.1.5 --- pyproject.toml | 2 +- uv.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4d323c49836886..704559ec8e75d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ dependencies = [ "mmh3>=4.0.0", "msgspec>=0.19.0", "msgpack>=1.1.0", - "objectstore-client>=0.1.1", + "objectstore-client>=0.1.5", "openai>=1.3.5", "orjson>=3.10.10", "p4python>=2025.1.2767466", diff --git a/uv.lock b/uv.lock index cb70c310833363..d4c5e7b677ace0 100644 --- a/uv.lock +++ b/uv.lock @@ -1322,7 +1322,7 @@ wheels = [ [[package]] name = "objectstore-client" -version = "0.1.1" +version = "0.1.5" source = { registry = "https://pypi.devinfra.sentry.io/simple" } dependencies = [ { name = "filetype", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, @@ -1332,7 +1332,7 @@ dependencies = [ { name = "zstandard", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] wheels = [ - { url = "https://pypi.devinfra.sentry.io/wheels/objectstore_client-0.1.1-py3-none-any.whl", hash = "sha256:fb63e88b6db101440b45f951810a35df41ade599f90791a1068e4da4e8e10691" }, + { url = "https://pypi.devinfra.sentry.io/wheels/objectstore_client-0.1.5-py3-none-any.whl", hash = "sha256:19ffcef5e33070d418268067e424fcb8de0739bfd2d310bc2de95a6791845857" }, ] [[package]] @@ -2337,7 +2337,7 @@ requires-dist = [ { name = "mmh3", specifier = ">=4.0.0" }, { name = "msgpack", specifier = ">=1.1.0" }, { name = "msgspec", specifier = ">=0.19.0" }, - { name = "objectstore-client", specifier = ">=0.1.1" }, + { name = "objectstore-client", specifier = ">=0.1.5" }, { name = "openai", specifier = ">=1.3.5" }, { name = "orjson", specifier = ">=3.10.10" }, { name = "p4python", specifier = ">=2025.1.2767466" }, From eb2ae56cc6ffca04464ca2bba2ce94ff6849d023 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Thu, 2 Apr 2026 15:04:20 +0200 Subject: [PATCH 3/4] fix(symbolicator): Refresh storage token on task resubmission The storage token was minted once before entering the retry loop in _process. On TaskIdNotFound or ServiceUnavailable the task is resubmitted with the same token, which may have expired by then. Add a kwargs_cb parameter to _process that is called on every new task submission and merged over the static kwargs. The objectstore callers use this to mint a fresh token each time instead of reusing the original one. --- src/sentry/lang/native/symbolicator.py | 31 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/sentry/lang/native/symbolicator.py b/src/sentry/lang/native/symbolicator.py index 5b5848ad0b2499..7ceef5bad5c417 100644 --- a/src/sentry/lang/native/symbolicator.py +++ b/src/sentry/lang/native/symbolicator.py @@ -114,11 +114,21 @@ def __init__( self.project = project self.event_id = event_id - def _process(self, task_name: str, path: str, **kwargs): + def _process( + self, + task_name: str, + path: str, + kwargs_cb: Callable[[], dict[str, Any]] | None = None, + **kwargs: Any, + ) -> Any: """ This function will submit a symbolication task to a Symbolicator and handle polling it using the `SymbolicatorSession`. It will also correctly handle `TaskIdNotFound` and `ServiceUnavailable` errors. + + `kwargs_cb`, if provided, is called on every new task submission and its result + is merged over `kwargs`. Use this for values that must be fresh on each + (re)submission, such as expiring tokens. """ session = SymbolicatorSession( url=self.base_url, @@ -137,7 +147,8 @@ def _process(self, task_name: str, path: str, **kwargs): try: if not task_id: # We are submitting a new task to Symbolicator - json_response = session.create_task(path, **kwargs) + create_kwargs = {**kwargs, **(kwargs_cb() if kwargs_cb else {})} + json_response = session.create_task(path, **create_kwargs) else: # The task has already been submitted to Symbolicator and we are polling json_response = session.query_task(task_id) @@ -190,7 +201,6 @@ def process_minidump( if minidump.stored_id: session = get_attachments_session(self.project.organization_id, self.project.id) storage_url = get_symbolicator_url(session, minidump.stored_id) - storage_token = session.mint_token() json: dict[str, Any] = { "platform": platform, "sources": sources, @@ -199,11 +209,15 @@ def process_minidump( "symbolicate": { "type": "minidump", "storage_url": storage_url, - "storage_token": storage_token, "rewrite_first_module": rewrite_first_module, }, } - res = self._process("process_minidump", "symbolicate-any", json=json) + + def cb() -> dict[str, Any]: + json["symbolicate"]["storage_token"] = session.mint_token() + return {"json": json} + + res = self._process("process_minidump", "symbolicate-any", kwargs_cb=cb) return process_response(res) data = { @@ -237,7 +251,12 @@ def process_applecrashreport(self, platform: str, report: CachedAttachment): "storage_token": storage_token, }, } - res = self._process("process_applecrashreport", "symbolicate-any", json=json) + + def cb() -> dict[str, Any]: + json["symbolicate"]["storage_token"] = session.mint_token() + return {"json": json} + + res = self._process("process_applecrashreport", "symbolicate-any", kwargs_cb=cb) return process_response(res) data = { From 3237f53055e7487bd6e3615ac829d07981b66d1f Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Thu, 2 Apr 2026 16:47:39 +0200 Subject: [PATCH 4/4] fix: Redundant token --- src/sentry/lang/native/symbolicator.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sentry/lang/native/symbolicator.py b/src/sentry/lang/native/symbolicator.py index 7ceef5bad5c417..5d788dd104b1a8 100644 --- a/src/sentry/lang/native/symbolicator.py +++ b/src/sentry/lang/native/symbolicator.py @@ -239,7 +239,6 @@ def process_applecrashreport(self, platform: str, report: CachedAttachment): if report.stored_id: session = get_attachments_session(self.project.organization_id, self.project.id) storage_url = get_symbolicator_url(session, report.stored_id) - storage_token = session.mint_token() json: dict[str, Any] = { "platform": platform, "sources": sources, @@ -248,7 +247,6 @@ def process_applecrashreport(self, platform: str, report: CachedAttachment): "symbolicate": { "type": "applecrashreport", "storage_url": storage_url, - "storage_token": storage_token, }, }