Skip to content

Commit 6ab4145

Browse files
author
Sergio García Prado
committed
ISSUE #315
* Improve logging strategy.
1 parent fa7b421 commit 6ab4145

File tree

2 files changed

+70
-38
lines changed

2 files changed

+70
-38
lines changed

packages/plugins/minos-router-graphql/minos/plugins/graphql/handlers.py

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from graphql import (
88
ExecutionResult,
9+
GraphQLError,
910
GraphQLSchema,
1011
graphql,
1112
print_schema,
@@ -53,30 +54,41 @@ async def _build_graphql_arguments(request: Request) -> dict[str, Any]:
5354

5455
return {"source": source, "variable_values": variables}
5556

56-
@staticmethod
57-
def _build_response_from_graphql(result: ExecutionResult) -> Response:
58-
errors = result.errors
59-
if errors is None:
60-
errors = list()
61-
62-
status = 200
57+
def _build_response_from_graphql(self, result: ExecutionResult) -> Response:
58+
content = {"data": result.data}
59+
if result.errors is not None:
60+
content["errors"] = [err.message for err in result.errors]
61+
self._log_errors(result.errors)
6362

64-
if len(errors):
65-
status = 500
66-
for error in errors:
67-
if error.original_error is None:
68-
logger.error(f"Raised an graphql exception:\n {error.formatted}")
69-
else:
63+
status = self._get_status(result)
7064

71-
if isinstance(error.original_error, ResponseException):
72-
status = error.original_error.status
73-
74-
error_trace = "".join(traceback.format_tb(error.original_error.__traceback__))
75-
logger.exception(f"Raised a system exception:\n {error_trace}")
65+
return Response(content, status=status)
7666

77-
content = {"data": result.data, "errors": [err.message for err in errors]}
67+
@staticmethod
68+
def _get_status(result: ExecutionResult) -> int:
69+
status = 200
70+
for error in result.errors or []:
71+
if error.original_error is None:
72+
current = 400
73+
elif isinstance(error.original_error, ResponseException):
74+
current = error.original_error.status
75+
else:
76+
current = 500
77+
status = max(status, current)
78+
return status
7879

79-
return Response(content, status=status)
80+
@staticmethod
81+
def _log_errors(errors: list[GraphQLError]) -> None:
82+
for error in errors:
83+
if error.original_error is None:
84+
tb = repr(error)
85+
else:
86+
tb = "".join(traceback.format_tb(error.__traceback__))
87+
88+
if error.original_error is None or isinstance(error.original_error, ResponseException):
89+
logger.error(f"Raised an application exception:\n {tb}")
90+
else:
91+
logger.exception(f"Raised a system exception:\n {tb}")
8092

8193
async def get_schema(self, request: Request) -> Response:
8294
"""Get schema

packages/plugins/minos-router-graphql/tests/test_graphql/test_handlers.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ async def resolve_ticket_raises(request: Request):
4747
raise ResponseException("Some error.", status=403)
4848

4949

50+
async def resolve_ticket_raises_system(request: Request):
51+
raise ValueError()
52+
53+
5054
class TestGraphQlHandler(unittest.IsolatedAsyncioTestCase):
5155
CONFIG_FILE_PATH = BASE_PATH / "test_config.yml"
5256
_config = Config(CONFIG_FILE_PATH)
@@ -66,7 +70,8 @@ async def test_execute_operation(self):
6670
result = await handler.execute_operation(request)
6771

6872
self.assertEqual(200, result.status)
69-
self.assertDictEqual(await result.content(), {"data": {"order_query": "ticket #4"}, "errors": []})
73+
expected_content = {"data": {"order_query": "ticket #4"}}
74+
self.assertDictEqual(expected_content, await result.content())
7075

7176
async def test_execute_operation_raises(self):
7277
routes = {
@@ -83,6 +88,21 @@ async def test_execute_operation_raises(self):
8388

8489
self.assertEqual(403, result.status)
8590

91+
async def test_execute_operation_raises_system(self):
92+
routes = {
93+
GraphQlQueryEnrouteDecorator(name="ticket_query", output=GraphQLString): resolve_ticket_raises_system,
94+
}
95+
96+
schema = GraphQLSchemaBuilder.build(routes=routes)
97+
98+
handler = GraphQlHandler(schema)
99+
100+
request = InMemoryRequest(content="{ ticket_query }")
101+
102+
result = await handler.execute_operation(request)
103+
104+
self.assertEqual(500, result.status)
105+
86106
async def test_execute_wrong_operation(self):
87107
routes = {
88108
GraphQlQueryEnrouteDecorator(name="order_query", output=GraphQLString): callback_fn,
@@ -99,8 +119,8 @@ async def test_execute_wrong_operation(self):
99119

100120
content = await result.content()
101121

102-
self.assertEqual(500, result.status)
103-
self.assertNotEqual(content["errors"], [])
122+
self.assertEqual(400, result.status)
123+
self.assertEqual(1, len(content["errors"]))
104124

105125
async def test_schema(self):
106126
routes = {
@@ -148,8 +168,8 @@ async def test_query_with_variables(self):
148168
content = await result.content()
149169

150170
self.assertEqual(200, result.status)
151-
self.assertDictEqual({"order_query": 3}, content["data"])
152-
self.assertEqual([], content["errors"])
171+
expected_content = {"data": {"order_query": 3}}
172+
self.assertDictEqual(expected_content, content)
153173

154174
async def test_simple_query(self):
155175
routes = {GraphQlQueryEnrouteDecorator(name="SimpleQuery", output=GraphQLString): resolve_simple_query}
@@ -171,8 +191,8 @@ async def test_simple_query(self):
171191
content = await result.content()
172192

173193
self.assertEqual(200, result.status)
174-
self.assertDictEqual({"SimpleQuery": "ABCD"}, content["data"])
175-
self.assertEqual([], content["errors"])
194+
expected_content = {"data": {"SimpleQuery": "ABCD"}}
195+
self.assertDictEqual(expected_content, content)
176196

177197
async def test_query_with_variables_return_user(self):
178198
routes = {GraphQlQueryEnrouteDecorator(name="order_query", argument=GraphQLInt, output=user_type): resolve_user}
@@ -204,11 +224,12 @@ async def test_query_with_variables_return_user(self):
204224
content = await result.content()
205225

206226
self.assertEqual(200, result.status)
207-
self.assertDictEqual(
208-
{"order_query": {"id": "3", "firstName": "Jack", "lastName": "Johnson", "tweets": 563, "verified": True}},
209-
content["data"],
210-
)
211-
self.assertEqual([], content["errors"])
227+
expected_content = {
228+
"data": {
229+
"order_query": {"id": "3", "firstName": "Jack", "lastName": "Johnson", "tweets": 563, "verified": True}
230+
}
231+
}
232+
self.assertDictEqual(expected_content, content)
212233

213234
async def test_mutation(self):
214235
routes = {
@@ -240,19 +261,18 @@ async def test_mutation(self):
240261
content = await result.content()
241262

242263
self.assertEqual(200, result.status)
243-
self.assertDictEqual(
244-
{
264+
expected_content = {
265+
"data": {
245266
"createUser": {
246267
"id": "4kjjj43-l23k4l3-325kgaa2",
247268
"firstName": "John",
248269
"lastName": "Doe",
249270
"tweets": 42,
250271
"verified": True,
251272
}
252-
},
253-
content["data"],
254-
)
255-
self.assertEqual([], content["errors"])
273+
}
274+
}
275+
self.assertDictEqual(expected_content, content)
256276

257277

258278
if __name__ == "__main__":

0 commit comments

Comments
 (0)