Bläddra i källkod

azuremonitor: simple alerting for Azure Monitor API

Lots of edge cases and functionality left to implement but
a simple query works for alerting now.
Daniel Lee 6 år sedan
förälder
incheckning
10194df112

+ 29 - 10
pkg/tsdb/azuremonitor/azuremonitor.go

@@ -11,8 +11,8 @@ import (
 	"path"
 	"path"
 	"time"
 	"time"
 
 
-	// "github.com/grafana/grafana/pkg/components/null"
 	"github.com/grafana/grafana/pkg/api/pluginproxy"
 	"github.com/grafana/grafana/pkg/api/pluginproxy"
+	"github.com/grafana/grafana/pkg/components/null"
 	"github.com/grafana/grafana/pkg/components/simplejson"
 	"github.com/grafana/grafana/pkg/components/simplejson"
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/models"
@@ -113,10 +113,12 @@ func (e *AzureMonitorExecutor) buildQueries(tsdbQuery *tsdb.TsdbQuery) ([]*Azure
 
 
 		azureMonitorTarget := query.Model.Get("azureMonitor").MustMap()
 		azureMonitorTarget := query.Model.Get("azureMonitor").MustMap()
 
 
-		resourceGroup := azureMonitorTarget["resourceGroup"].(string)
-		metricDefinition := azureMonitorTarget["metricDefinition"].(string)
-		resourceName := azureMonitorTarget["resourceName"].(string)
-		azureURL := fmt.Sprintf("resourceGroups/%s/providers/%s/%s/providers/microsoft.insights/metrics", resourceGroup, metricDefinition, resourceName)
+		urlComponents := make(map[string]string)
+		urlComponents["resourceGroup"] = azureMonitorTarget["resourceGroup"].(string)
+		urlComponents["metricDefinition"] = azureMonitorTarget["metricDefinition"].(string)
+		urlComponents["resourceName"] = azureMonitorTarget["resourceName"].(string)
+
+		azureURL := fmt.Sprintf("resourceGroups/%s/providers/%s/%s/providers/microsoft.insights/metrics", urlComponents["resourceGroup"], urlComponents["metricDefinition"], urlComponents["resourceName"])
 
 
 		alias := azureMonitorTarget["alias"].(string)
 		alias := azureMonitorTarget["alias"].(string)
 
 
@@ -133,11 +135,12 @@ func (e *AzureMonitorExecutor) buildQueries(tsdbQuery *tsdb.TsdbQuery) ([]*Azure
 		}
 		}
 
 
 		azureMonitorQueries = append(azureMonitorQueries, &AzureMonitorQuery{
 		azureMonitorQueries = append(azureMonitorQueries, &AzureMonitorQuery{
-			URL:    azureURL,
-			Target: target,
-			Params: params,
-			RefID:  query.RefId,
-			Alias:  alias,
+			URL:           azureURL,
+			UrlComponents: urlComponents,
+			Target:        target,
+			Params:        params,
+			RefID:         query.RefId,
+			Alias:         alias,
 		})
 		})
 	}
 	}
 
 
@@ -247,5 +250,21 @@ func (e *AzureMonitorExecutor) unmarshalResponse(res *http.Response) (AzureMonit
 func (e *AzureMonitorExecutor) parseResponse(queryRes *tsdb.QueryResult, data AzureMonitorResponse, query *AzureMonitorQuery) error {
 func (e *AzureMonitorExecutor) parseResponse(queryRes *tsdb.QueryResult, data AzureMonitorResponse, query *AzureMonitorQuery) error {
 	slog.Info("AzureMonitor", "Response", data)
 	slog.Info("AzureMonitor", "Response", data)
 
 
+	for _, series := range data.Value {
+		points := make([]tsdb.TimePoint, 0)
+
+		defaultMetricName := fmt.Sprintf("%s.%s", query.UrlComponents["resourceName"], series.Name.LocalizedValue)
+
+		for _, point := range series.Timeseries[0].Data {
+			value := point.Average
+			points = append(points, tsdb.NewTimePoint(null.FloatFrom(value), float64((point.TimeStamp).Unix())*1000))
+		}
+
+		queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{
+			Name:   defaultMetricName,
+			Points: points,
+		})
+	}
+
 	return nil
 	return nil
 }
 }

+ 34 - 0
pkg/tsdb/azuremonitor/azuremonitor_test.go

