mirror of https://github.com/grafana/grafana.git
add more tests at query parse level since feature toggle has been removed
Signed-off-by: bergquist <carl.bergquist@gmail.com>
This commit is contained in:
parent
30971834ee
commit
403e334590
|
|
@ -812,6 +812,501 @@ func TestAlignTimeRange(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseWithAdhocFilters(t *testing.T) {
|
||||||
|
_, span := tracer.Start(context.Background(), "operation")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
t.Run("parsing query with adhoc filters", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "http_requests_total",
|
||||||
|
"refId": "A",
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "job",
|
||||||
|
"value": "prometheus",
|
||||||
|
"operator": "equals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "method",
|
||||||
|
"value": "get",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `http_requests_total{job="prometheus",method="get"}`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing query with adhoc filters using not-equals operator", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "http_requests_total{job=\"grafana\"}",
|
||||||
|
"refId": "A",
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "status",
|
||||||
|
"value": "500",
|
||||||
|
"operator": "not-equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `http_requests_total{job="grafana",status!="500"}`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing query with adhoc filters using one-of operator", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "http_requests_total",
|
||||||
|
"refId": "A",
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "status",
|
||||||
|
"values": ["200", "201", "202"],
|
||||||
|
"operator": "one-of"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `http_requests_total{status=~"200|201|202"}`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing complex query with adhoc filters", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "rate(http_requests_total{job=\"prometheus\"}[5m]) + rate(http_errors_total{job=\"grafana\"}[5m])",
|
||||||
|
"refId": "A",
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "environment",
|
||||||
|
"value": "production",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `rate(http_requests_total{environment="production",job="prometheus"}[5m]) + rate(http_errors_total{environment="production",job="grafana"}[5m])`, res.Expr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseWithScopes(t *testing.T) {
|
||||||
|
_, span := tracer.Start(context.Background(), "operation")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
t.Run("parsing query with scope filters", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "http_requests_total",
|
||||||
|
"refId": "A",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "production-scope",
|
||||||
|
"title": "Production Environment",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": "environment",
|
||||||
|
"value": "production",
|
||||||
|
"operator": "equals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "region",
|
||||||
|
"value": "us-west-2",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `http_requests_total{environment="production",region="us-west-2"}`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing query with multiple scopes having same filter key", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "http_requests_total",
|
||||||
|
"refId": "A",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "namespace-scope-1",
|
||||||
|
"title": "Default Namespace",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": "namespace",
|
||||||
|
"value": "default",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "namespace-scope-2",
|
||||||
|
"title": "Kube System Namespace",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": "namespace",
|
||||||
|
"value": "kube-system",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `http_requests_total{namespace=~"default|kube-system"}`, res.Expr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseWithScopesAndAdhocFilters(t *testing.T) {
|
||||||
|
_, span := tracer.Start(context.Background(), "operation")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
t.Run("parsing query with both scopes and adhoc filters", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "http_requests_total",
|
||||||
|
"refId": "A",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "production-scope",
|
||||||
|
"title": "Production Environment",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": "environment",
|
||||||
|
"value": "production",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "job",
|
||||||
|
"value": "prometheus",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `http_requests_total{environment="production",job="prometheus"}`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("adhoc filters override scope filters on conflict", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "http_requests_total",
|
||||||
|
"refId": "A",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "staging-scope",
|
||||||
|
"title": "Staging Environment",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": "environment",
|
||||||
|
"value": "staging",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "environment",
|
||||||
|
"value": "production",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `http_requests_total{environment="production"}`, res.Expr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseWithGroupByKeys(t *testing.T) {
|
||||||
|
_, span := tracer.Start(context.Background(), "operation")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
t.Run("parsing query with group by keys", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "sum(http_requests_total)",
|
||||||
|
"refId": "A",
|
||||||
|
"groupByKeys": ["job", "instance"]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `sum by (job, instance) (http_requests_total)`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing query with group by keys and existing group by", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "sum by (job) (http_requests_total)",
|
||||||
|
"refId": "A",
|
||||||
|
"groupByKeys": ["status"]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `sum by (job, status) (http_requests_total)`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing query with filters and group by keys", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "sum(http_requests_total)",
|
||||||
|
"refId": "A",
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "job",
|
||||||
|
"value": "prometheus",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groupByKeys": ["status", "method"]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `sum by (status, method) (http_requests_total{job="prometheus"})`, res.Expr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseComplexScenariosWithFilters(t *testing.T) {
|
||||||
|
_, span := tracer.Start(context.Background(), "operation")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
t.Run("parsing query with regex filters and variables", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(48 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "rate(http_requests_total[$__interval])",
|
||||||
|
"refId": "A",
|
||||||
|
"intervalMs": 60000,
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "job",
|
||||||
|
"value": "prometheus.*",
|
||||||
|
"operator": "regex-match"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
Interval: time.Minute,
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `rate(http_requests_total{job=~"prometheus.*"}[2m])`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing query with complex expression, scopes, adhoc filters, and group by", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m])) * 100",
|
||||||
|
"refId": "A",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "production-scope",
|
||||||
|
"title": "Production Environment",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": "environment",
|
||||||
|
"value": "production",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "region",
|
||||||
|
"values": ["us-west-1", "us-west-2", "us-east-1"],
|
||||||
|
"operator": "one-of"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groupByKeys": ["job"]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `sum by (job) (rate(http_requests_total{environment="production",region=~"us-west-1|us-west-2|us-east-1"}[5m])) / sum by (job) (rate(http_requests_total{environment="production",region=~"us-west-1|us-west-2|us-east-1"}[5m])) * 100`, res.Expr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("parsing query with __name__ selector and filters", func(t *testing.T) {
|
||||||
|
timeRange := backend.TimeRange{
|
||||||
|
From: now,
|
||||||
|
To: now.Add(12 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
queryJson := `{
|
||||||
|
"expr": "{__name__=\"http_requests_total\"}",
|
||||||
|
"refId": "A",
|
||||||
|
"adhocFilters": [
|
||||||
|
{
|
||||||
|
"key": "namespace",
|
||||||
|
"value": "monitoring",
|
||||||
|
"operator": "equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
q := backend.DataQuery{
|
||||||
|
JSON: []byte(queryJson),
|
||||||
|
TimeRange: timeRange,
|
||||||
|
RefID: "A",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `{__name__="http_requests_total",namespace="monitoring"}`, res.Expr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestQueryTypeDefinitions(t *testing.T) {
|
func TestQueryTypeDefinitions(t *testing.T) {
|
||||||
builder, err := schemabuilder.NewSchemaBuilder(
|
builder, err := schemabuilder.NewSchemaBuilder(
|
||||||
schemabuilder.BuilderOptions{
|
schemabuilder.BuilderOptions{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue