AzureMonitor and GCM: Replace deprecated experimental/errorsource (#97360)

* Update cloud monitoring

* Update azure monitor

* Update test
pull/97584/head
Ivana Huckova 6 months ago committed by GitHub
parent 1fc9b4bfc1
commit 9a3f8c93dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 21
      pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go
  2. 10
      pkg/tsdb/azuremonitor/loganalytics/utils.go
  3. 12
      pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go
  4. 9
      pkg/tsdb/azuremonitor/utils/utils.go
  5. 59
      pkg/tsdb/azuremonitor/utils/utils_test.go
  6. 9
      pkg/tsdb/cloud-monitoring/annotation_query.go
  7. 19
      pkg/tsdb/cloud-monitoring/cloudmonitoring.go
  8. 3
      pkg/tsdb/cloud-monitoring/promql_query.go
  9. 3
      pkg/tsdb/cloud-monitoring/utils.go

@ -18,7 +18,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
@ -142,12 +141,12 @@ func (e *AzureLogAnalyticsDatasource) ExecuteTimeSeriesQuery(ctx context.Context
for _, query := range originalQueries {
logsQuery, err := e.buildQuery(ctx, query, dsInfo, fromAlert)
if err != nil {
errorsource.AddErrorToResponse(query.RefID, result, err)
result.Responses[query.RefID] = backend.ErrorResponseWithErrorSource(err)
continue
}
res, err := e.executeQuery(ctx, logsQuery, dsInfo, client, url)
if err != nil {
errorsource.AddErrorToResponse(query.RefID, result, err)
result.Responses[query.RefID] = backend.ErrorResponseWithErrorSource(err)
continue
}
result.Responses[query.RefID] = *res
@ -252,7 +251,7 @@ func (e *AzureLogAnalyticsDatasource) buildQuery(ctx context.Context, query back
cfg := backend.GrafanaConfigFromContext(ctx)
hasPromExemplarsToggle := cfg.FeatureToggles().IsEnabled("azureMonitorPrometheusExemplars")
if !hasPromExemplarsToggle {
return nil, errorsource.DownstreamError(fmt.Errorf("query type unsupported as azureMonitorPrometheusExemplars feature toggle is not enabled"), false)
return nil, backend.DownstreamError(fmt.Errorf("query type unsupported as azureMonitorPrometheusExemplars feature toggle is not enabled"))
}
}
azureAppInsightsQuery, err := buildAppInsightsQuery(ctx, query, dsInfo, appInsightsRegExp, e.Logger)
@ -269,7 +268,7 @@ func (e *AzureLogAnalyticsDatasource) buildQuery(ctx context.Context, query back
func (e *AzureLogAnalyticsDatasource) executeQuery(ctx context.Context, query *AzureLogAnalyticsQuery, dsInfo types.DatasourceInfo, client *http.Client, url string) (*backend.DataResponse, error) {
// If azureLogAnalyticsSameAs is defined and set to false, return an error
if sameAs, ok := dsInfo.JSONData["azureLogAnalyticsSameAs"]; ok && !sameAs.(bool) {
return nil, errorsource.DownstreamError(fmt.Errorf("credentials for Log Analytics are no longer supported. Go to the data source configuration to update Azure Monitor credentials"), false)
return nil, backend.DownstreamError(fmt.Errorf("credentials for Log Analytics are no longer supported. Go to the data source configuration to update Azure Monitor credentials"))
}
queryJSONModel := dataquery.AzureMonitorQuery{}
@ -280,7 +279,7 @@ func (e *AzureLogAnalyticsDatasource) executeQuery(ctx context.Context, query *A
if query.QueryType == dataquery.AzureQueryTypeAzureTraces {
if query.ResultFormat == dataquery.ResultFormatTrace && query.Query == "" {
return nil, errorsource.DownstreamError(fmt.Errorf("cannot visualise trace events using the trace visualiser"), false)
return nil, backend.DownstreamError(fmt.Errorf("cannot visualise trace events using the trace visualiser"))
}
}
@ -301,7 +300,7 @@ func (e *AzureLogAnalyticsDatasource) executeQuery(ctx context.Context, query *A
res, err := client.Do(req)
if err != nil {
return nil, errorsource.DownstreamError(err, false)
return nil, backend.DownstreamError(err)
}
defer func() {
@ -597,11 +596,11 @@ func getCorrelationWorkspaces(ctx context.Context, baseResource string, resource
res, err := azMonService.HTTPClient.Do(req)
if err != nil {
return AzureCorrelationAPIResponse{}, errorsource.DownstreamError(err, false)
return AzureCorrelationAPIResponse{}, backend.DownstreamError(err)
}
body, err := io.ReadAll(res.Body)
if err != nil {
return AzureCorrelationAPIResponse{}, errorsource.DownstreamError(err, false)
return AzureCorrelationAPIResponse{}, backend.DownstreamError(err)
}
defer func() {
@ -611,7 +610,7 @@ func getCorrelationWorkspaces(ctx context.Context, baseResource string, resource
}()
if res.StatusCode/100 != 2 {
return AzureCorrelationAPIResponse{}, errorsource.SourceError(backend.ErrorSourceFromHTTPStatus(res.StatusCode), fmt.Errorf("request failed, status: %s, body: %s", res.Status, string(body)), false)
return AzureCorrelationAPIResponse{}, utils.CreateResponseErrorFromStatusCode(res.StatusCode, res.Status, body)
}
var data AzureCorrelationAPIResponse
d := json.NewDecoder(bytes.NewReader(body))
@ -675,7 +674,7 @@ func (e *AzureLogAnalyticsDatasource) unmarshalResponse(res *http.Response) (Azu
}()
if res.StatusCode/100 != 2 {
return AzureLogAnalyticsResponse{}, errorsource.SourceError(backend.ErrorSourceFromHTTPStatus(res.StatusCode), fmt.Errorf("request failed, status: %s, body: %s", res.Status, string(body)), false)
return AzureLogAnalyticsResponse{}, utils.CreateResponseErrorFromStatusCode(res.StatusCode, res.Status, body)
}
var data AzureLogAnalyticsResponse

@ -7,8 +7,8 @@ import (
"strings"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/kinds/dataquery"
)
@ -47,18 +47,18 @@ func AddConfigLinks(frame data.Frame, dl string, title *string) data.Frame {
// 4. the ds toggle is set to true
func meetsBasicLogsCriteria(resources []string, fromAlert bool, basicLogsEnabled bool) (bool, error) {
if fromAlert {
return false, errorsource.DownstreamError(fmt.Errorf("basic Logs queries cannot be used for alerts"), false)
return false, backend.DownstreamError(fmt.Errorf("basic Logs queries cannot be used for alerts"))
}
if len(resources) != 1 {
return false, errorsource.DownstreamError(fmt.Errorf("basic logs queries cannot be run against multiple resources"), false)
return false, backend.DownstreamError(fmt.Errorf("basic logs queries cannot be run against multiple resources"))
}
if !strings.Contains(strings.ToLower(resources[0]), "microsoft.operationalinsights/workspaces") {
return false, errorsource.DownstreamError(fmt.Errorf("basic logs queries may only be run against Log Analytics workspaces"), false)
return false, backend.DownstreamError(fmt.Errorf("basic logs queries may only be run against Log Analytics workspaces"))
}
if !basicLogsEnabled {
return false, errorsource.DownstreamError(fmt.Errorf("basic Logs queries are disabled for this data source"), false)
return false, backend.DownstreamError(fmt.Errorf("basic Logs queries are disabled for this data source"))
}
return true, nil

@ -17,7 +17,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
@ -25,6 +24,7 @@ import (
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/loganalytics"
azTime "github.com/grafana/grafana/pkg/tsdb/azuremonitor/time"
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/types"
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/utils"
)
// AzureMonitorDatasource calls the Azure Monitor API - one of the four API's supported
@ -55,12 +55,12 @@ func (e *AzureMonitorDatasource) ExecuteTimeSeriesQuery(ctx context.Context, ori
for _, query := range originalQueries {
azureQuery, err := e.buildQuery(query, dsInfo)
if err != nil {
errorsource.AddErrorToResponse(query.RefID, result, err)
result.Responses[query.RefID] = backend.ErrorResponseWithErrorSource(err)
continue
}
res, err := e.executeQuery(ctx, azureQuery, dsInfo, client, url)
if err != nil {
errorsource.AddErrorToResponse(query.RefID, result, err)
result.Responses[query.RefID] = backend.ErrorResponseWithErrorSource(err)
continue
}
result.Responses[query.RefID] = *res
@ -284,7 +284,7 @@ func (e *AzureMonitorDatasource) retrieveSubscriptionDetails(cli *http.Client, c
}
if res.StatusCode/100 != 2 {
return "", errorsource.SourceError(backend.ErrorSourceFromHTTPStatus(res.StatusCode), fmt.Errorf("request failed, status: %s, error: %s", res.Status, string(body)), false)
return "", utils.CreateResponseErrorFromStatusCode(res.StatusCode, res.Status, body)
}
var data types.SubscriptionsResponse
@ -321,7 +321,7 @@ func (e *AzureMonitorDatasource) executeQuery(ctx context.Context, query *types.
res, err := cli.Do(req)
if err != nil {
return nil, errorsource.DownstreamError(err, false)
return nil, backend.DownstreamError(err)
}
defer func() {
@ -366,7 +366,7 @@ func (e *AzureMonitorDatasource) unmarshalResponse(res *http.Response) (types.Az
}
if res.StatusCode/100 != 2 {
return types.AzureMonitorResponse{}, errorsource.SourceError(backend.ErrorSourceFromHTTPStatus(res.StatusCode), fmt.Errorf("request failed, status: %s, body: %s", res.Status, string(body)), false)
return types.AzureMonitorResponse{}, utils.CreateResponseErrorFromStatusCode(res.StatusCode, res.Status, body)
}
var data types.AzureMonitorResponse

@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/types"
@ -78,3 +79,11 @@ func ApplySourceFromError(errorMessage error, err error) error {
}
return errorMessage
}
func CreateResponseErrorFromStatusCode(statusCode int, status string, body []byte) error {
statusErr := fmt.Errorf("request failed, status: %s, body: %s", status, string(body))
if backend.ErrorSourceFromHTTPStatus(statusCode) == backend.ErrorSourceDownstream {
return backend.DownstreamError(statusErr)
}
return backend.PluginError(statusErr)
}

@ -0,0 +1,59 @@
package utils
import (
"errors"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/stretchr/testify/assert"
)
func TestCreateResponseErrorFromStatusCode(t *testing.T) {
tests := []struct {
name string
statusCode int
status string
body []byte
expectedErrMessage string
expectedType backend.ErrorSource
}{
{
name: "Downstream error for 500 status",
statusCode: 500,
status: "500 Internal Server Error",
body: []byte("body bytes"),
expectedErrMessage: "request failed, status: 500 Internal Server Error, body: body bytes",
expectedType: backend.ErrorSourceDownstream,
},
{
name: "Plugin error for 501 status",
statusCode: 501,
status: "501 Not Implemented",
body: []byte("body bytes"),
expectedErrMessage: "request failed, status: 501 Not Implemented, body: body bytes",
expectedType: backend.ErrorSourcePlugin,
},
{
name: "Downstream error for 502 status",
statusCode: 502,
status: "502 Gateway Error",
body: []byte("body bytes"),
expectedErrMessage: "request failed, status: 502 Gateway Error, body: body bytes",
expectedType: backend.ErrorSourceDownstream,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := CreateResponseErrorFromStatusCode(tt.statusCode, tt.status, tt.body)
assert.Error(t, err)
// Check if error is of type ErrorWithSource
var errorWithSource backend.ErrorWithSource
assert.True(t, errors.As(err, &errorWithSource))
// Validate the source of the error
assert.Equal(t, tt.expectedType, errorWithSource.ErrorSource())
assert.Contains(t, err.Error(), tt.expectedErrMessage)
})
}
}

@ -10,7 +10,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
)
type annotationEvent struct {
@ -25,10 +24,10 @@ func (s *Service) executeAnnotationQuery(ctx context.Context, req *backend.Query
resp := backend.NewQueryDataResponse()
dr, queryRes, _, err := queries[0].run(ctx, req, s, dsInfo, logger)
if dr.Error != nil {
errorsource.AddErrorToResponse(queries[0].getRefID(), resp, dr.Error)
resp.Responses[queries[0].getRefID()] = backend.ErrorResponseWithErrorSource(dr.Error)
}
if err != nil {
errorsource.AddErrorToResponse(queries[0].getRefID(), resp, err)
resp.Responses[queries[0].getRefID()] = backend.ErrorResponseWithErrorSource(err)
return resp, err
}
@ -43,7 +42,7 @@ func (s *Service) executeAnnotationQuery(ctx context.Context, req *backend.Query
err = json.Unmarshal(firstQuery.JSON, &tslq)
if err != nil {
logger.Error("error unmarshaling query", "error", err, "statusSource", backend.ErrorSourceDownstream)
errorsource.AddErrorToResponse(firstQuery.RefID, resp, err)
resp.Responses[firstQuery.RefID] = backend.ErrorResponseWithErrorSource(err)
return resp, nil
}
@ -52,7 +51,7 @@ func (s *Service) executeAnnotationQuery(ctx context.Context, req *backend.Query
resp.Responses[firstQuery.RefID] = *dr
if err != nil {
errorsource.AddErrorToResponse(firstQuery.RefID, resp, err)
resp.Responses[firstQuery.RefID] = backend.ErrorResponseWithErrorSource(err)
return resp, err
}

@ -22,7 +22,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery"
)
@ -363,16 +362,16 @@ func (s *Service) executeTimeSeriesQuery(ctx context.Context, req *backend.Query
for _, queryExecutor := range queries {
dr, queryRes, executedQueryString, err := queryExecutor.run(ctx, req, s, dsInfo, logger)
if err != nil {
errorsource.AddErrorToResponse(queryExecutor.getRefID(), resp, err)
resp.Responses[queryExecutor.getRefID()] = backend.ErrorResponseWithErrorSource(err)
return resp, err
}
err = queryExecutor.parseResponse(dr, queryRes, executedQueryString, logger)
if err != nil {
dr.Error = err
// // Default to a plugin error if there's no source
errWithSource := errorsource.SourceError(backend.ErrorSourcePlugin, err, false)
dr.Error = errWithSource.Unwrap()
dr.ErrorSource = errWithSource.ErrorSource()
// If the error is a downstream error, set the error source
if backend.IsDownstreamError(err) {
dr.ErrorSource = backend.ErrorSourceDownstream
}
}
resp.Responses[queryExecutor.getRefID()] = *dr
@ -592,7 +591,7 @@ func (s *Service) getDefaultProject(ctx context.Context, dsInfo datasourceInfo)
if dsInfo.authenticationType == gceAuthentication {
project, err := s.gceDefaultProjectGetter(ctx, cloudMonitorScope)
if err != nil {
return project, errorsource.DownstreamError(err, false)
return project, backend.DownstreamError(err)
}
return project, nil
}
@ -613,7 +612,11 @@ func unmarshalResponse(res *http.Response, logger log.Logger) (cloudMonitoringRe
if res.StatusCode/100 != 2 {
logger.Error("Request failed", "status", res.Status, "body", string(body), "statusSource", backend.ErrorSourceDownstream)
return cloudMonitoringResponse{}, errorsource.SourceError(backend.ErrorSourceFromHTTPStatus(res.StatusCode), fmt.Errorf("query failed: %s", string(body)), false)
statusErr := fmt.Errorf("query failed: %s", string(body))
if backend.ErrorSourceFromHTTPStatus(res.StatusCode) == backend.ErrorSourceDownstream {
return cloudMonitoringResponse{}, backend.DownstreamError(statusErr)
}
return cloudMonitoringResponse{}, backend.PluginError(statusErr)
}
var data cloudMonitoringResponse

@ -13,7 +13,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/converter"
jsoniter "github.com/json-iterator/go"
)
@ -68,7 +67,7 @@ func doRequestProm(r *http.Request, dsInfo datasourceInfo, body map[string]any)
}
res, err := dsInfo.services[cloudMonitor].client.Do(r)
if err != nil {
return res, errorsource.DownstreamError(err, false)
return res, backend.DownstreamError(err)
}
return res, nil

@ -18,7 +18,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental/errorsource"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
@ -85,7 +84,7 @@ func doRequestPage(_ context.Context, r *http.Request, dsInfo datasourceInfo, pa
}
res, err := dsInfo.services[cloudMonitor].client.Do(r)
if err != nil {
return cloudMonitoringResponse{}, errorsource.DownstreamError(err, false)
return cloudMonitoringResponse{}, backend.DownstreamError(err)
}
defer func() {

Loading…
Cancel
Save