@@ -1,7 +1,9 @@
 package azuremonitor
 package azuremonitor
 
 
 import (
 import (
+	"encoding/json"
 	"fmt"
 	"fmt"
+	"io/ioutil"
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
@@ -57,5 +59,37 @@ func TestAzureMonitor(t *testing.T) {
 				So(queries[0].Alias, ShouldEqual, "testalias")
 				So(queries[0].Alias, ShouldEqual, "testalias")
 			})
 			})
 		})
 		})
+
+		Convey("Parse AzureMonitor API response in the time series format", func() {
+			Convey("when data from query aggregated to one time series", func() {
+				data, err := loadTestFile("./test-data/1-azure-monitor-response.json")
+				So(err, ShouldBeNil)
+				So(data.Interval, ShouldEqual, "PT1M")
+
+				res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
+				query := &AzureMonitorQuery{
+					UrlComponents: map[string]string{
+						"resourceName": "grafana",
+					},
+				}
+				err = executor.parseResponse(res, data, query)
+				So(err, ShouldBeNil)
+
+				So(len(res.Series), ShouldEqual, 1)
+				So(res.Series[0].Name, ShouldEqual, "grafana.Percentage CPU")
+				So(len(res.Series[0].Points), ShouldEqual, 5)
+			})
+		})
 	})
 	})
 }
 }
+
+func loadTestFile(path string) (AzureMonitorResponse, error) {
+	var data AzureMonitorResponse
+
+	jsonBody, err := ioutil.ReadFile(path)
+	if err != nil {
+		return data, err
+	}
+	err = json.Unmarshal(jsonBody, &data)
+	return data, err
+}

+ 47 - 0
pkg/tsdb/azuremonitor/test-data/1-azure-monitor-response.json

@@ -0,0 +1,47 @@
+{
+  "cost": 0,
+  "timespan": "2019-02-08T10:13:50Z\/2019-02-08T16:13:50Z",
+  "interval": "PT1M",
+  "value": [
+    {
+      "id": "\/subscriptions\/44693801-6ee6-49de-9b2d-9106972f9572\/resourceGroups\/grafanastaging\/providers\/Microsoft.Compute\/virtualMachines\/grafana\/providers\/Microsoft.Insights\/metrics\/Percentage CPU",
+      "type": "Microsoft.Insights\/metrics",
+      "name": {
+        "value": "Percentage CPU",
+        "localizedValue": "Percentage CPU"
+      },
+      "unit": "Percent",
+      "timeseries": [
+        {
+          "metadatavalues": [
+
+          ],
+          "data": [
+            {
+              "timeStamp": "2019-02-08T10:13:00Z",
+              "average": 2.0875
+            },
+            {
+              "timeStamp": "2019-02-08T10:14:00Z",
+              "average": 2.1525
+            },
+            {
+              "timeStamp": "2019-02-08T10:15:00Z",
+              "average": 2.155
+            },
+            {
+              "timeStamp": "2019-02-08T10:16:00Z",
+              "average": 3.6925
+            },
+            {
+              "timeStamp": "2019-02-08T10:17:00Z",
+              "average": 2.44
+            }
+          ]
+        }
+      ]
+    }
+  ],
+  "namespace": "Microsoft.Compute\/virtualMachines",
+  "resourceregion": "westeurope"
+}

+ 6 - 5
pkg/tsdb/azuremonitor/types.go

@@ -8,11 +8,12 @@ import (
 // AzureMonitorQuery is the query for all the services as they have similar queries
 // AzureMonitorQuery is the query for all the services as they have similar queries
 // with a url, a querystring and an alias field
 // with a url, a querystring and an alias field
 type AzureMonitorQuery struct {
 type AzureMonitorQuery struct {
-	URL    string
-	Target string
-	Params url.Values
-	RefID  string
-	Alias  string
+	URL           string
+	UrlComponents map[string]string
+	Target        string
+	Params        url.Values
+	RefID         string
+	Alias         string
 }
 }
 
 
 // AzureMonitorResponse is the json response from the Azure Monitor API
 // AzureMonitorResponse is the json response from the Azure Monitor API

+ 2 - 1
public/app/plugins/datasource/grafana-azure-monitor-datasource/plugin.json

@@ -158,5 +158,6 @@
   },
   },
 
 
   "metrics": true,
   "metrics": true,
-  "annotations": true
+  "annotations": true,
+  "alerting": true
 }
 }