Skip to content

Commit

Permalink
[v9.3.x] AzureMonitor: Fix bad request when setting dimensions (#59708)
Browse files Browse the repository at this point in the history
AzureMonitor: Fix bad request when setting dimensions (#59700)

(cherry picked from commit a7d4bbf)

Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
  • Loading branch information
grafanabot and andresmgot committed Dec 2, 2022
1 parent 04fb50f commit 51e6b11
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 15 deletions.
20 changes: 15 additions & 5 deletions pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
}

azureURL := BuildSubscriptionMetricsURL(queryJSONModel.Subscription)
filterInBody := true
if azJSONModel.Region != "" {
params.Add("region", azJSONModel.Region)
} else {
Expand All @@ -121,6 +122,8 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
ResourceName: azJSONModel.ResourceName,
}
azureURL = ub.BuildMetricsURL()
// POST requests are only supported at the subscription level
filterInBody = false
}

// old model
Expand Down Expand Up @@ -174,15 +177,22 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
logger.Debug("Azuremonitor request", "params", params)
}

azureMonitorQueries = append(azureMonitorQueries, &types.AzureMonitorQuery{
query := &types.AzureMonitorQuery{
URL: azureURL,
Target: target,
Params: params,
RefID: query.RefID,
Alias: alias,
TimeRange: query.TimeRange,
Filter: filterString,
})
}
if filterString != "" {
if filterInBody {
query.BodyFilter = filterString
} else {
query.Params.Add("$filter", filterString)
}
}
azureMonitorQueries = append(azureMonitorQueries, query)
}

return azureMonitorQueries, nil
Expand All @@ -200,9 +210,9 @@ func (e *AzureMonitorDatasource) executeQuery(ctx context.Context, logger log.Lo

req.URL.Path = path.Join(req.URL.Path, query.URL)
req.URL.RawQuery = query.Params.Encode()
if query.Filter != "" {
if query.BodyFilter != "" {
req.Method = http.MethodPost
req.Body = io.NopCloser(strings.NewReader(fmt.Sprintf(`{"filter": "%s"}`, query.Filter)))
req.Body = io.NopCloser(strings.NewReader(fmt.Sprintf(`{"filter": "%s"}`, query.BodyFilter)))
}

ctx, span := tracer.Start(ctx, "azuremonitor query")
Expand Down
31 changes: 28 additions & 3 deletions pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
ptr "github.com/xorcare/pointer"

Expand Down Expand Up @@ -208,6 +209,19 @@ func TestAzureMonitorBuildQueries(t *testing.T) {
azureMonitorQueryTarget: "aggregation=Average&api-version=2021-05-01&interval=PT1M&metricnames=Percentage+CPU&metricnamespace=Microsoft.Compute%2FvirtualMachines&region=westus&timespan=2018-03-15T13%3A00%3A00Z%2F2018-03-15T13%3A34%3A00Z",
expectedURL: "/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/providers/microsoft.insights/metrics",
},
{
name: "Includes a region and a filter",
azureMonitorVariedProperties: map[string]interface{}{
"timeGrain": "PT1M",
"top": "10",
"region": "westus",
"resources": []types.AzureMonitorResource{{ResourceGroup: "rg", ResourceName: "vm"}},
},
expectedInterval: "PT1M",
azureMonitorQueryTarget: "aggregation=Average&api-version=2021-05-01&interval=PT1M&metricnames=Percentage+CPU&metricnamespace=Microsoft.Compute%2FvirtualMachines&region=westus&timespan=2018-03-15T13%3A00%3A00Z%2F2018-03-15T13%3A34%3A00Z",
expectedURL: "/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/providers/microsoft.insights/metrics",
expectedFilter: "Microsoft.ResourceId eq '/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/vm'",
},
{
name: "includes a resource as a filter",
azureMonitorVariedProperties: map[string]interface{}{
Expand Down Expand Up @@ -266,6 +280,9 @@ func TestAzureMonitorBuildQueries(t *testing.T) {
},
}

queries, err := datasource.buildQueries(log.New("test"), tsdbQuery, dsInfo)
require.NoError(t, err)

azureMonitorQuery := &types.AzureMonitorQuery{
URL: tt.expectedURL,
Target: tt.azureMonitorQueryTarget,
Expand All @@ -275,14 +292,22 @@ func TestAzureMonitorBuildQueries(t *testing.T) {
From: fromStart,
To: fromStart.Add(34 * time.Minute),
},
Filter: tt.expectedFilter,
}
if tt.azureMonitorVariedProperties["region"] != nil {
// If the region is included, the filter will be added in the Body of the request
azureMonitorQuery.BodyFilter = tt.expectedFilter
} else {
// In other case, the filter will be added in the URL
if tt.expectedFilter != "" {
assert.Equal(t, tt.expectedFilter, queries[0].Params.Get("$filter"))
} else {
assert.Equal(t, false, queries[0].Params.Has("$filter"))
}
}
if azureMonitorQuery.URL == "" {
azureMonitorQuery.URL = "/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanastaging/providers/Microsoft.Compute/virtualMachines/grafana/providers/microsoft.insights/metrics"
}

queries, err := datasource.buildQueries(log.New("test"), tsdbQuery, dsInfo)
require.NoError(t, err)
if diff := cmp.Diff(azureMonitorQuery, queries[0], cmpopts.IgnoreUnexported(simplejson.Json{}), cmpopts.IgnoreFields(types.AzureMonitorQuery{}, "Params")); diff != "" {
t.Errorf("Result mismatch (-want +got):\n%s", diff)
}
Expand Down
14 changes: 7 additions & 7 deletions pkg/tsdb/azuremonitor/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ type DatasourceInfo struct {
// AzureMonitorQuery is the query for all the services as they have similar queries
// with a url, a querystring and an alias field
type AzureMonitorQuery struct {
URL string
Target string
Params url.Values
RefID string
Alias string
TimeRange backend.TimeRange
Filter string
URL string
Target string
Params url.Values
RefID string
Alias string
TimeRange backend.TimeRange
BodyFilter string
}

// AzureMonitorResponse is the json response from the Azure Monitor API
Expand Down

0 comments on commit 51e6b11

Please sign in to comment.