From 4fcd3483666b58b75206ab0b9fd5318746549e76 Mon Sep 17 00:00:00 2001 From: ismail simsek Date: Thu, 4 Jul 2024 17:45:36 +0200 Subject: [PATCH] InfluxDB: Fix returning InfluxDB error messages (#89973) * Revert "Chore: Return influxdb query error early before parsing the result (#88549)" This reverts commit a87c155c06bf3f92d711342131f68f3086b3f9d0. * Handle error in buffered parser * handle error message in streaming parser --- .../influxql/buffered/response_parser.go | 8 +++++ .../influxql/buffered/response_parser_test.go | 10 ++++-- .../influxdb/influxql/converter/converter.go | 32 ++++++++++++++++--- pkg/tsdb/influxdb/influxql/influxql.go | 5 --- .../influxql/querydata/stream_parser.go | 4 +++ .../influxql/querydata/stream_parser_test.go | 8 +++++ .../influxql/testdata/invalid_response.json | 4 +++ pkg/tsdb/influxdb/models/models.go | 2 ++ 8 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 pkg/tsdb/influxdb/influxql/testdata/invalid_response.json diff --git a/pkg/tsdb/influxdb/influxql/buffered/response_parser.go b/pkg/tsdb/influxdb/influxql/buffered/response_parser.go index 91fc8b9967f..b6b840e6dc5 100644 --- a/pkg/tsdb/influxdb/influxql/buffered/response_parser.go +++ b/pkg/tsdb/influxdb/influxql/buffered/response_parser.go @@ -23,6 +23,14 @@ func ResponseParse(buf io.ReadCloser, statusCode int, query *models.Query) *back func parse(buf io.Reader, statusCode int, query *models.Query) *backend.DataResponse { response, jsonErr := parseJSON(buf) + if statusCode/100 != 2 { + errorStr := response.Error + if errorStr == "" { + errorStr = response.Message + } + return &backend.DataResponse{Error: fmt.Errorf("InfluxDB returned error: %s", errorStr)} + } + if jsonErr != nil { return &backend.DataResponse{Error: jsonErr} } diff --git a/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go b/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go index 3dab1ff1603..b1ec590c2d5 100644 --- a/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go +++ b/pkg/tsdb/influxdb/influxql/buffered/response_parser_test.go @@ -338,9 +338,15 @@ func TestInfluxdbResponseParser(t *testing.T) { }) t.Run("Influxdb response parser with top-level error", func(t *testing.T) { - result := ResponseParse(readJsonFile("error_on_top_level_response"), 200, generateQuery("Test raw query", "time_series", "")) + result := ResponseParse(readJsonFile("error_on_top_level_response"), 400, generateQuery("Test raw query", "time_series", "")) require.Nil(t, result.Frames) - require.EqualError(t, result.Error, "error parsing query: found THING") + require.EqualError(t, result.Error, "InfluxDB returned error: error parsing query: found THING") + }) + + t.Run("Influxdb response parser with error message", func(t *testing.T) { + result := ResponseParse(readJsonFile("invalid_response"), 400, generateQuery("Test raw query", "time_series", "")) + require.Nil(t, result.Frames) + require.EqualError(t, result.Error, "InfluxDB returned error: failed to parse query: found WERE, expected ; at line 1, char 38") }) t.Run("Influxdb response parser parseNumber nil", func(t *testing.T) { diff --git a/pkg/tsdb/influxdb/influxql/converter/converter.go b/pkg/tsdb/influxdb/influxql/converter/converter.go index 0cdbc010b73..337b24014b1 100644 --- a/pkg/tsdb/influxdb/influxql/converter/converter.go +++ b/pkg/tsdb/influxdb/influxql/converter/converter.go @@ -34,6 +34,26 @@ l1Fields: if rsp.Error != nil { return rsp } + case "error": + v, err := iter.ReadString() + if err != nil { + rsp.Error = err + } else { + rsp.Error = fmt.Errorf(v) + } + return rsp + case "code": + // we only care of the message + _, err := iter.Read() + if err != nil { + return rspErr(err) + } + case "message": + v, err := iter.Read() + if err != nil { + return rspErr(err) + } + return rspErr(fmt.Errorf("%s", v)) case "": if err != nil { return rspErr(err) @@ -41,11 +61,15 @@ l1Fields: break l1Fields default: v, err := iter.Read() - if err != nil { - rsp.Error = err - return rsp - } fmt.Printf("[ROOT] unsupported key: %s / %v\n\n", l1Field, v) + if err != nil { + if rsp != nil { + rsp.Error = err + return rsp + } else { + return rspErr(err) + } + } } } diff --git a/pkg/tsdb/influxdb/influxql/influxql.go b/pkg/tsdb/influxdb/influxql/influxql.go index 660e245a940..61879579f0e 100644 --- a/pkg/tsdb/influxdb/influxql/influxql.go +++ b/pkg/tsdb/influxdb/influxql/influxql.go @@ -177,11 +177,6 @@ func execute(ctx context.Context, tracer trace.Tracer, dsInfo *models.Datasource if err != nil { return backend.DataResponse{}, err } - - if res.StatusCode/100 != 2 { - return backend.DataResponse{Error: fmt.Errorf("InfluxDB returned error: %v", res.Body)}, nil - } - defer func() { if err := res.Body.Close(); err != nil { logger.Warn("Failed to close response body", "err", err) diff --git a/pkg/tsdb/influxdb/influxql/querydata/stream_parser.go b/pkg/tsdb/influxdb/influxql/querydata/stream_parser.go index 2efded14ed9..dde413c8fa4 100644 --- a/pkg/tsdb/influxdb/influxql/querydata/stream_parser.go +++ b/pkg/tsdb/influxdb/influxql/querydata/stream_parser.go @@ -23,6 +23,10 @@ func ResponseParse(buf io.ReadCloser, statusCode int, query *models.Query) *back iter := jsoniter.Parse(jsoniter.ConfigDefault, buf, 1024) r := converter.ReadInfluxQLStyleResult(iter, query) + if statusCode/100 != 2 { + return &backend.DataResponse{Error: fmt.Errorf("InfluxDB returned error: %s", r.Error)} + } + // The ExecutedQueryString can be viewed in QueryInspector in UI for i, frame := range r.Frames { if i == 0 { diff --git a/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go b/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go index 7e2f8951bbe..3c6222ea824 100644 --- a/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go +++ b/pkg/tsdb/influxdb/influxql/querydata/stream_parser_test.go @@ -105,3 +105,11 @@ func TestParsingAsTimeSeriesWithoutTimeColumn(t *testing.T) { runQuery(t, f, "cardinality", "time_series", query) }) } + +func TestInfluxDBStreamingParser(t *testing.T) { + t.Run("Influxdb response parser with error message", func(t *testing.T) { + result := ResponseParse(readJsonFile("invalid_response"), 400, generateQuery("Test raw query", "time_series", "")) + require.Nil(t, result.Frames) + require.EqualError(t, result.Error, "InfluxDB returned error: failed to parse query: found WERE, expected ; at line 1, char 38") + }) +} diff --git a/pkg/tsdb/influxdb/influxql/testdata/invalid_response.json b/pkg/tsdb/influxdb/influxql/testdata/invalid_response.json new file mode 100644 index 00000000000..1d8d62eb9c5 --- /dev/null +++ b/pkg/tsdb/influxdb/influxql/testdata/invalid_response.json @@ -0,0 +1,4 @@ +{ + "code": "invalid", + "message": "failed to parse query: found WERE, expected ; at line 1, char 38" +} diff --git a/pkg/tsdb/influxdb/models/models.go b/pkg/tsdb/influxdb/models/models.go index 020b90742bd..2afab2f848b 100644 --- a/pkg/tsdb/influxdb/models/models.go +++ b/pkg/tsdb/influxdb/models/models.go @@ -32,6 +32,8 @@ type Select []QueryPart type Response struct { Results []Result Error string + Code string + Message string } type Result struct {