Skip to content

Commit 0cde760

Browse files
committed
typing etc.
1 parent 1412ad9 commit 0cde760

File tree

4 files changed

+196
-64
lines changed

4 files changed

+196
-64
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import AriadneIntegration, GrapheneIntegration # noqa
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from sentry_sdk.hub import Hub, _should_send_default_pii
2+
from sentry_sdk.integrations import DidNotEnable, Integration
3+
from sentry_sdk.utils import parse_version
4+
from sentry_sdk._types import TYPE_CHECKING
5+
6+
try:
7+
from graphql import version as GRAPHQL_CORE_VERSION
8+
except ImportError:
9+
raise DidNotEnable("graphql-core not installed")
10+
11+
try:
12+
import ariadne
13+
except ImportError:
14+
raise DidNotEnable("ariadne not installed")
15+
16+
17+
if TYPE_CHECKING:
18+
from typing import Any
19+
from ariadne.graphql import GraphQLSchema
20+
from ariadne.types import GraphQLResult
21+
from sentry_sdk._types import EventProcessor
22+
23+
24+
class AriadneIntegration(Integration):
25+
identifier = "ariadne"
26+
27+
@staticmethod
28+
def setup_once():
29+
# type: () -> None
30+
# XXX version guard for ariadne
31+
# guard for double patching
32+
version = parse_version(GRAPHQL_CORE_VERSION)
33+
34+
if version is None:
35+
raise DidNotEnable(
36+
"Unparsable graphql-core version: {}".format(GRAPHQL_CORE_VERSION)
37+
)
38+
39+
if version < (3, 2):
40+
raise DidNotEnable("graphql-core 3.2 or newer required.")
41+
42+
old_graphql_sync = ariadne.graphql_sync
43+
old_graphql_async = ariadne.graphql
44+
45+
def _sentry_patched_graphql_sync(schema, data, *args, **kwargs):
46+
# type: (GraphQLSchema, Any, Any, Any) -> GraphQLResult
47+
hub = Hub.current
48+
integration = hub.get_integration(AriadneIntegration)
49+
if integration is None or hub.client is None:
50+
return old_graphql_sync(schema, data, *args, **kwargs)
51+
52+
result = old_graphql_sync(schema, data, *args, **kwargs)
53+
54+
_raise_errors(result, hub)
55+
56+
return result
57+
58+
async def _sentry_patched_graphql_async(schema, data, *args, **kwargs):
59+
# type: (GraphQLSchema, Any, Any, Any) -> GraphQLResult
60+
hub = Hub.current
61+
integration = hub.get_integration(AriadneIntegration)
62+
if integration is None or hub.client is None:
63+
return await old_graphql_async(schema, data, *args, **kwargs)
64+
65+
result = await old_graphql_async(schema, data, *args, **kwargs)
66+
67+
_raise_errors(result, hub)
68+
69+
return result
70+
71+
ariadne.graphql_sync = _sentry_patched_graphql_sync
72+
ariadne.graphql_async = _sentry_patched_graphql_async
73+
74+
75+
def _raise_errors(result, hub):
76+
# type: (GraphQLResult, Hub) -> None
77+
data = result[1]
78+
if not isinstance(data, dict) or not data.get("errors"):
79+
return result
80+
81+
for error in data["errors"]:
82+
hub.capture_exception(error)
83+
84+
85+
def _make_event_processor():
86+
# type: () -> EventProcessor
87+
def inner(event, hint):
88+
if _should_send_default_pii():
89+
pass
90+
91+
return event
92+
93+
return inner
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
from sentry_sdk.hub import Hub, _should_send_default_pii
2+
from sentry_sdk.integrations import DidNotEnable, Integration
3+
from sentry_sdk.utils import parse_version
4+
from sentry_sdk._types import TYPE_CHECKING
5+
6+
try:
7+
from graphql import version as GRAPHQL_CORE_VERSION
8+
except ImportError:
9+
raise DidNotEnable("graphql-core not installed")
10+
11+
12+
try:
13+
from graphql import schema as graphene_schema
14+
except ImportError:
15+
raise DidNotEnable("graphene not installed")
16+
17+
18+
if TYPE_CHECKING:
19+
from typing import Any, Union
20+
from graphene.language.source import Source
21+
from graphql.execution import ExecutionResult
22+
from graphql.type import GraphQLSchema
23+
from sentry_sdk._types import EventProcessor
24+
25+
26+
class GrapheneIntegration(Integration):
27+
identifier = "graphene"
28+
29+
@staticmethod
30+
def setup_once():
31+
# type: () -> None
32+
# XXX version guard for graphene
33+
version = parse_version(GRAPHQL_CORE_VERSION)
34+
35+
if version is None:
36+
raise DidNotEnable(
37+
"Unparsable graphql-core version: {}".format(GRAPHQL_CORE_VERSION)
38+
)
39+
40+
if version < (3, 2):
41+
raise DidNotEnable("graphql-core 3.2 or newer required.")
42+
43+
# XXX: a guard against patching multiple times?
44+
old_execute_sync = graphene_schema.graphql_sync
45+
old_execute_async = graphene_schema.graphql
46+
47+
def _sentry_patched_graphql_sync(schema, source, *args, **kwargs):
48+
# type: (GraphQLSchema, Union[str, Source], Any, Any) -> ExecutionResult
49+
hub = Hub.current
50+
integration = hub.get_integration(GrapheneIntegration)
51+
if integration is None or hub.client is None:
52+
return old_execute_sync(schema, source, *args, **kwargs)
53+
54+
scope = hub.scope # XXX
55+
if scope is not None:
56+
event_processor = _make_event_processor(source)
57+
scope.add_event_processor(event_processor)
58+
59+
result = old_execute_sync(schema, source, *args, **kwargs)
60+
61+
_raise_graphql_errors(result)
62+
63+
return result
64+
65+
async def _sentry_patched_graphql_async(schema, source, *args, **kwargs):
66+
# type: (GraphQLSchema, Union[str, Source], Any, Any) -> ExecutionResult
67+
hub = Hub.current
68+
integration = hub.get_integration(GrapheneIntegration)
69+
if integration is None or hub.client is None:
70+
return await old_execute_async(schema, source, *args, **kwargs)
71+
72+
scope = hub.scope # XXX
73+
if scope is not None:
74+
event_processor = _make_event_processor(source)
75+
scope.add_event_processor(event_processor)
76+
77+
result = await old_execute_async(schema, source, *args, **kwargs)
78+
79+
_raise_graphql_errors(result)
80+
81+
return result
82+
83+
graphene_schema.graphql_sync = _sentry_patched_graphql_sync
84+
graphene_schema.graphql = _sentry_patched_graphql_async
85+
86+
87+
def _raise_graphql_errors(result, hub):
88+
# type: (ExecutionResult, Hub) -> None
89+
for error in result.errors or []:
90+
hub.capture_exception(error)
91+
92+
93+
def _make_event_processor(source):
94+
# type: (Source) -> EventProcessor
95+
def inner(event, hint):
96+
if _should_send_default_pii():
97+
request_info = event.setdefault("request", {})
98+
request_info["data"] = str(source)
99+
100+
return event
101+
102+
return inner

sentry_sdk/integrations/graphql/server.py

Lines changed: 0 additions & 64 deletions
This file was deleted.

0 commit comments

Comments
 (0)