Skip to content

Commit d0db5af

Browse files
authored
Merge branch 'master' into ivana/delayed-asynciointegration-enable
2 parents 0193dea + de7854e commit d0db5af

File tree

8 files changed

+80
-48
lines changed

8 files changed

+80
-48
lines changed

sentry_sdk/integrations/clickhouse_driver.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ def __getitem__(self, _):
3030

3131

3232
try:
33-
import clickhouse_driver # type: ignore[import-not-found]
33+
from clickhouse_driver import VERSION # type: ignore[import-not-found]
34+
from clickhouse_driver.client import Client # type: ignore[import-not-found]
35+
from clickhouse_driver.connection import Connection # type: ignore[import-not-found]
3436

3537
except ImportError:
3638
raise DidNotEnable("clickhouse-driver not installed.")
@@ -42,29 +44,23 @@ class ClickhouseDriverIntegration(Integration):
4244

4345
@staticmethod
4446
def setup_once() -> None:
45-
_check_minimum_version(ClickhouseDriverIntegration, clickhouse_driver.VERSION)
47+
_check_minimum_version(ClickhouseDriverIntegration, VERSION)
4648

4749
# Every query is done using the Connection's `send_query` function
48-
clickhouse_driver.connection.Connection.send_query = _wrap_start(
49-
clickhouse_driver.connection.Connection.send_query
50-
)
50+
Connection.send_query = _wrap_start(Connection.send_query)
5151

5252
# If the query contains parameters then the send_data function is used to send those parameters to clickhouse
5353
_wrap_send_data()
5454

