Skip to content

fix(integrations): Do not patch execute #4026

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions requirements-linting.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ openfeature-sdk
launchdarkly-server-sdk
UnleashClient
typer
strawberry-graphql
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/ariadne.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
if TYPE_CHECKING:
from typing import Any, Dict, List, Optional
from ariadne.types import GraphQLError, GraphQLResult, GraphQLSchema, QueryParser # type: ignore
from graphql.language.ast import DocumentNode # type: ignore
from graphql.language.ast import DocumentNode
from sentry_sdk._types import Event, EventProcessor


Expand Down
7 changes: 6 additions & 1 deletion sentry_sdk/integrations/gql.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@

try:
import gql # type: ignore[import-not-found]
from graphql import print_ast, get_operation_ast, DocumentNode, VariableDefinitionNode # type: ignore[import-not-found]
from graphql import (
print_ast,
get_operation_ast,
DocumentNode,
VariableDefinitionNode,
)
from gql.transport import Transport, AsyncTransport # type: ignore[import-not-found]
from gql.transport.exceptions import TransportQueryError # type: ignore[import-not-found]
except ImportError:
Expand Down
4 changes: 2 additions & 2 deletions sentry_sdk/integrations/graphene.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
from collections.abc import Generator
from typing import Any, Dict, Union
from graphene.language.source import Source # type: ignore
from graphql.execution import ExecutionResult # type: ignore
from graphql.type import GraphQLSchema # type: ignore
from graphql.execution import ExecutionResult
from graphql.type import GraphQLSchema
from sentry_sdk._types import Event


Expand Down
70 changes: 19 additions & 51 deletions sentry_sdk/integrations/strawberry.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@
raise DidNotEnable("strawberry-graphql integration requires Python 3.8 or newer")

try:
import strawberry.schema.schema as strawberry_schema # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

so glad this is gone :D

from strawberry import Schema
from strawberry.extensions import SchemaExtension # type: ignore
from strawberry.extensions.tracing.utils import should_skip_tracing as strawberry_should_skip_tracing # type: ignore
from strawberry.http import async_base_view, sync_base_view # type: ignore
from strawberry.extensions import SchemaExtension
from strawberry.extensions.tracing.utils import (
should_skip_tracing as strawberry_should_skip_tracing,
)
from strawberry.http import async_base_view, sync_base_view
except ImportError:
raise DidNotEnable("strawberry-graphql is not installed")

try:
from strawberry.extensions.tracing import ( # type: ignore
from strawberry.extensions.tracing import (
SentryTracingExtension as StrawberrySentryAsyncExtension,
SentryTracingExtensionSync as StrawberrySentrySyncExtension,
)
Expand All @@ -47,10 +48,10 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Any, Callable, Generator, List, Optional, Union
from graphql import GraphQLError, GraphQLResolveInfo # type: ignore
from typing import Any, Callable, Generator, List, Optional
from graphql import GraphQLError, GraphQLResolveInfo
from strawberry.http import GraphQLHTTPResponse
from strawberry.types import ExecutionContext, ExecutionResult, SubscriptionExecutionResult # type: ignore
from strawberry.types import ExecutionContext
from sentry_sdk._types import Event, EventProcessor


Expand Down Expand Up @@ -78,7 +79,6 @@ def setup_once():
_check_minimum_version(StrawberryIntegration, version, "strawberry-graphql")

_patch_schema_init()
_patch_execute()
_patch_views()


Expand Down Expand Up @@ -124,10 +124,10 @@ def _sentry_patched_schema_init(self, *args, **kwargs):

return old_schema_init(self, *args, **kwargs)

Schema.__init__ = _sentry_patched_schema_init
Schema.__init__ = _sentry_patched_schema_init # type: ignore[method-assign]


class SentryAsyncExtension(SchemaExtension): # type: ignore
class SentryAsyncExtension(SchemaExtension):
def __init__(
self,
*,
Expand All @@ -140,7 +140,7 @@ def __init__(
@cached_property
def _resource_name(self):
# type: () -> str
query_hash = self.hash_query(self.execution_context.query)
query_hash = self.hash_query(self.execution_context.query) # type: ignore

if self.execution_context.operation_name:
return "{}:{}".format(self.execution_context.operation_name, query_hash)
Expand Down Expand Up @@ -180,6 +180,10 @@ def on_operation(self):
},
)

scope = sentry_sdk.get_isolation_scope()
event_processor = _make_request_event_processor(self.execution_context)
scope.add_event_processor(event_processor)

span = sentry_sdk.get_current_span()
if span:
self.graphql_span = span.start_child(
Expand Down Expand Up @@ -287,41 +291,6 @@ def resolve(self, _next, root, info, *args, **kwargs):
return _next(root, info, *args, **kwargs)


def _patch_execute():
# type: () -> None
old_execute_async = strawberry_schema.execute
old_execute_sync = strawberry_schema.execute_sync

async def _sentry_patched_execute_async(*args, **kwargs):
# type: (Any, Any) -> Union[ExecutionResult, SubscriptionExecutionResult]
result = await old_execute_async(*args, **kwargs)

if sentry_sdk.get_client().get_integration(StrawberryIntegration) is None:
return result

if "execution_context" in kwargs:
scope = sentry_sdk.get_isolation_scope()
event_processor = _make_request_event_processor(kwargs["execution_context"])
scope.add_event_processor(event_processor)

return result

@ensure_integration_enabled(StrawberryIntegration, old_execute_sync)
def _sentry_patched_execute_sync(*args, **kwargs):
# type: (Any, Any) -> ExecutionResult
result = old_execute_sync(*args, **kwargs)

if "execution_context" in kwargs:
scope = sentry_sdk.get_isolation_scope()
event_processor = _make_request_event_processor(kwargs["execution_context"])
scope.add_event_processor(event_processor)

return result

strawberry_schema.execute = _sentry_patched_execute_async
strawberry_schema.execute_sync = _sentry_patched_execute_sync


def _patch_views():
# type: () -> None
old_async_view_handle_errors = async_base_view.AsyncBaseHTTPView._handle_errors
Expand Down Expand Up @@ -359,10 +328,10 @@ def _sentry_patched_handle_errors(self, errors, response_data):
)
sentry_sdk.capture_event(event, hint=hint)

async_base_view.AsyncBaseHTTPView._handle_errors = (
async_base_view.AsyncBaseHTTPView._handle_errors = ( # type: ignore[method-assign]
_sentry_patched_async_view_handle_errors
)
sync_base_view.SyncBaseHTTPView._handle_errors = (
sync_base_view.SyncBaseHTTPView._handle_errors = ( # type: ignore[method-assign]
_sentry_patched_sync_view_handle_errors
)

Expand All @@ -378,8 +347,7 @@ def inner(event, hint):
request_data["api_target"] = "graphql"

if not request_data.get("data"):
data = {"query": execution_context.query}

data = {"query": execution_context.query} # type: dict[str, Any]
if execution_context.variables:
data["variables"] = execution_context.variables
if execution_context.operation_name:
Expand Down
Loading