Release 5.0.2 with error source fix for some downstream errors (#1980)

This PR fixes error source for 2 errors:
- parsing of invalid json response should be downstream error as we
expect to receive valid json from zabbix
- no host found error should be downstream. We are bumping sdk that
includes that fix
https://github.com/grafana/grafana-plugin-sdk-go/pull/1246.

As you can see - the invalid json parsing is now downstream error
<img width="1498" alt="image"
src="https://github.com/user-attachments/assets/88028dbe-0f73-47aa-8262-5729059ce12f"
/>
This commit is contained in:
Ivana Huckova
2025-02-27 12:30:19 +01:00
committed by GitHub
parent d28a715bb1
commit 58902e7ed9
9 changed files with 84 additions and 26 deletions

View File

@@ -117,23 +117,23 @@ func (ds *ZabbixDatasource) QueryData(ctx context.Context, req *backend.QueryDat
query, err := ReadQuery(q)
ds.logger.Debug("DS query", "query", q)
if err != nil {
res.Error = err
res = backend.ErrorResponseWithErrorSource(err)
} else if query.QueryType == MODE_METRICS {
frames, err := zabbixDS.queryNumericItems(ctx, &query)
if err != nil {
res.Error = err
res = backend.ErrorResponseWithErrorSource(err)
} else {
res.Frames = append(res.Frames, frames...)
}
} else if query.QueryType == MODE_ITEMID {
frames, err := zabbixDS.queryItemIdData(ctx, &query)
if err != nil {
res.Error = err
res = backend.ErrorResponseWithErrorSource(err)
} else {
res.Frames = append(res.Frames, frames...)
}
} else {
res.Error = backend.DownstreamError(ErrNonMetricQueryNotSupported)
res = backend.ErrorResponseWithErrorSource(backend.DownstreamError(ErrNonMetricQueryNotSupported))
}
qdr.Responses[q.RefID] = res
}

View File

@@ -118,13 +118,13 @@ func ReadQuery(query backend.DataQuery) (QueryModel, error) {
Interval: query.Interval,
}
if err := json.Unmarshal(query.JSON, &model); err != nil {
return model, fmt.Errorf("could not read query: %w", err)
return model, backend.DownstreamError(fmt.Errorf("could not read query: %w", err))
}
if model.QueryType == "" {
queryJSON, err := simplejson.NewJson(query.JSON)
if err != nil {
return model, fmt.Errorf("could not read query JSON: %w", err)
return model, backend.DownstreamError(fmt.Errorf("could not read query JSON: %w", err))
}
queryType, err := queryJSON.Get("queryType").Int64()

View File

@@ -125,7 +125,7 @@ func (zabbix *Zabbix) Authenticate(ctx context.Context) error {
}
err = zabbix.api.AuthenticateWithToken(ctx, token)
if err != nil {
zabbix.logger.Error("Zabbix authentication error", "error", err)
zabbix.logger.Error("Zabbix authentication token error", "error", err)
return err
}
zabbix.logger.Debug("Using API token for authentication")

View File

@@ -196,7 +196,8 @@ func isDeprecatedUserParamError(err error) bool {
func handleAPIResult(response []byte) (*simplejson.Json, error) {
jsonResp, err := simplejson.NewJson([]byte(response))
if err != nil {
return nil, err
// Response is not valid JSON
return nil, backend.DownstreamError(err)
}
if errJSON, isError := jsonResp.CheckGet("error"); isError {
errMessage := fmt.Errorf("%s %s", errJSON.Get("message").MustString(), errJSON.Get("data").MustString())

View File

@@ -71,3 +71,54 @@ func TestZabbixAPI(t *testing.T) {
})
}
}
func TestHandleAPIResult(t *testing.T) {
tests := []struct {
name string
response string
expectedData interface{}
expectedError string
isDownstream bool
}{
{
name: "Valid JSON with result",
response: `{"result": {"data": "test"}}`,
expectedData: map[string]interface{}{"data": "test"},
},
{
name: "Invalid JSON",
response: `{"result": invalid}`,
expectedError: "invalid character 'i' looking for beginning of value",
isDownstream: true,
},
{
name: "API error response",
response: `{"error": {"message": "Authentication failed", "data": "Session terminated"}}`,
expectedError: "Authentication failed Session terminated",
isDownstream: true,
},
{
name: "Empty result",
response: `{"result": []}`,
expectedData: []interface{}{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := handleAPIResult([]byte(tt.response))
if tt.expectedError != "" {
assert.Error(t, err)
assert.Equal(t, tt.expectedError, err.Error())
if tt.isDownstream {
assert.True(t, backend.IsDownstreamError(err), "error should be a downstream error")
}
return
}
assert.NoError(t, err)
assert.Equal(t, tt.expectedData, result.Interface())
})
}
}