AzureMonitor: Support multi-resource aliases and subscription aliases (#68648)

Update legend aliases

- Add subscription response type
- Update AzureMonitorQuery type
- Update docs
- Update tests
- Add function to retrieve subscription display name if not present
pull/68794/head
Andreas Christou 2 years ago committed by GitHub
parent a44ac0ed63
commit bca8428f63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      docs/sources/datasources/azure-monitor/query-editor/index.md
  2. 99
      pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go
  3. 49
      pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go
  4. 2
      pkg/tsdb/azuremonitor/testdata/azuremonitor/7-azure-monitor-response-multi-dimension.json
  5. 18
      pkg/tsdb/azuremonitor/testdata/azuremonitor/7-azure-monitor-response-multi-dimension.json.multiple-dimension-time-series-response-with-label-alias.golden.jsonc
  6. 25
      pkg/tsdb/azuremonitor/types/types.go

@ -83,6 +83,8 @@ For example:
| Alias pattern | Description |
| ----------------------------- | ------------------------------------------------------------------------------------------------------ |
| `{{ subscriptionid }}` | Replaced with the subscription ID. |
| `{{ subscription }}` | Replaced with the subscription name. |
| `{{ resourcegroup }}` | Replaced with the the resource group. |
| `{{ namespace }}` | Replaced with the resource type or namespace, such as `Microsoft.Compute/virtualMachines`. |
| `{{ resourcename }}` | Replaced with the resource name. |

@ -42,6 +42,8 @@ func (e *AzureMonitorDatasource) ResourceRequest(rw http.ResponseWriter, req *ht
e.Proxy.Do(rw, req, cli)
}
var subscriptions = map[string]string{}
// executeTimeSeriesQuery does the following:
// 1. build the AzureMonitor url and querystring for each query
// 2. executes each query by calling the Azure Monitor API
@ -112,6 +114,7 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
params.Add("region", azJSONModel.Region)
}
resourceIDs := []string{}
resourceMap := map[string]types.AzureMonitorResource{}
if hasOne, resourceGroup, resourceName := hasOneResource(queryJSONModel); hasOne {
ub := urlBuilder{
ResourceURI: azJSONModel.ResourceURI,
@ -125,6 +128,7 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
azureURL = ub.BuildMetricsURL()
// POST requests are only supported at the subscription level
filterInBody = false
resourceMap[ub.buildResourceURI()] = types.AzureMonitorResource{ResourceGroup: resourceGroup, ResourceName: resourceName}
} else {
for _, r := range azJSONModel.Resources {
ub := urlBuilder{
@ -134,7 +138,9 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
MetricNamespace: azJSONModel.MetricNamespace,
ResourceName: r.ResourceName,
}
resourceIDs = append(resourceIDs, fmt.Sprintf("Microsoft.ResourceId eq '%s'", ub.buildResourceURI()))
resourceUri := ub.buildResourceURI()
resourceMap[resourceUri] = r
resourceIDs = append(resourceIDs, fmt.Sprintf("Microsoft.ResourceId eq '%s'", resourceUri))
}
}
@ -180,13 +186,15 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
}
query := &types.AzureMonitorQuery{
URL: azureURL,
Target: target,
Params: params,
RefID: query.RefID,
Alias: alias,
TimeRange: query.TimeRange,
Dimensions: azJSONModel.DimensionFilters,
URL: azureURL,
Target: target,
Params: params,
RefID: query.RefID,
Alias: alias,
TimeRange: query.TimeRange,
Dimensions: azJSONModel.DimensionFilters,
Resources: resourceMap,
Subscription: queryJSONModel.Subscription,
}
if filterString != "" {
if filterInBody {
@ -201,6 +209,51 @@ func (e *AzureMonitorDatasource) buildQueries(logger log.Logger, queries []backe
return azureMonitorQueries, nil
}
func retrieveSubscriptionDetails(e *AzureMonitorDatasource, cli *http.Client, ctx context.Context, logger log.Logger, tracer tracing.Tracer, subscriptionId string, baseUrl string, dsId int64, orgId int64) {
req, err := e.createRequest(ctx, logger, fmt.Sprintf("%s/subscriptions/%s", baseUrl, subscriptionId))
if err != nil {
logger.Error("failed to retrieve subscription details for subscription %s: %s", subscriptionId, err)
}
values := req.URL.Query()
values.Add("api-version", "2022-12-01")
req.URL.RawQuery = values.Encode()
ctx, span := tracer.Start(ctx, "azuremonitor query")
span.SetAttributes("subscription", subscriptionId, attribute.Key("subscription").String(subscriptionId))
span.SetAttributes("datasource_id", dsId, attribute.Key("datasource_id").Int64(dsId))
span.SetAttributes("org_id", orgId, attribute.Key("org_id").Int64(orgId))
defer span.End()
tracer.Inject(ctx, req.Header, span)
logger.Debug("AzureMonitor", "Subscription Details Req")
res, err := cli.Do(req)
if err != nil {
logger.Warn("failed to request subscription details: %s", err)
}
defer func() {
if err := res.Body.Close(); err != nil {
logger.Warn("Failed to close response body", "err", err)
}
}()
body, err := io.ReadAll(res.Body)
if err != nil {
logger.Warn("failed to read response body: %s", err)
}
if res.StatusCode/100 != 2 {
logger.Warn("request failed, status: %s, error: %s", res.Status, string(body))
}
var data types.SubscriptionsResponse
err = json.Unmarshal(body, &data)
if err != nil {
logger.Warn("Failed to unmarshal subscription detail response", "error", err, "status", res.Status, "body", string(body))
}
subscriptions[data.SubscriptionID] = data.DisplayName
}
func (e *AzureMonitorDatasource) executeQuery(ctx context.Context, logger log.Logger, query *types.AzureMonitorQuery, dsInfo types.DatasourceInfo, cli *http.Client,
url string, tracer tracing.Tracer) backend.DataResponse {
dataResponse := backend.DataResponse{}
@ -253,6 +306,10 @@ func (e *AzureMonitorDatasource) executeQuery(ctx context.Context, logger log.Lo
return dataResponse
}
if _, ok := subscriptions[query.Subscription]; !ok {
retrieveSubscriptionDetails(e, cli, ctx, logger, tracer, query.Subscription, dsInfo.Routes["Azure Monitor"].URL, dsInfo.DatasourceID, dsInfo.OrgID)
}
dataResponse.Frames, err = e.parseResponse(data, query, azurePortalUrl)
if err != nil {
dataResponse.Error = err
@ -340,8 +397,9 @@ func (e *AzureMonitorDatasource) parseResponse(amr types.AzureMonitorResponse, q
labels["resourceName"] = resourceName
}
currentResource := query.Resources[resourceID]
if query.Alias != "" {
displayName := formatAzureMonitorLegendKey(query.Alias, resourceName,
displayName := formatAzureMonitorLegendKey(query.Alias, query.Subscription, currentResource,
amr.Value[0].Name.LocalizedValue, "", "", amr.Namespace, amr.Value[0].ID, labels)
if dataField.Config != nil {
@ -379,7 +437,6 @@ func (e *AzureMonitorDatasource) parseResponse(amr types.AzureMonitorResponse, q
if err != nil {
return nil, err
}
frameWithLink := loganalytics.AddConfigLinks(*frame, queryUrl, nil)
frames = append(frames, &frameWithLink)
}
@ -495,12 +552,8 @@ func getQueryUrl(query *types.AzureMonitorQuery, azurePortalUrl, resourceID, res
// formatAzureMonitorLegendKey builds the legend key or timeseries name
// Alias patterns like {{resourcename}} are replaced with the appropriate data values.
func formatAzureMonitorLegendKey(alias string, resourceName string, metricName string, metadataName string,
func formatAzureMonitorLegendKey(alias string, subscriptionId string, resource types.AzureMonitorResource, metricName string, metadataName string,
metadataValue string, namespace string, seriesID string, labels data.Labels) string {
startIndex := strings.Index(seriesID, "/resourceGroups/") + 16
endIndex := strings.Index(seriesID, "/providers")
resourceGroup := seriesID[startIndex:endIndex]
// Could be a collision problem if there were two keys that varied only in case, but I don't think that would happen in azure.
lowerLabels := data.Labels{}
for k, v := range labels {
@ -517,8 +570,20 @@ func formatAzureMonitorLegendKey(alias string, resourceName string, metricName s
metaPartName = strings.Replace(metaPartName, "}}", "", 1)
metaPartName = strings.ToLower(strings.TrimSpace(metaPartName))
if metaPartName == "subscriptionid" {
return []byte(subscriptionId)
}
if metaPartName == "subscription" {
if subscription, ok := subscriptions[subscriptionId]; ok {
return []byte(subscription)
} else {
return []byte{}
}
}
if metaPartName == "resourcegroup" {
return []byte(resourceGroup)
return []byte(resource.ResourceGroup)
}
if metaPartName == "namespace" {
@ -526,7 +591,7 @@ func formatAzureMonitorLegendKey(alias string, resourceName string, metricName s
}
if metaPartName == "resourcename" {
return []byte(resourceName)
return []byte(resource.ResourceName)
}
if metaPartName == "metric" {

@ -49,6 +49,7 @@ func TestAzureMonitorBuildQueries(t *testing.T) {
expectedBodyFilter string
expectedParamFilter string
expectedPortalURL *string
resources map[string]types.AzureMonitorResource
}{
{
name: "Parse queries from frontend and build AzureMonitor API queries",
@ -296,6 +297,16 @@ func TestAzureMonitorBuildQueries(t *testing.T) {
queries, err := datasource.buildQueries(log.New("test"), tsdbQuery, dsInfo)
require.NoError(t, err)
resources := map[string]types.AzureMonitorResource{}
if tt.azureMonitorVariedProperties["resources"] != nil {
resourceSlice := tt.azureMonitorVariedProperties["resources"].([]types.AzureMonitorResource)
for _, resource := range resourceSlice {
resources[fmt.Sprintf("/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s", resource.ResourceGroup, resource.ResourceName)] = resource
}
} else {
resources["/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanastaging/providers/Microsoft.Compute/virtualMachines/grafana"] = types.AzureMonitorResource{ResourceGroup: "grafanastaging", ResourceName: "grafana"}
}
azureMonitorQuery := &types.AzureMonitorQuery{
URL: tt.expectedURL,
Target: tt.azureMonitorQueryTarget,
@ -305,7 +316,9 @@ func TestAzureMonitorBuildQueries(t *testing.T) {
From: fromStart,
To: fromStart.Add(34 * time.Minute),
},
BodyFilter: tt.expectedBodyFilter,
BodyFilter: tt.expectedBodyFilter,
Subscription: "12345678-aaaa-bbbb-cccc-123456789abc",
Resources: resources,
}
assert.Equal(t, tt.expectedParamFilter, queries[0].Params.Get("$filter"))
@ -354,6 +367,10 @@ func TestCustomNamespace(t *testing.T) {
}
func TestAzureMonitorParseResponse(t *testing.T) {
resources := map[string]types.AzureMonitorResource{}
resources["/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanastaging/providers/Microsoft.Compute/virtualMachines/grafana"] = types.AzureMonitorResource{ResourceGroup: "grafanastaging", ResourceName: "grafana"}
subscription := "12345678-aaaa-bbbb-cccc-123456789abc"
tests := []struct {
name string
responseFile string
@ -369,6 +386,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Average"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -379,6 +398,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Total"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -389,6 +410,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Maximum"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -399,6 +422,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Minimum"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -409,6 +434,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Count"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -419,6 +446,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Average"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -430,6 +459,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Total"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -441,17 +472,21 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Average"},
},
Resources: resources,
Subscription: subscription,
},
},
{
name: "multiple dimension time series response with label alias",
responseFile: "azuremonitor/7-azure-monitor-response-multi-dimension.json",
mockQuery: &types.AzureMonitorQuery{
URL: "/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanastaging/providers/Microsoft.Compute/virtualMachines/grafana/providers/microsoft.insights/metrics",
URL: "/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanatest/providers/Microsoft.Storage/storageAccounts/testblobaccount/blobServices/default/providers/Microsoft.Insights/metrics",
Alias: "{{resourcegroup}} {Blob Type={{blobtype}}, Tier={{Tier}}}",
Params: url.Values{
"aggregation": {"Average"},
},
Resources: map[string]types.AzureMonitorResource{"/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanatest/providers/Microsoft.Storage/storageAccounts/testblobaccount/blobServices/default/providers/Microsoft.Insights/metrics": {ResourceGroup: "grafanatest", ResourceName: "testblobaccount"}},
Subscription: subscription,
},
},
{
@ -463,6 +498,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Average"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -474,6 +511,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Total"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -485,6 +524,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Total"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -495,6 +536,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Average"},
},
Resources: resources,
Subscription: subscription,
},
},
{
@ -505,6 +548,8 @@ func TestAzureMonitorParseResponse(t *testing.T) {
Params: url.Values{
"aggregation": {"Average"},
},
Resources: resources,
Subscription: subscription,
},
},
}

@ -4,7 +4,7 @@
"interval": "PT1H",
"value": [
{
"id": "/subscriptions/44693801-6ee6-49de-9b2d-9106972f9572/resourceGroups/danieltest/providers/Microsoft.Storage/storageAccounts/danieltestdiag187/blobServices/default/providers/Microsoft.Insights/metrics/BlobCapacity",
"id": "/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanatest/providers/Microsoft.Storage/storageAccounts/testblobaccount/blobServices/default/providers/Microsoft.Insights/metrics/BlobCapacity",
"type": "Microsoft.Insights/metrics",
"name": {
"value": "BlobCapacity",

@ -62,7 +62,7 @@
{
"title": "View in Azure Portal",
"targetBlank": true,
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanastaging%2Fproviders%2FMicrosoft.Compute%2FvirtualMachines%2Fgrafana%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22grafana%22%7D%7D%5D%7D%5D%7D"
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanatest%2Fproviders%2FMicrosoft.Storage%2FstorageAccounts%2Ftestblobaccount%2FblobServices%2Fdefault%2Fproviders%2FMicrosoft.Insights%2Fmetrics%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22default%22%7D%7D%5D%7D%5D%7D"
}
]
}
@ -79,13 +79,13 @@
"tier": "Standard"
},
"config": {
"displayName": "danieltest {Blob Type=PageBlob, Tier=Standard}",
"displayName": "grafanatest {Blob Type=PageBlob, Tier=Standard}",
"unit": "decbytes",
"links": [
{
"title": "View in Azure Portal",
"targetBlank": true,
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanastaging%2Fproviders%2FMicrosoft.Compute%2FvirtualMachines%2Fgrafana%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22grafana%22%7D%7D%5D%7D%5D%7D"
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanatest%2Fproviders%2FMicrosoft.Storage%2FstorageAccounts%2Ftestblobaccount%2FblobServices%2Fdefault%2Fproviders%2FMicrosoft.Insights%2Fmetrics%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22default%22%7D%7D%5D%7D%5D%7D"
}
]
}
@ -121,7 +121,7 @@
{
"title": "View in Azure Portal",
"targetBlank": true,
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanastaging%2Fproviders%2FMicrosoft.Compute%2FvirtualMachines%2Fgrafana%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22grafana%22%7D%7D%5D%7D%5D%7D"
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanatest%2Fproviders%2FMicrosoft.Storage%2FstorageAccounts%2Ftestblobaccount%2FblobServices%2Fdefault%2Fproviders%2FMicrosoft.Insights%2Fmetrics%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22default%22%7D%7D%5D%7D%5D%7D"
}
]
}
@ -138,13 +138,13 @@
"tier": "Hot"
},
"config": {
"displayName": "danieltest {Blob Type=BlockBlob, Tier=Hot}",
"displayName": "grafanatest {Blob Type=BlockBlob, Tier=Hot}",
"unit": "decbytes",
"links": [
{
"title": "View in Azure Portal",
"targetBlank": true,
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanastaging%2Fproviders%2FMicrosoft.Compute%2FvirtualMachines%2Fgrafana%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22grafana%22%7D%7D%5D%7D%5D%7D"
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanatest%2Fproviders%2FMicrosoft.Storage%2FstorageAccounts%2Ftestblobaccount%2FblobServices%2Fdefault%2Fproviders%2FMicrosoft.Insights%2Fmetrics%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22default%22%7D%7D%5D%7D%5D%7D"
}
]
}
@ -180,7 +180,7 @@
{
"title": "View in Azure Portal",
"targetBlank": true,
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanastaging%2Fproviders%2FMicrosoft.Compute%2FvirtualMachines%2Fgrafana%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22grafana%22%7D%7D%5D%7D%5D%7D"
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanatest%2Fproviders%2FMicrosoft.Storage%2FstorageAccounts%2Ftestblobaccount%2FblobServices%2Fdefault%2Fproviders%2FMicrosoft.Insights%2Fmetrics%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22default%22%7D%7D%5D%7D%5D%7D"
}
]
}
@ -197,13 +197,13 @@
"tier": "Cool"
},
"config": {
"displayName": "danieltest {Blob Type=Azure Data Lake Storage, Tier=Cool}",
"displayName": "grafanatest {Blob Type=Azure Data Lake Storage, Tier=Cool}",
"unit": "decbytes",
"links": [
{
"title": "View in Azure Portal",
"targetBlank": true,
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanastaging%2Fproviders%2FMicrosoft.Compute%2FvirtualMachines%2Fgrafana%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22grafana%22%7D%7D%5D%7D%5D%7D"
"url": "http://ds/#blade/Microsoft_Azure_MonitoringMetrics/Metrics.ReactView/Referer/MetricsExplorer/TimeContext/%7B%22absolute%22%3A%7B%22startTime%22%3A%220001-01-01T00%3A00%3A00Z%22%2C%22endTime%22%3A%220001-01-01T00%3A00%3A00Z%22%7D%7D/ChartDefinition/%7B%22v2charts%22%3A%5B%7B%22metrics%22%3A%5B%7B%22resourceMetadata%22%3A%7B%22id%22%3A%22%2Fsubscriptions%2F12345678-aaaa-bbbb-cccc-123456789abc%2FresourceGroups%2Fgrafanatest%2Fproviders%2FMicrosoft.Storage%2FstorageAccounts%2Ftestblobaccount%2FblobServices%2Fdefault%2Fproviders%2FMicrosoft.Insights%2Fmetrics%22%7D%2C%22name%22%3A%22%22%2C%22aggregationType%22%3A4%2C%22namespace%22%3A%22%22%2C%22metricVisualization%22%3A%7B%22displayName%22%3A%22%22%2C%22resourceDisplayName%22%3A%22default%22%7D%7D%5D%7D%5D%7D"
}
]
}

@ -65,14 +65,16 @@ 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
BodyFilter string
Dimensions []AzureMonitorDimensionFilter
URL string
Target string
Params url.Values
RefID string
Alias string
TimeRange backend.TimeRange
BodyFilter string
Dimensions []AzureMonitorDimensionFilter
Resources map[string]AzureMonitorResource
Subscription string
}
// AzureMonitorResponse is the json response from the Azure Monitor API
@ -274,4 +276,11 @@ type LogAnalyticsWorkspaceResponse struct {
RetentionInDays int `json:"retentionInDays"`
}
type SubscriptionsResponse struct {
ID string `json:"id"`
SubscriptionID string `json:"subscriptionId"`
TenantID string `json:"tenantId"`
DisplayName string `json:"displayName"`
}
var ErrorAzureHealthCheck = errors.New("health check failed")

Loading…
Cancel
Save