5555
# Every query ends either with the Client's `receive_end_of_query` (no result expected)
5656
# or its `receive_result` (result expected)
57-
clickhouse_driver.client.Client.receive_end_of_query = _wrap_end(
58-
clickhouse_driver.client.Client.receive_end_of_query
59-
)
60-
if hasattr(clickhouse_driver.client.Client, "receive_end_of_insert_query"):
57+
Client.receive_end_of_query = _wrap_end(Client.receive_end_of_query)
58+
if hasattr(Client, "receive_end_of_insert_query"):
6159
# In 0.2.7, insert queries are handled separately via `receive_end_of_insert_query`
62-
clickhouse_driver.client.Client.receive_end_of_insert_query = _wrap_end(
63-
clickhouse_driver.client.Client.receive_end_of_insert_query
60+
Client.receive_end_of_insert_query = _wrap_end(
61+
Client.receive_end_of_insert_query
6462
)
65-
clickhouse_driver.client.Client.receive_result = _wrap_end(
66-
clickhouse_driver.client.Client.receive_result
67-
)
63+
Client.receive_result = _wrap_end(Client.receive_result)
6864

6965

7066
P = ParamSpec("P")
@@ -128,7 +124,7 @@ def _inner_end(*args: "P.args", **kwargs: "P.kwargs") -> "T":
128124

129125

130126
def _wrap_send_data() -> None:
131-
original_send_data = clickhouse_driver.client.Client.send_data
127+
original_send_data = Client.send_data
132128

133129
def _inner_send_data( # type: ignore[no-untyped-def] # clickhouse-driver does not type send_data
134130
self, sample_block, data, types_check=False, columnar=False, *args, **kwargs
@@ -164,12 +160,10 @@ def wrapped_generator() -> "Iterator[Any]":
164160
self, sample_block, data, types_check, columnar, *args, **kwargs
165161
)
166162

167-
clickhouse_driver.client.Client.send_data = _inner_send_data
163+
Client.send_data = _inner_send_data
168164

169165

170-
def _set_db_data(
171-
span: "Span", connection: "clickhouse_driver.connection.Connection"
172-
) -> None:
166+
def _set_db_data(span: "Span", connection: "Connection") -> None:
173167
span.set_data(SPANDATA.DB_SYSTEM, "clickhouse")
174168
span.set_data(SPANDATA.SERVER_ADDRESS, connection.host)
175169
span.set_data(SPANDATA.SERVER_PORT, connection.port)

sentry_sdk/integrations/gql.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,23 @@ def _request_info_from_transport(
9595
def _patch_execute() -> None:
9696
real_execute = gql.Client.execute
9797

98+
# Maintain signature for backwards compatibility.
99+
# gql.Client.execute() accepts a positional-only "request"
100+
# parameter with version 4.0.0.
98101
@ensure_integration_enabled(GQLIntegration, real_execute)
99102
def sentry_patched_execute(
100103
self: "gql.Client",
101-
document_or_request: "DocumentNode",
104+
document: "DocumentNode",
102105
*args: "Any",
103106
**kwargs: "Any",
104107
) -> "Any":
105108
scope = sentry_sdk.get_isolation_scope()
106-
scope.add_event_processor(_make_gql_event_processor(self, document_or_request))
109+
# document is a gql.GraphQLRequest with gql v4.0.0.
110+
scope.add_event_processor(_make_gql_event_processor(self, document))
107111

108112
try:
109-
return real_execute(self, document_or_request, *args, **kwargs)
113+
# document is a gql.GraphQLRequest with gql v4.0.0.
114+
return real_execute(self, document, *args, **kwargs)
110115
except TransportQueryError as e:
111116
event, hint = event_from_exception(
112117
e,

sentry_sdk/integrations/litellm.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
try:
2121
import litellm # type: ignore[import-not-found]
22+
from litellm import input_callback, success_callback, failure_callback
2223
except ImportError:
2324
raise DidNotEnable("LiteLLM not installed")
2425

@@ -278,14 +279,14 @@ def __init__(self: "LiteLLMIntegration", include_prompts: bool = True) -> None:
278279
@staticmethod
279280
def setup_once() -> None:
280281
"""Set up LiteLLM callbacks for monitoring."""
281-
litellm.input_callback = litellm.input_callback or []
282+
litellm.input_callback = input_callback or []
282283
if _input_callback not in litellm.input_callback:
283284
litellm.input_callback.append(_input_callback)
284285

285-
litellm.success_callback = litellm.success_callback or []
286+
litellm.success_callback = success_callback or []
286287
if _success_callback not in litellm.success_callback:
287288
litellm.success_callback.append(_success_callback)
288289

289-
litellm.failure_callback = litellm.failure_callback or []
290+
litellm.failure_callback = failure_callback or []
290291
if _failure_callback not in litellm.failure_callback:
291292
litellm.failure_callback.append(_failure_callback)

sentry_sdk/integrations/pure_eval.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
from sentry_sdk._types import Event, Hint
1616

1717
try:
18-
import executing
18+
from executing import Source
1919
except ImportError:
2020
raise DidNotEnable("executing is not installed")
2121

2222
try:
23-
import pure_eval
23+
from pure_eval import Evaluator
2424
except ImportError:
2525
raise DidNotEnable("pure_eval is not installed")
2626

@@ -81,7 +81,7 @@ def add_executing_info(
8181

8282

8383
def pure_eval_frame(frame: "FrameType") -> "Dict[str, Any]":
84-
source = executing.Source.for_frame(frame)
84+
source = Source.for_frame(frame)
8585
if not source.tree:
8686
return {}
8787

@@ -98,7 +98,7 @@ def pure_eval_frame(frame: "FrameType") -> "Dict[str, Any]":
9898
if isinstance(scope, (ast.FunctionDef, ast.ClassDef, ast.Module)):
9999
break
100100

101-
evaluator = pure_eval.Evaluator.from_frame(frame)
101+
evaluator = Evaluator.from_frame(frame)
102102
expressions = evaluator.interesting_expressions_grouped(scope)
103103

104104
def closeness(expression: "Tuple[List[Any], Any]") -> "Tuple[int, int]":

sentry_sdk/integrations/ray.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
try:
1818
import ray # type: ignore[import-not-found]
19+
from ray import remote
1920
except ImportError:
2021
raise DidNotEnable("Ray not installed.")
2122

@@ -57,7 +58,7 @@ def _insert_sentry_tracing_in_signature(func: "Callable[..., Any]") -> None:
5758

5859

5960
def _patch_ray_remote() -> None:
60-
old_remote = ray.remote
61+
old_remote = remote
6162

6263
@functools.wraps(old_remote)
6364
def new_remote(

sentry_sdk/integrations/typer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
try:
2424
import typer
25+
from typer.main import except_hook
2526
except ImportError:
2627
raise DidNotEnable("Typer not installed")
2728

@@ -31,7 +32,7 @@ class TyperIntegration(Integration):
3132

3233
@staticmethod
3334
def setup_once() -> None:
34-
typer.main.except_hook = _make_excepthook(typer.main.except_hook) # type: ignore
35+
typer.main.except_hook = _make_excepthook(except_hook) # type: ignore
3536

3637

3738
def _make_excepthook(old_excepthook: "Excepthook") -> "Excepthook":

tests/integrations/gql/test_gql.py

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
import responses
44
from gql import gql
55
from gql import Client
6+
from gql import __version__
67
from gql.transport.exceptions import TransportQueryError
78
from gql.transport.requests import RequestsHTTPTransport
89
from sentry_sdk.integrations.gql import GQLIntegration
10+
from sentry_sdk.utils import parse_version
11+
12+
GQL_VERSION = parse_version(__version__)
913

1014

1115
@responses.activate
@@ -32,7 +36,36 @@ def _execute_mock_query(response_json):
3236
return client.execute(query)
3337

3438

35-
def _make_erroneous_query(capture_events):
39+
@responses.activate
40+
def _execute_mock_query_with_keyword_document(response_json):
41+
url = "http://example.com/graphql"
42+
query_string = """
43+
query Example {
44+
example
45+
}
46+
"""
47+
48+
# Mock the GraphQL server response
49+
responses.add(
50+
method=responses.POST,
51+
url=url,
52+
json=response_json,
53+
status=200,
54+
)
55+
56+
transport = RequestsHTTPTransport(url=url)
57+
client = Client(transport=transport)
58+
query = gql(query_string)
59+
60+
return client.execute(document=query)
61+
62+
63+
_execute_query_funcs = [_execute_mock_query]
64+
if GQL_VERSION < (4,):
65+
_execute_query_funcs.append(_execute_mock_query_with_keyword_document)
66+
67+
68+
def _make_erroneous_query(capture_events, execute_query):
3669
"""
3770
Make an erroneous GraphQL query, and assert that the error was reraised, that
3871
exactly one event was recorded, and that the exception recorded was a
@@ -42,7 +75,7 @@ def _make_erroneous_query(capture_events):
4275
response_json = {"errors": ["something bad happened"]}
4376

4477
with pytest.raises(TransportQueryError):
45-
_execute_mock_query(response_json)
78+
execute_query(response_json)
4679

4780
assert len(events) == 1, (
4881
"the sdk captured %d events, but 1 event was expected" % len(events)
@@ -67,7 +100,8 @@ def test_gql_init(sentry_init):
67100
sentry_init(integrations=[GQLIntegration()])
68101

69102

70-
def test_real_gql_request_no_error(sentry_init, capture_events):
103+
@pytest.mark.parametrize("execute_query", _execute_query_funcs)
104+
def test_real_gql_request_no_error(sentry_init, capture_events, execute_query):
71105
"""
72106
Integration test verifying that the GQLIntegration works as expected with successful query.
73107
"""
@@ -77,7 +111,7 @@ def test_real_gql_request_no_error(sentry_init, capture_events):
77111
response_data = {"example": "This is the example"}
78112
response_json = {"data": response_data}
79113

80-
result = _execute_mock_query(response_json)
114+
result = execute_query(response_json)
81115

82116
assert result == response_data, (
83117
"client.execute returned a different value from what it received from the server"
@@ -87,27 +121,31 @@ def test_real_gql_request_no_error(sentry_init, capture_events):
87121
)
88122

89123

90-
def test_real_gql_request_with_error_no_pii(sentry_init, capture_events):
124+
@pytest.mark.parametrize("execute_query", _execute_query_funcs)
125+
def test_real_gql_request_with_error_no_pii(sentry_init, capture_events, execute_query):
91126
"""
92127
Integration test verifying that the GQLIntegration works as expected with query resulting
93128
in a GraphQL error, and that PII is not sent.
94129
"""
95130
sentry_init(integrations=[GQLIntegration()])
96131

97-
event = _make_erroneous_query(capture_events)
132+
event = _make_erroneous_query(capture_events, execute_query)
98133

99134
assert "data" not in event["request"]
100135
assert "response" not in event["contexts"]
101136

102137

103-
def test_real_gql_request_with_error_with_pii(sentry_init, capture_events):
138+
@pytest.mark.parametrize("execute_query", _execute_query_funcs)
139+
def test_real_gql_request_with_error_with_pii(
140+
sentry_init, capture_events, execute_query
141+
):
104142
"""
105143
Integration test verifying that the GQLIntegration works as expected with query resulting
106144
in a GraphQL error, and that PII is not sent.
107145
"""
108146
sentry_init(integrations=[GQLIntegration()], send_default_pii=True)
109147

110-
event = _make_erroneous_query(capture_events)
148+
event = _make_erroneous_query(capture_events, execute_query)
111149

112150
assert "data" in event["request"]
113151
assert "response" in event["contexts"]

tests/test_shadowed_module.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,7 @@ def pytest_generate_tests(metafunc):
2626

2727
metafunc.parametrize(
2828
"integration_submodule_name",
29-
# Temporarily skip some integrations
30-
submodule_names
31-
- {
32-
"clickhouse_driver",
33-
"litellm",
34-
"pure_eval",
35-
"ray",
36-
"typer",
37-
},
29+
submodule_names,
3830
)
3931

4032

0 commit comments

Comments
 (0)