Просмотр исходного кода

Merge pull request #6290 from utkarshcmu/alerting_opentsdb

Opentsdb alerting feature completed, ready for testing
Carl Bergquist 9 лет назад
Родитель
Сommit
a1e97b0067
3 измененных файлов с 242 добавлено и 24 удалено
  1. 63 16
      pkg/tsdb/opentsdb/opentsdb.go
  2. 176 0
      pkg/tsdb/opentsdb/opentsdb_test.go
  3. 3 8
      pkg/tsdb/opentsdb/types.go

+ 63 - 16
pkg/tsdb/opentsdb/opentsdb.go

@@ -14,7 +14,6 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
-	//"net/http/httputil"
 	"encoding/json"
 	"encoding/json"
 
 
 	"gopkg.in/guregu/null.v3"
 	"gopkg.in/guregu/null.v3"
@@ -59,13 +58,9 @@ func (e *OpenTsdbExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice,
 	tsdbQuery.Start = queryContext.TimeRange.GetFromAsMsEpoch()
 	tsdbQuery.Start = queryContext.TimeRange.GetFromAsMsEpoch()
 	tsdbQuery.End = queryContext.TimeRange.GetToAsMsEpoch()
 	tsdbQuery.End = queryContext.TimeRange.GetToAsMsEpoch()
 
 
-	for _, query := range queries {
-		tsdbQuery.Queries = []OpenTsdbMetric{
-			OpenTsdbMetric{
-				Metric:     query.Model.Get("metric").MustString(),
-				Aggregator: query.Model.Get("aggregator").MustString(),
-			},
-		}
+  for _ , query := range queries {
+  	metric := e.buildMetric(query)
+  	tsdbQuery.Queries = append(tsdbQuery.Queries, metric)
 	}
 	}
 
 
 	if setting.Env == setting.DEV {
 	if setting.Env == setting.DEV {
@@ -109,14 +104,7 @@ func (e *OpenTsdbExecutor) createRequest(data OpenTsdbQuery) (*http.Request, err
 	if e.BasicAuth {
 	if e.BasicAuth {
 		req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword)
 		req.SetBasicAuth(e.BasicAuthUser, e.BasicAuthPassword)
 	}
 	}
-
-	/*
-	  requestDump, err := httputil.DumpRequest(req, true)
-	  if err != nil {
-	    fmt.Println(err)
-	  }
-	  fmt.Println(string(requestDump))
-	*/
+	
 	return req, err
 	return req, err
 }
 }
 
 
@@ -163,3 +151,62 @@ func (e *OpenTsdbExecutor) parseResponse(query OpenTsdbQuery, res *http.Response
 	queryResults["A"] = queryRes
 	queryResults["A"] = queryRes
 	return queryResults, nil
 	return queryResults, nil
 }
 }
+
+func (e *OpenTsdbExecutor) buildMetric(query *tsdb.Query) (map[string]interface{}) {
+
+	metric := make(map[string]interface{})
+
+		// Setting metric and aggregator		
+		metric["metric"] = query.Model.Get("metric").MustString()
+		metric["aggregator"] = query.Model.Get("aggregator").MustString()
+
+		// Setting downsampling options
+		disableDownsampling := query.Model.Get("disableDownsampling").MustBool()
+		if !disableDownsampling {
+			downsampleInterval := query.Model.Get("downsampleInterval").MustString()
+			if downsampleInterval == "" {
+				downsampleInterval = "1m"  //default value for blank
+			}
+			downsample :=  downsampleInterval + "-" + query.Model.Get("downsampleAggregator").MustString()
+			if query.Model.Get("downsampleFillPolicy").MustString() != "none" {
+				metric["downsample"] = downsample + "-" + query.Model.Get("downsampleFillPolicy").MustString()
+			} else {
+				metric["downsample"] = downsample
+			}
+		}
+
+		// Setting rate options
+		if query.Model.Get("shouldComputeRate").MustBool() {
+			
+			metric["rate"] = true
+			rateOptions := make(map[string]interface{})
+			rateOptions["counter"] = query.Model.Get("isCounter").MustBool()
+
+			counterMax, counterMaxCheck := query.Model.CheckGet("counterMax")
+			if counterMaxCheck {
+				rateOptions["counterMax"] = counterMax.MustFloat64()
+			}
+			
+			resetValue, resetValueCheck := query.Model.CheckGet("counterResetValue")
+			if resetValueCheck {
+				rateOptions["resetValue"] = resetValue.MustFloat64()
+			}
+
+			metric["rateOptions"] = rateOptions
+		}
+
+		// Setting tags
+		tags, tagsCheck := query.Model.CheckGet("tags")
+		if tagsCheck && len(tags.MustMap()) > 0 {
+			metric["tags"] = tags.MustMap()
+		}
+
+		// Setting filters
+		filters, filtersCheck := query.Model.CheckGet("filters")
+		if filtersCheck && len(filters.MustArray()) > 0 {
+			metric["filters"] = filters.MustArray()
+		}
+
+		return metric
+
+}

