You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by rb...@apache.org on 2026/03/19 14:37:36 UTC
(superset) 01/01: fix(chart): add error logging to /api/v1/chart/data endpoint
This is an automated email from the ASF dual-hosted git repository.
rbenitez pushed a commit to branch rebenitez1802/fix/add-debug-logs-to-chart-data-endpoint
in repository https://gitbox.apache.org/repos/asf/superset.git
commit c21321dfa2cd631208fea07b0f500f4347413dc0
Author: Rafael Benitez <re...@gmail.com>
AuthorDate: Thu Mar 19 11:37:09 2026 -0300
fix(chart): add error logging to /api/v1/chart/data endpoint
Add error-level logging to all failure paths in the chart data API
to help diagnose intermittent 400 BAD REQUEST failures during CSV
exports. Previously, JSON parsing errors were silently swallowed by
contextlib.suppress and validation/query errors returned 400 without
any logging, making it impossible to identify which failure path was
hit.
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
superset/charts/data/api.py | 69 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/superset/charts/data/api.py b/superset/charts/data/api.py
index 707ce79f918..93c754c8906 100644
--- a/superset/charts/data/api.py
+++ b/superset/charts/data/api.py
@@ -250,9 +250,29 @@ class ChartDataRestApi(ChartRestApi):
json_body = request.json
elif request.form.get("form_data"):
# CSV export submits regular form data
- with contextlib.suppress(TypeError, json.JSONDecodeError):
+ try:
json_body = json.loads(request.form["form_data"])
+ except (TypeError, json.JSONDecodeError):
+ logger.error(
+ "Failed to parse form_data JSON: "
+ "content_type=%s, content_length=%s, form_data_length=%s, "
+ "referrer=%s",
+ request.content_type,
+ request.content_length,
+ len(request.form.get("form_data", "")),
+ request.referrer,
+ )
if json_body is None:
+ logger.error(
+ "Chart data request rejected: json_body is None. "
+ "is_json=%s, content_type=%s, content_length=%s, "
+ "has_form_data=%s, referrer=%s",
+ request.is_json,
+ request.content_type,
+ request.content_length,
+ bool(request.form.get("form_data")),
+ request.referrer,
+ )
return self.response_400(message=_("Request is not JSON"))
try:
@@ -260,10 +280,37 @@ class ChartDataRestApi(ChartRestApi):
command = ChartDataCommand(query_context)
command.validate()
except DatasourceNotFound:
+ logger.error(
+ "Chart data request: DatasourceNotFound. "
+ "datasource=%s, result_format=%s, "
+ "slice_id=%s, referrer=%s",
+ json_body.get("datasource"),
+ json_body.get("result_format"),
+ json_body.get("form_data", {}).get("slice_id"),
+ request.referrer,
+ )
return self.response_404()
except QueryObjectValidationError as error:
+ logger.error(
+ "Chart data request: QueryObjectValidationError: %s. "
+ "result_format=%s, slice_id=%s, referrer=%s",
+ error.message,
+ json_body.get("result_format"),
+ json_body.get("form_data", {}).get("slice_id"),
+ request.referrer,
+ )
return self.response_400(message=error.message)
except ValidationError as error:
+ logger.error(
+ "Chart data request: ValidationError: %s. "
+ "result_format=%s, datasource=%s, "
+ "slice_id=%s, referrer=%s",
+ error.normalized_messages(),
+ json_body.get("result_format"),
+ json_body.get("datasource"),
+ json_body.get("form_data", {}).get("slice_id"),
+ request.referrer,
+ )
return self.response_400(
message=_(
"Request is incorrect: %(error)s", error=error.normalized_messages()
@@ -413,9 +460,21 @@ class ChartDataRestApi(ChartRestApi):
else:
has_export_perm = security_manager.can_access("can_csv", "Superset")
if not has_export_perm:
+ logger.error(
+ "Chart data request: export permission denied. "
+ "result_format=%s, referrer=%s",
+ result_format,
+ request.referrer,
+ )
return self.response_403()
if not result["queries"]:
+ logger.error(
+ "Chart data request: empty query result. "
+ "result_format=%s, referrer=%s",
+ result_format,
+ request.referrer,
+ )
return self.response_400(_("Empty query result"))
is_csv_format = result_format == ChartDataResultFormat.CSV
@@ -504,6 +563,14 @@ class ChartDataRestApi(ChartRestApi):
except ChartDataCacheLoadError as exc:
return self.response_422(message=exc.message)
except ChartDataQueryFailedError as exc:
+ logger.error(
+ "Chart data query failed: %s. "
+ "result_format=%s, force_cached=%s, referrer=%s",
+ exc.message,
+ form_data.get("result_format") if form_data else None,
+ force_cached,
+ request.referrer,
+ )
return self.response_400(message=exc.message)
# Log is_cached if extra payload callback is provided