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

feat(prometheus): add support for legend formatting

bergquist 9 лет назад
Родитель
Сommit
4c88db3e43

+ 1 - 1
pkg/services/alerting/conditions/query.go

@@ -111,7 +111,7 @@ func (c *QueryCondition) getRequestForAlertRule(datasource *m.DataSource, timera
 		Queries: []*tsdb.Query{
 		Queries: []*tsdb.Query{
 			{
 			{
 				RefId: "A",
 				RefId: "A",
-				Query: c.Query.Model.Get("target").MustString(),
+				Model: c.Query.Model,
 				DataSource: &tsdb.DataSourceInfo{
 				DataSource: &tsdb.DataSourceInfo{
 					Id:                datasource.Id,
 					Id:                datasource.Id,
 					Name:              datasource.Name,
 					Name:              datasource.Name,

+ 1 - 1
pkg/tsdb/graphite/graphite.go

@@ -54,7 +54,7 @@ func (e *GraphiteExecutor) Execute(queries tsdb.QuerySlice, context *tsdb.QueryC
 	}
 	}
 
 
 	for _, query := range queries {
 	for _, query := range queries {
-		formData["target"] = []string{query.Query}
+		formData["target"] = []string{query.Model.Get("target").MustString()}
 	}
 	}
 
 
 	if setting.Env == setting.DEV {
 	if setting.Env == setting.DEV {

+ 3 - 0
pkg/tsdb/models.go

@@ -1,8 +1,11 @@
 package tsdb
 package tsdb
 
 
+import "github.com/grafana/grafana/pkg/components/simplejson"
+
 type Query struct {
 type Query struct {
 	RefId      string
 	RefId      string
 	Query      string
 	Query      string
+	Model      *simplejson.Json
 	Depends    []string
 	Depends    []string
 	DataSource *DataSourceInfo
 	DataSource *DataSourceInfo
 	Results    []*TimeSeries
 	Results    []*TimeSeries

+ 35 - 6
pkg/tsdb/prometheus/prometheus.go

@@ -3,6 +3,8 @@ package prometheus
 import (
 import (
 	"context"
 	"context"
 	"net/http"
 	"net/http"
+	"regexp"
+	"strings"
 	"time"
 	"time"
 
 
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/log"
@@ -53,25 +55,52 @@ func (e *PrometheusExecutor) Execute(queries tsdb.QuerySlice, queryContext *tsdb
 
 
 	from, _ := queryContext.TimeRange.FromTime()
 	from, _ := queryContext.TimeRange.FromTime()
 	to, _ := queryContext.TimeRange.ToTime()
 	to, _ := queryContext.TimeRange.ToTime()
+
+	query := parseQuery(queries)
+
 	timeRange := prometheus.Range{
 	timeRange := prometheus.Range{
 		Start: from,
 		Start: from,
 		End:   to,
 		End:   to,
-		Step:  time.Second,
+		Step:  query.Step,
 	}
 	}
 
 
-	ctx := context.Background()
-	value, err := client.QueryRange(ctx, "counters_logins", timeRange)
+	value, err := client.QueryRange(context.Background(), query.Expr, timeRange)
 
 
 	if err != nil {
 	if err != nil {
 		result.Error = err
 		result.Error = err
 		return result
 		return result
 	}
 	}
 
 
-	result.QueryResults = parseResponse(value)
+	result.QueryResults = parseResponse(value, query)
 	return result
 	return result
 }
 }
 
 
-func parseResponse(value pmodel.Value) map[string]*tsdb.QueryResult {
+func formatLegend(metric pmodel.Metric, query PrometheusQuery) string {
+	r, _ := regexp.Compile(`\{\{\s*(.+?)\s*\}\}`)
+
+	result := r.ReplaceAllFunc([]byte(query.LegendFormat), func(in []byte) []byte {
+		ind := strings.Replace(strings.Replace(string(in), "{{", "", 1), "}}", "", 1)
+		if val, exists := metric[pmodel.LabelName(ind)]; exists {
+			return []byte(val)
+		}
+
+		return in
+	})
+
+	return string(result)
+}
+
+func parseQuery(queries tsdb.QuerySlice) PrometheusQuery {
+	queryModel := queries[0]
+
+	return PrometheusQuery{
+		Expr:         queryModel.Model.Get("expr").MustString(),
+		Step:         time.Second * time.Duration(queryModel.Model.Get("step").MustInt64(1)),
+		LegendFormat: queryModel.Model.Get("legendFormat").MustString(),
+	}
+}
+
+func parseResponse(value pmodel.Value, query PrometheusQuery) map[string]*tsdb.QueryResult {
 	queryResults := make(map[string]*tsdb.QueryResult)
 	queryResults := make(map[string]*tsdb.QueryResult)
 	queryRes := &tsdb.QueryResult{}
 	queryRes := &tsdb.QueryResult{}
 
 
@@ -86,7 +115,7 @@ func parseResponse(value pmodel.Value) map[string]*tsdb.QueryResult {
 		}
 		}
 
 
 		queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{
 		queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{
-			Name:   v.Metric.String(),
+			Name:   formatLegend(v.Metric, query),
 			Points: points,
 			Points: points,
 		})
 		})
 	}
 	}

+ 26 - 0
pkg/tsdb/prometheus/prometheus_test.go

@@ -0,0 +1,26 @@
+package prometheus
+
+import (
+	"testing"
+
+	p "github.com/prometheus/common/model"
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+func TestPrometheus(t *testing.T) {
+	Convey("Prometheus", t, func() {
+
+		Convey("converting metric name", func() {
+			metric := map[p.LabelName]p.LabelValue{
+				p.LabelName("app"):    p.LabelValue("backend"),
+				p.LabelName("device"): p.LabelValue("mobile"),
+			}
+
+			query := PrometheusQuery{
+				LegendFormat: "legend {{app}} {{device}} {{broken}}",
+			}
+
+			So(formatLegend(metric, query), ShouldEqual, "legend backend mobile {{broken}}")
+		})
+	})
+}

+ 8 - 0
pkg/tsdb/prometheus/types.go

@@ -1 +1,9 @@
 package prometheus
 package prometheus
+
+import "time"
+
+type PrometheusQuery struct {
+	Expr         string
+	Step         time.Duration
+	LegendFormat string
+}

+ 0 - 1
public/app/plugins/datasource/prometheus/datasource.ts

@@ -113,7 +113,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
           throw response.error;
           throw response.error;
         }
         }
         delete self.lastErrors.query;
         delete self.lastErrors.query;
-
         _.each(response.data.data.result, function(metricData) {
         _.each(response.data.data.result, function(metricData) {
           result.push(self.transformMetricData(metricData, activeTargets[index], start, end));
           result.push(self.transformMetricData(metricData, activeTargets[index], start, end));
         });
         });