+ 176 - 0
pkg/tsdb/opentsdb/opentsdb_test.go

@@ -0,0 +1,176 @@
+package opentsdb
+
+import (
+	"testing"
+
+	"github.com/grafana/grafana/pkg/tsdb"
+	. "github.com/smartystreets/goconvey/convey"
+	"github.com/grafana/grafana/pkg/components/simplejson"
+)
+
+func TestOpenTsdbExecutor(t *testing.T) {
+	Convey("OpenTsdb query testing", t, func() {
+
+		exec := &OpenTsdbExecutor{}
+
+		Convey("Build metric with downsampling enabled", func() {
+
+			query := &tsdb.Query{
+				Model: simplejson.New(),
+			}
+
+			query.Model.Set("metric", "cpu.average.percent")
+			query.Model.Set("aggregator", "avg")
+			query.Model.Set("disableDownsampling", false)
+			query.Model.Set("downsampleInterval", "")
+			query.Model.Set("downsampleAggregator","avg")
+			query.Model.Set("downsampleFillPolicy","none")
+
+			metric := exec.buildMetric(query)
+
+			So(len(metric), ShouldEqual, 3)
+			So(metric["metric"], ShouldEqual, "cpu.average.percent")
+			So(metric["aggregator"], ShouldEqual, "avg")
+			So(metric["downsample"], ShouldEqual, "1m-avg")
+
+		})
+
+		Convey("Build metric with downsampling diabled", func() {
+
+			query := &tsdb.Query{
+				Model: simplejson.New(),
+			}
+
+			query.Model.Set("metric", "cpu.average.percent")
+			query.Model.Set("aggregator", "avg")
+			query.Model.Set("disableDownsampling", true)
+			query.Model.Set("downsampleInterval", "")
+			query.Model.Set("downsampleAggregator","avg")
+			query.Model.Set("downsampleFillPolicy","none")
+
+			metric := exec.buildMetric(query)
+
+			So(len(metric), ShouldEqual, 2)
+			So(metric["metric"], ShouldEqual, "cpu.average.percent")
+			So(metric["aggregator"], ShouldEqual, "avg")
+			
+		})
+
+		Convey("Build metric with downsampling enabled with params", func() {
+
+			query := &tsdb.Query{
+				Model: simplejson.New(),
+			}
+
+			query.Model.Set("metric", "cpu.average.percent")
+			query.Model.Set("aggregator", "avg")
+			query.Model.Set("disableDownsampling", false)
+			query.Model.Set("downsampleInterval", "5m")
+			query.Model.Set("downsampleAggregator","sum")
+			query.Model.Set("downsampleFillPolicy","null")
+
+			metric := exec.buildMetric(query)
+
+			So(len(metric), ShouldEqual, 3)
+			So(metric["metric"], ShouldEqual, "cpu.average.percent")
+			So(metric["aggregator"], ShouldEqual, "avg")
+			So(metric["downsample"], ShouldEqual, "5m-sum-null")
+		})
+
+		Convey("Build metric with tags with downsampling disabled", func() {
+
+			query := &tsdb.Query{
+				Model: simplejson.New(),
+			}
+
+			query.Model.Set("metric", "cpu.average.percent")
+			query.Model.Set("aggregator", "avg")
+			query.Model.Set("disableDownsampling", true)
+			query.Model.Set("downsampleInterval", "5m")
+			query.Model.Set("downsampleAggregator","sum")
+			query.Model.Set("downsampleFillPolicy","null")
+
+			tags := simplejson.New()
+			tags.Set("env", "prod")
+			tags.Set("app", "grafana")
+			query.Model.Set("tags", tags.MustMap())
+
+			metric := exec.buildMetric(query)
+
+			So(len(metric), ShouldEqual, 3)
+			So(metric["metric"], ShouldEqual, "cpu.average.percent")
+			So(metric["aggregator"], ShouldEqual, "avg")
+			So(metric["downsample"], ShouldEqual, nil)
+			So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2)
+			So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod")
+			So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana")
+			So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil)
+		})
+
+		Convey("Build metric with rate enabled but counter disabled", func() {
+
+			query := &tsdb.Query{
+				Model: simplejson.New(),
+			}
+
+			query.Model.Set("metric", "cpu.average.percent")
+			query.Model.Set("aggregator", "avg")
+			query.Model.Set("disableDownsampling", true)
+			query.Model.Set("shouldComputeRate", true)
+			query.Model.Set("isCounter",false)
+			
+			tags := simplejson.New()
+			tags.Set("env", "prod")
+			tags.Set("app", "grafana")
+			query.Model.Set("tags", tags.MustMap())
+
+			metric := exec.buildMetric(query)
+
+			So(len(metric), ShouldEqual, 5)
+			So(metric["metric"], ShouldEqual, "cpu.average.percent")
+			So(metric["aggregator"], ShouldEqual, "avg")
+			So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2)
+			So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod")
+			So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana")
+			So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil)
+			So(metric["rate"], ShouldEqual, true)
+			So(metric["rateOptions"].(map[string]interface{})["counter"], ShouldEqual, false)
+		})
+
+		Convey("Build metric with rate and counter enabled", func() {
+
+			query := &tsdb.Query{
+				Model: simplejson.New(),
+			}
+
+			query.Model.Set("metric", "cpu.average.percent")
+			query.Model.Set("aggregator", "avg")
+			query.Model.Set("disableDownsampling", true)
+			query.Model.Set("shouldComputeRate", true)
+			query.Model.Set("isCounter",true)
+			query.Model.Set("counterMax",45)
+			query.Model.Set("counterResetValue",60)
+
+			tags := simplejson.New()
+			tags.Set("env", "prod")
+			tags.Set("app", "grafana")
+			query.Model.Set("tags", tags.MustMap())
+
+			metric := exec.buildMetric(query)
+
+			So(len(metric), ShouldEqual, 5)
+			So(metric["metric"], ShouldEqual, "cpu.average.percent")
+			So(metric["aggregator"], ShouldEqual, "avg")
+			So(len(metric["tags"].(map[string]interface{})), ShouldEqual, 2)
+			So(metric["tags"].(map[string]interface{})["env"], ShouldEqual, "prod")
+			So(metric["tags"].(map[string]interface{})["app"], ShouldEqual, "grafana")
+			So(metric["tags"].(map[string]interface{})["ip"], ShouldEqual, nil)
+			So(metric["rate"], ShouldEqual, true)
+			So(len(metric["rateOptions"].(map[string]interface{})), ShouldEqual, 3)
+			So(metric["rateOptions"].(map[string]interface{})["counter"], ShouldEqual, true)
+			So(metric["rateOptions"].(map[string]interface{})["counterMax"], ShouldEqual, 45)
+			So(metric["rateOptions"].(map[string]interface{})["resetValue"], ShouldEqual, 60)
+		})
+
+	})
+}

+ 3 - 8
pkg/tsdb/opentsdb/types.go

@@ -1,14 +1,9 @@
 package opentsdb
 package opentsdb
 
 
 type OpenTsdbQuery struct {
 type OpenTsdbQuery struct {
-	Start	   int64     				 `json:"start"`
-	End		   int64   	 				 `json:"end"`
-	Queries  []OpenTsdbMetric  `json:"queries"`
-}
-
-type OpenTsdbMetric struct {
-	Metric      string  `json:"metric"`
-	Aggregator  string  `json:"aggregator"`
+	Start	   int64     				         `json:"start"`
+	End		   int64   	 				 				 `json:"end"`
+	Queries  []map[string]interface{}  `json:"queries"`
 }
 }
 
 
 type OpenTsdbResponse struct {
 type OpenTsdbResponse struct {