Commit 4c88db3e by bergquist

feat(prometheus): add support for legend formatting

parent 43d8bd5a
...@@ -111,7 +111,7 @@ func (c *QueryCondition) getRequestForAlertRule(datasource *m.DataSource, timera ...@@ -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,
......
...@@ -54,7 +54,7 @@ func (e *GraphiteExecutor) Execute(queries tsdb.QuerySlice, context *tsdb.QueryC ...@@ -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 {
......
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
......
...@@ -3,6 +3,8 @@ package prometheus ...@@ -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 ...@@ -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(context.Background(), query.Expr, timeRange)
value, err := client.QueryRange(ctx, "counters_logins", 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 { ...@@ -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,
}) })
} }
......
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}}")
})
})
}
package prometheus package prometheus
import "time"
type PrometheusQuery struct {
Expr string
Step time.Duration
LegendFormat string
}
...@@ -113,7 +113,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS ...@@ -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));
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment