Skip to content

Commit 82324c8

Browse files
committed
formatting
1 parent 17c60dd commit 82324c8

6 files changed

+391
-179
lines changed

ddtrace/contrib/internal/graphql/patch.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import re
33
import sys
4+
import traceback
45
from typing import TYPE_CHECKING
56
from typing import List
67

@@ -26,6 +27,7 @@
2627
from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY
2728
from ddtrace.constants import _SPAN_MEASURED_KEY
2829
from ddtrace.constants import ERROR_MSG
30+
from ddtrace.constants import ERROR_STACK
2931
from ddtrace.constants import ERROR_TYPE
3032
from ddtrace.contrib import trace_utils
3133
from ddtrace.ext import SpanTypes
@@ -302,6 +304,31 @@ def _set_span_errors(errors: List[GraphQLError], span: Span) -> None:
302304
# we will not set the error.stack tag on graphql spans. Setting only one traceback
303305
# could be misleading and might obfuscate errors.
304306
span.set_tag_str(ERROR_MSG, error_msgs)
307+
for error in errors:
308+
locations = " ".join(f"{loc.formatted['line']}:{loc.formatted['column']}" for loc in error.locations)
309+
attributes = {
310+
"message": error.message,
311+
"type": span.get_tag("error.type"),
312+
"locations": locations,
313+
}
314+
315+
if error.__traceback__:
316+
stacktrace = "".join(
317+
traceback.format_exception(
318+
type(error), error, error.__traceback__, limit=config._span_traceback_max_size
319+
)
320+
)
321+
attributes["stacktrace"] = stacktrace
322+
span.set_tag_str(ERROR_STACK, stacktrace)
323+
324+
if error.path is not None:
325+
path = ",".join([str(path_obj) for path_obj in error.path])
326+
attributes["path"] = path
327+
328+
span._add_event(
329+
name="dd.graphql.query.error",
330+
attributes=attributes,
331+
)
305332

306333

307334
def _set_span_operation_tags(span, document):

tests/contrib/graphene/test_graphene.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ async def test_schema_execute_async_with_resolvers(test_schema, test_source_str,
9595

9696

9797
@pytest.mark.snapshot(
98-
ignores=["meta.error.stack"], variants={"v2": graphene.VERSION < (3,), "": graphene.VERSION >= (3,)}
98+
ignores=["meta.error.stack", "meta.events"], variants={"v2": graphene.VERSION < (3,), "": graphene.VERSION >= (3,)}
9999
)
100100
def test_schema_failing_execute(failing_schema, test_source_str, enable_graphql_resolvers):
101101
result = failing_schema.execute(test_source_str)

tests/contrib/graphql/test_graphql.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import os
22

33
import graphql
4+
from graphql import build_schema
5+
from graphql import graphql_sync
46
import pytest
57

68
from ddtrace.contrib.internal.graphql.patch import _graphql_version as graphql_version
@@ -73,13 +75,48 @@ async def test_graphql_with_traced_resolver(test_schema, test_source_str, snapsh
7375
assert result.data == {"hello": "friend"}
7476

7577

78+
def resolve_fail(root, info):
79+
undefined_var = None
80+
return undefined_var.property
81+
82+
83+
@snapshot(ignores=["meta.error.stack", "meta.events"])
84+
def test_graphql_fail(enable_graphql_resolvers):
85+
query = """
86+
query {
87+
fail
88+
}
89+
"""
90+
91+
resolvers = {
92+
"Query": {
93+
"fail": resolve_fail,
94+
}
95+
}
96+
schema_definition = """
97+
type Query {
98+
fail: String
99+
}
100+
"""
101+
102+
test_schema = build_schema(schema_definition)
103+
result = graphql_sync(
104+
test_schema, query, root_value=None, field_resolver=lambda _type, _field: resolvers[_type.name][_field.name]
105+
)
106+
107+
assert result.errors is not None
108+
assert len(result.errors) == 1
109+
assert isinstance(result.errors[0], graphql.error.GraphQLError)
110+
assert "'NoneType' object has no attribute 'name'" in result.errors[0].message
111+
112+
76113
@pytest.mark.asyncio
77114
async def test_graphql_error(test_schema, snapshot_context):
78-
with snapshot_context(ignores=["meta.error.type", "meta.error.message"]):
115+
with snapshot_context(ignores=["meta.error.type", "meta.error.message", "meta.events"]):
79116
if graphql_version < (3, 0):
80-
result = graphql.graphql(test_schema, "{ invalid_schema }")
117+
result = graphql.graphql(test_schema, "query my_query{ invalid_schema }")
81118
else:
82-
result = await graphql.graphql(test_schema, "{ invalid_schema }")
119+
result = await graphql.graphql(test_schema, "query my_query{ invalid_schema }")
83120
assert len(result.errors) == 1
84121
assert isinstance(result.errors[0], graphql.error.GraphQLError)
85122
assert "Cannot query field" in result.errors[0].message
@@ -99,7 +136,7 @@ def test_graphql_v2_promise(test_schema, test_source_str):
99136
)
100137
@pytest.mark.skipif(graphql_version >= (3, 0), reason="graphql.graphql is NOT async in v2.0")
101138
def test_graphql_error_v2_promise(test_schema):
102-
promise = graphql.graphql(test_schema, "{ invalid_schema }", return_promise=True)
139+
promise = graphql.graphql(test_schema, "query my_query{ invalid_schema }", return_promise=True)
103140
result = promise.get()
104141
assert len(result.errors) == 1
105142
assert isinstance(result.errors[0], graphql.error.GraphQLError)
Lines changed: 111 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,113 @@
1-
[[
2-
{
3-
"name": "graphql.request",
4-
"service": "graphql",
5-
"resource": "{ patron { id name age } }",
6-
"trace_id": 0,
7-
"span_id": 1,
8-
"parent_id": 0,
9-
"type": "graphql",
10-
"error": 1,
11-
"meta": {
12-
"_dd.base_service": "tests.contrib.graphene",
13-
"_dd.p.dm": "-0",
14-
"_dd.p.tid": "654a694400000000",
15-
"component": "graphql",
16-
"error.message": "exception was raised in a graphene query\n\nGraphQL request:3:7\n2 | {\n3 | patron {\n | ^\n4 | id",
17-
"error.type": "graphql.error.graphql_error.GraphQLError",
18-
"language": "python",
19-
"runtime-id": "bd29f6239b6740229c13f18d5b0d3f74"
1+
[
2+
[
3+
{
4+
"name": "graphql.request",
5+
"service": "graphql",
6+
"resource": "{ patron { id name age } }",
7+
"trace_id": 0,
8+
"span_id": 1,
9+
"parent_id": 0,
10+
"type": "graphql",
11+
"error": 1,
12+
"meta": {
13+
"_dd.base_service": "tests.contrib.graphene",
14+
"_dd.p.dm": "-0",
15+
"_dd.p.tid": "679ba78900000000",
16+
"component": "graphql",
17+
"error.message": "exception was raised in a graphene query\n\nGraphQL request:3:7\n2 | {\n3 | patron {\n | ^\n4 | id",
18+
"error.stack": "Traceback (most recent call last):\n File \"/Users/quinna.halim/dd-trace-py/.riot/venv_py31013_mock_pytest_pytest-mock_coverage_pytest-cov_opentracing_hypothesis6451_graphene~300_pytest-asyncio0211_graphql-relay_pytest-randomly/lib/python3.10/site-packages/graphql/execution/execute.py\", line 617, in resolve_field\n result = resolve_fn(source, info, **args)\n File \"/Users/quinna.halim/dd-trace-py/ddtrace/contrib/internal/graphql/patch.py\", line 242, in _resolver_middleware\n return next_middleware(root, info, **args)\n File \"/Users/quinna.halim/dd-trace-py/tests/contrib/graphene/test_graphene.py\", line 26, in resolve_patron\n raise Exception(\"exception was raised in a graphene query\")\ngraphql.error.graphql_error.GraphQLError: exception was raised in a graphene query\n\nGraphQL request:3:7\n2 | {\n3 | patron {\n | ^\n4 | id\n",
19+
"error.type": "graphql.error.graphql_error.GraphQLError",
20+
"events": "[{\"name\": \"dd.graphql.query.error\", \"time_unix_nano\": 1738254217957740000, \"attributes\": {\"message\": \"exception was raised in a graphene query\", \"type\": \"graphql.error.graphql_error.GraphQLError\", \"locations\": \"3:7\", \"stacktrace\": \"Traceback (most recent call last):\\n File \\\"/Users/quinna.halim/dd-trace-py/.riot/venv_py31013_mock_pytest_pytest-mock_coverage_pytest-cov_opentracing_hypothesis6451_graphene~300_pytest-asyncio0211_graphql-relay_pytest-randomly/lib/python3.10/site-packages/graphql/execution/execute.py\\\", line 617, in resolve_field\\n result = resolve_fn(source, info, **args)\\n File \\\"/Users/quinna.halim/dd-trace-py/ddtrace/contrib/internal/graphql/patch.py\\\", line 242, in _resolver_middleware\\n return next_middleware(root, info, **args)\\n File \\\"/Users/quinna.halim/dd-trace-py/tests/contrib/graphene/test_graphene.py\\\", line 26, in resolve_patron\\n raise Exception(\\\"exception was raised in a graphene query\\\")\\ngraphql.error.graphql_error.GraphQLError: exception was raised in a graphene query\\n\\nGraphQL request:3:7\\n2 | {\\n3 | patron {\\n | ^\\n4 | id\\n\", \"path\": \"patron\"}}]",
21+
"language": "python",
22+
"runtime-id": "8203164c8f8a4840943bf798c4daea9a"
23+
},
24+
"metrics": {
25+
"_dd.measured": 1,
26+
"_dd.top_level": 1,
27+
"_dd.tracer_kr": 1.0,
28+
"_sampling_priority_v1": 1,
29+
"process_id": 62451
30+
},
31+
"duration": 5396000,
32+
"start": 1738254217952345000
2033
},
21-
"metrics": {
22-
"_dd.measured": 1,
23-
"_dd.top_level": 1,
24-
"_dd.tracer_kr": 1.0,
25-
"_sampling_priority_v1": 1,
26-
"process_id": 47948
34+
{
35+
"name": "graphql.parse",
36+
"service": "graphql",
37+
"resource": "graphql.parse",
38+
"trace_id": 0,
39+
"span_id": 2,
40+
"parent_id": 1,
41+
"type": "graphql",
42+
"error": 0,
43+
"meta": {
44+
"_dd.base_service": "tests.contrib.graphene",
45+
"component": "graphql",
46+
"graphql.source": "{ patron { id name age } }"
47+
},
48+
"duration": 828000,
49+
"start": 1738254217952815000
2750
},
28-
"duration": 3427167,
29-
"start": 1692710307375136045
30-
},
31-
{
32-
"name": "graphql.parse",
33-
"service": "graphql",
34-
"resource": "graphql.parse",
35-
"trace_id": 0,
36-
"span_id": 2,
37-
"parent_id": 1,
38-
"type": "graphql",
39-
"error": 0,
40-
"meta": {
41-
"_dd.base_service": "tests.contrib.graphene",
42-
"_dd.p.tid": "654a694400000000",
43-
"component": "graphql",
44-
"graphql.source": "{ patron { id name age } }"
45-
},
46-
"duration": 140959,
47-
"start": 1692710307375365003
48-
},
49-
{
50-
"name": "graphql.validate",
51-
"service": "graphql",
52-
"resource": "graphql.validate",
53-
"trace_id": 0,
54-
"span_id": 3,
55-
"parent_id": 1,
56-
"type": "graphql",
57-
"error": 0,
58-
"meta": {
59-
"_dd.base_service": "tests.contrib.graphene",
60-
"_dd.p.tid": "654a694400000000",
61-
"component": "graphql",
62-
"graphql.source": "{ patron { id name age } }"
63-
},
64-
"duration": 1062625,
65-
"start": 1692710307375544295
66-
},
67-
{
68-
"name": "graphql.execute",
69-
"service": "graphql",
70-
"resource": "{ patron { id name age } }",
71-
"trace_id": 0,
72-
"span_id": 4,
73-
"parent_id": 1,
74-
"type": "graphql",
75-
"error": 1,
76-
"meta": {
77-
"_dd.base_service": "tests.contrib.graphene",
78-
"_dd.p.tid": "654a694400000000",
79-
"component": "graphql",
80-
"error.message": "exception was raised in a graphene query\n\nGraphQL request:3:7\n2 | {\n3 | patron {\n | ^\n4 | id",
81-
"error.type": "graphql.error.graphql_error.GraphQLError",
82-
"graphql.operation.type": "query",
83-
"graphql.source": "{ patron { id name age } }"
84-
},
85-
"metrics": {
86-
"_dd.measured": 1
87-
},
88-
"duration": 1875416,
89-
"start": 1692710307376651212
90-
},
91-
{
92-
"name": "graphql.resolve",
93-
"service": "graphql",
94-
"resource": "patron",
95-
"trace_id": 0,
96-
"span_id": 5,
97-
"parent_id": 4,
98-
"type": "graphql",
99-
"error": 1,
100-
"meta": {
101-
"_dd.base_service": "tests.contrib.graphene",
102-
"_dd.p.tid": "654a694400000000",
103-
"component": "graphql",
104-
"error.message": "exception was raised in a graphene query",
105-
"error.stack": "Traceback (most recent call last):\n File \"/root/project/ddtrace/contrib/graphql/patch.py\", line 236, in _resolver_middleware\n return next_middleware(root, info, **args)\n File \"/root/project/tests/contrib/graphene/test_graphene.py\", line 26, in resolve_patron\n raise Exception(\"exception was raised in a graphene query\")\nException: exception was raised in a graphene query\n",
106-
"error.type": "builtins.Exception"
107-
},
108-
"duration": 1716208,
109-
"start": 1692710307376713212
110-
}]]
51+
{
52+
"name": "graphql.validate",
53+
"service": "graphql",
54+
"resource": "graphql.validate",
55+
"trace_id": 0,
56+
"span_id": 3,
57+
"parent_id": 1,
58+
"type": "graphql",
59+
"error": 0,
60+
"meta": {
61+
"_dd.base_service": "tests.contrib.graphene",
62+
"component": "graphql",
63+
"graphql.source": "{ patron { id name age } }"
64+
},
65+
"duration": 2534000,
66+
"start": 1738254217954222000
67+
},
68+
{
69+
"name": "graphql.execute",
70+
"service": "graphql",
71+
"resource": "{ patron { id name age } }",
72+
"trace_id": 0,
73+
"span_id": 4,
74+
"parent_id": 1,
75+
"type": "graphql",
76+
"error": 1,
77+
"meta": {
78+
"_dd.base_service": "tests.contrib.graphene",
79+
"component": "graphql",
80+
"error.message": "exception was raised in a graphene query\n\nGraphQL request:3:7\n2 | {\n3 | patron {\n | ^\n4 | id",
81+
"error.stack": "Traceback (most recent call last):\n File \"/Users/quinna.halim/dd-trace-py/.riot/venv_py31013_mock_pytest_pytest-mock_coverage_pytest-cov_opentracing_hypothesis6451_graphene~300_pytest-asyncio0211_graphql-relay_pytest-randomly/lib/python3.10/site-packages/graphql/execution/execute.py\", line 617, in resolve_field\n result = resolve_fn(source, info, **args)\n File \"/Users/quinna.halim/dd-trace-py/ddtrace/contrib/internal/graphql/patch.py\", line 242, in _resolver_middleware\n return next_middleware(root, info, **args)\n File \"/Users/quinna.halim/dd-trace-py/tests/contrib/graphene/test_graphene.py\", line 26, in resolve_patron\n raise Exception(\"exception was raised in a graphene query\")\ngraphql.error.graphql_error.GraphQLError: exception was raised in a graphene query\n\nGraphQL request:3:7\n2 | {\n3 | patron {\n | ^\n4 | id\n",
82+
"error.type": "graphql.error.graphql_error.GraphQLError",
83+
"events": "[{\"name\": \"dd.graphql.query.error\", \"time_unix_nano\": 1738254217957645000, \"attributes\": {\"message\": \"exception was raised in a graphene query\", \"type\": \"graphql.error.graphql_error.GraphQLError\", \"locations\": \"3:7\", \"stacktrace\": \"Traceback (most recent call last):\\n File \\\"/Users/quinna.halim/dd-trace-py/.riot/venv_py31013_mock_pytest_pytest-mock_coverage_pytest-cov_opentracing_hypothesis6451_graphene~300_pytest-asyncio0211_graphql-relay_pytest-randomly/lib/python3.10/site-packages/graphql/execution/execute.py\\\", line 617, in resolve_field\\n result = resolve_fn(source, info, **args)\\n File \\\"/Users/quinna.halim/dd-trace-py/ddtrace/contrib/internal/graphql/patch.py\\\", line 242, in _resolver_middleware\\n return next_middleware(root, info, **args)\\n File \\\"/Users/quinna.halim/dd-trace-py/tests/contrib/graphene/test_graphene.py\\\", line 26, in resolve_patron\\n raise Exception(\\\"exception was raised in a graphene query\\\")\\ngraphql.error.graphql_error.GraphQLError: exception was raised in a graphene query\\n\\nGraphQL request:3:7\\n2 | {\\n3 | patron {\\n | ^\\n4 | id\\n\", \"path\": \"patron\"}}]",
84+
"graphql.operation.type": "query",
85+
"graphql.source": "{ patron { id name age } }"
86+
},
87+
"metrics": {
88+
"_dd.measured": 1
89+
},
90+
"duration": 803000,
91+
"start": 1738254217956843000
92+
},
93+
{
94+
"name": "graphql.resolve",
95+
"service": "graphql",
96+
"resource": "patron",
97+
"trace_id": 0,
98+
"span_id": 5,
99+
"parent_id": 4,
100+
"type": "graphql",
101+
"error": 1,
102+
"meta": {
103+
"_dd.base_service": "tests.contrib.graphene",
104+
"component": "graphql",
105+
"error.message": "exception was raised in a graphene query",
106+
"error.stack": "Traceback (most recent call last):\n File \"/Users/quinna.halim/dd-trace-py/ddtrace/contrib/internal/graphql/patch.py\", line 242, in _resolver_middleware\n return next_middleware(root, info, **args)\n File \"/Users/quinna.halim/dd-trace-py/tests/contrib/graphene/test_graphene.py\", line 26, in resolve_patron\n raise Exception(\"exception was raised in a graphene query\")\nException: exception was raised in a graphene query\n",
107+
"error.type": "builtins.Exception"
108+
},
109+
"duration": 430000,
110+
"start": 1738254217956914000
111+
}
112+
]
113+
]

0 commit comments

Comments
 (0)