Skip to content

Commit 014cb8a

Browse files
committed
feat: enrich GraphQL error logs with operation name, variables, and path
- Include operation_name and variables in partial-error warning logs - Include error path from GraphQL spec for pinpointing failed fields - Add operation_name to GraphQLClientGraphQLMultiError for full errors - Pass album_ids context for CheckAudiobookIds diagnostics
1 parent c810567 commit 014cb8a

1 file changed

Lines changed: 27 additions & 7 deletions

File tree

deezer_python_gql/base_client.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,24 @@ def __init__(self, message: str, locations: Any = None, path: Any = None) -> Non
4747
class GraphQLClientGraphQLMultiError(GraphQLClientError):
4848
"""Raised when the GraphQL response contains errors."""
4949

50-
def __init__(self, errors: list[GraphQLClientGraphQLError], data: Any = None) -> None:
50+
def __init__(
51+
self,
52+
errors: list[GraphQLClientGraphQLError],
53+
data: Any = None,
54+
operation_name: str | None = None,
55+
) -> None:
5156
self.errors = errors
5257
self.data = data
53-
super().__init__(str(errors))
58+
self.operation_name = operation_name
59+
msg = f"{operation_name}: {errors}" if operation_name else str(errors)
60+
super().__init__(msg)
5461

5562
@classmethod
5663
def from_errors_dicts(
5764
cls,
5865
errors_dicts: list[dict[str, Any]],
5966
data: Any = None,
67+
operation_name: str | None = None,
6068
) -> GraphQLClientGraphQLMultiError:
6169
"""Create from raw error dicts in a GraphQL response."""
6270
errors = [
@@ -67,7 +75,7 @@ def from_errors_dicts(
6775
)
6876
for e in errors_dicts
6977
]
70-
return cls(errors=errors, data=data)
78+
return cls(errors=errors, data=data, operation_name=operation_name)
7179

7280

7381
class DeezerBaseClient:
@@ -101,6 +109,8 @@ def __init__(
101109
self._owns_http_client = http_client is None
102110
self._jwt: str | None = None
103111
self._jwt_expires_at: float = 0
112+
self._last_operation_name: str | None = None
113+
self._last_variables: dict[str, Any] | None = None
104114

105115
def _get_http_client(self) -> httpx.AsyncClient:
106116
"""Return the HTTP client, creating an internal one if needed."""
@@ -144,6 +154,8 @@ async def execute(
144154
:param kwargs: Additional keyword arguments passed to httpx.
145155
"""
146156
logger.debug("GQL execute: %s (variables=%s)", operation_name or "<unnamed>", variables)
157+
self._last_operation_name = operation_name
158+
self._last_variables = variables
147159
jwt = await self._ensure_jwt()
148160

149161
headers: dict[str, str] = kwargs.pop("headers", None) or {}
@@ -202,17 +214,24 @@ def get_data(self, response: httpx.Response) -> dict[str, Any]:
202214
errors = response_json.get("errors")
203215

204216
if errors:
217+
op = self._last_operation_name or "<unknown>"
218+
variables = self._last_variables
205219
if data:
206220
# Partial success — some items failed (e.g. deleted albums in favorites).
207221
# Log the errors but return the valid data.
222+
error_details = [
223+
f"{e.get('message', 'Unknown error')} (path={e.get('path')})" for e in errors
224+
]
208225
logger.warning(
209-
"GraphQL response contained %d error(s): %s",
226+
"GraphQL response for %s (variables=%s) contained %d error(s): %s",
227+
op,
228+
variables,
210229
len(errors),
211-
[e.get("message", "Unknown error") for e in errors],
230+
error_details,
212231
)
213232
else:
214233
raise GraphQLClientGraphQLMultiError.from_errors_dicts(
215-
errors_dicts=errors, data=data
234+
errors_dicts=errors, data=data, operation_name=op
216235
)
217236

218237
# The Deezer API omits __typename for single-member union types
@@ -304,7 +323,8 @@ async def check_audiobook_ids(self, album_ids: list[str]) -> set[str]:
304323
]
305324
query = "{ " + " ".join(parts) + " }"
306325

307-
resp = await self.execute(query)
326+
resp = await self.execute(query, operation_name="CheckAudiobookIds")
327+
self._last_variables = {"album_ids": album_ids}
308328
data = self.get_data(resp)
309329

310330
audiobook_ids: set[str] = set()

0 commit comments

Comments
 (0)