Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion sentry/interceptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@
with workflow.unsafe.imports_passed_through():
import sentry_sdk


logger = logging.getLogger(__name__)

TEMPORAL_UI_URL = "https://cloud.temporal.io"


def _build_temporal_workflow_url(namespace: str, workflow_id: str, run_id: str) -> str | None:
"""Build a URL to the Temporal UI for a specific workflow execution."""
# URL encode the workflow_id in case it contains special characters
encoded_workflow_id = quote(workflow_id, safe="")
return f"{TEMPORAL_UI_URL}/namespaces/{namespace}/workflows/{encoded_workflow_id}/{run_id}"


class _SentryActivityInboundInterceptor(ActivityInboundInterceptor):
async def execute_activity(self, input: ExecuteActivityInput) -> Any:
Expand All @@ -35,6 +43,27 @@ async def execute_activity(self, input: ExecuteActivityInput) -> Any:
"temporal.workflow.namespace", activity_info.workflow_namespace
)
scope.set_tag("temporal.workflow.run_id", activity_info.workflow_run_id)

# Build workflow URL for easy navigation from Sentry
Copy link
Member

Choose a reason for hiding this comment

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

This is meant to be a sample a user can adjust with these more advanced needs rather than a library. I am not sure we want the sample assuming anything about cloud, though it would totally make sense for some users to set this tag (or any other tag) when they copy this sample and adjust it for their needs.

workflow_url = _build_temporal_workflow_url(
namespace=activity_info.workflow_namespace,
workflow_id=activity_info.workflow_id,
run_id=activity_info.workflow_run_id,
)

if workflow_url:
scope.set_tag("temporal.workflow.url", workflow_url)
scope.set_context(
"Temporal Workflow",
{
"name": activity_info.workflow_type,
"url": workflow_url,
"workflow_id": activity_info.workflow_id,
"run_id": activity_info.workflow_run_id,
"activity": activity_info.activity_type,
},
)

try:
return await super().execute_activity(input)
except Exception as e:
Expand All @@ -61,6 +90,28 @@ async def execute_workflow(self, input: ExecuteWorkflowInput) -> Any:
scope.set_tag("temporal.workflow.task_queue", workflow_info.task_queue)
scope.set_tag("temporal.workflow.namespace", workflow_info.namespace)
scope.set_tag("temporal.workflow.run_id", workflow_info.run_id)

# Build workflow URL for easy navigation from Sentry
# Note: We need to access settings inside sandbox_unrestricted for workflow context
with workflow.unsafe.sandbox_unrestricted():
workflow_url = _build_temporal_workflow_url(
namespace=workflow_info.namespace,
workflow_id=workflow_info.workflow_id,
run_id=workflow_info.run_id,
)

if workflow_url:
scope.set_tag("temporal.workflow.url", workflow_url)
scope.set_context(
"Temporal Workflow",
{
"name": workflow_info.workflow_type,
"url": workflow_url,
"workflow_id": workflow_info.workflow_id,
"run_id": workflow_info.run_id,
},
)

try:
return await super().execute_workflow(input)
except Exception as e:
Expand Down