-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6fff6bb
commit 4d0e2f9
Showing
4 changed files
with
237 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package variables | ||
|
||
// PromQLFuncLabelNames is the label_names function in Grafana | ||
type GrafanaFuncLabelNames struct { | ||
MetricRegexp string | ||
} | ||
|
||
// PromQLFuncLabelValues is the label_values function in Grafana | ||
type GrafanaFuncLabelValues struct { | ||
Metric string | ||
Label string | ||
} | ||
|
||
// PromQLFuncQueryResult is the query_result function in Grafana | ||
type GrafanaFuncQueryResult struct { | ||
Query string | ||
} | ||
|
||
// PromQLFuncMetrics is the metrics function in Grafana | ||
type GrafanaFuncMetrics struct { | ||
MetricRegexp string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package variables | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
) | ||
|
||
var ( | ||
// PromQLLabelNamesFuncName is the label_names function in Grafana | ||
PrometheusLabelNamesRegex = regexp.MustCompile(`^label_names\(\)\s*$`) | ||
|
||
// PromQLLabelValuesFuncName is the label_values function in Grafana | ||
PrometheusLabelValuesRegex = regexp.MustCompile(`^label_values\((?:(.+),\s*)?([a-zA-Z_$][a-zA-Z0-9_]*)\)\s*$`) | ||
|
||
// PromQLMetricsFuncName is the metrics function in Grafana | ||
PrometheusMetricNamesRegex = regexp.MustCompile(`^metrics\((.+)\)\s*$`) | ||
|
||
// PromQLQueryResultFuncName is the query_result function in Grafana | ||
PrometheusQueryResultRegex = regexp.MustCompile(`^query_result\((.+)\)\s*$`) | ||
|
||
// PromQLLabelNamesFuncNameWithMatch is the label_names function in Grafana | ||
PrometheusLabelNamesRegexWithMatch = regexp.MustCompile(`^label_names\((.+)\)\s*$`) | ||
) | ||
|
||
const ( | ||
// PrometheusLabelNamesFuncName is the label_names function name in Grafana | ||
PrometheusLabelNamesFuncName = "label_names" | ||
|
||
// PrometheusLabelValuesFuncName is the label_values function name in Grafana | ||
PrometheusLabelValuesFuncName = "label_values" | ||
|
||
// PrometheusMetricsFuncName is the metrics function name in Grafana | ||
PrometheusMetricNamesFuncName = "metrics" | ||
|
||
// PrometheusQueryResultFuncName is the query_result function name in Grafana | ||
PrometheusQueryResultFuncName = "query_result" | ||
) | ||
|
||
type GrafanaVariable struct { | ||
Expr string | ||
FuncName string | ||
Func interface{} | ||
} | ||
|
||
func ParseGrafanaVariable(expr string) (*GrafanaVariable, error) { | ||
switch { | ||
case PrometheusLabelValuesRegex.MatchString(expr): | ||
match := PrometheusLabelValuesRegex.FindStringSubmatch(expr) | ||
if len(match) != 3 { | ||
return nil, fmt.Errorf("failed to get label from variable: %s", expr) | ||
} | ||
return &GrafanaVariable{ | ||
Expr: expr, | ||
FuncName: PrometheusLabelValuesFuncName, | ||
Func: &GrafanaFuncLabelValues{ | ||
Metric: match[1], | ||
Label: match[2], | ||
}, | ||
}, nil | ||
case PrometheusQueryResultRegex.MatchString(expr): | ||
match := PrometheusQueryResultRegex.FindStringSubmatch(expr) | ||
if len(match) != 2 { | ||
return nil, fmt.Errorf("failed to get query: %s", expr) | ||
} | ||
return &GrafanaVariable{ | ||
Expr: expr, | ||
FuncName: PrometheusQueryResultFuncName, | ||
Func: &GrafanaFuncQueryResult{ | ||
Query: match[1], | ||
}, | ||
}, nil | ||
case PrometheusMetricNamesRegex.MatchString(expr): | ||
match := PrometheusMetricNamesRegex.FindStringSubmatch(expr) | ||
if len(match) != 2 { | ||
return nil, fmt.Errorf("failed to get metric: %s", expr) | ||
} | ||
return &GrafanaVariable{ | ||
Expr: expr, | ||
FuncName: PrometheusMetricNamesFuncName, | ||
Func: &GrafanaFuncMetrics{ | ||
MetricRegexp: match[1], | ||
}, | ||
}, nil | ||
case PrometheusLabelNamesRegexWithMatch.MatchString(expr): | ||
match := PrometheusLabelNamesRegexWithMatch.FindStringSubmatch(expr) | ||
if len(match) != 2 { | ||
return nil, fmt.Errorf("failed to get metric: %s", expr) | ||
} | ||
return &GrafanaVariable{ | ||
Expr: expr, | ||
FuncName: PrometheusLabelNamesFuncName, | ||
Func: &GrafanaFuncLabelNames{ | ||
MetricRegexp: match[1], | ||
}, | ||
}, nil | ||
case PrometheusLabelNamesRegex.MatchString(expr): | ||
return &GrafanaVariable{ | ||
Expr: expr, | ||
FuncName: PrometheusLabelNamesFuncName, | ||
Func: &GrafanaFuncLabelNames{ | ||
MetricRegexp: "", | ||
}, | ||
}, nil | ||
default: | ||
return &GrafanaVariable{ | ||
Expr: expr, | ||
FuncName: "", | ||
Func: nil, | ||
}, nil | ||
} | ||
} | ||
|
||
func toDQL(promExpr string) (string, error) { | ||
grafanaVariable, err := ParseGrafanaVariable(promExpr) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to parse grafana variable: %w", err) | ||
} | ||
|
||
switch grafanaVariable.FuncName { | ||
case PrometheusLabelNamesFuncName: | ||
return "", nil | ||
case PrometheusLabelValuesFuncName: | ||
return "", nil | ||
case PrometheusQueryResultFuncName: | ||
return "", nil | ||
case PrometheusMetricNamesFuncName: | ||
return "", nil | ||
default: | ||
return "", nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package variables | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestParseGrafanaVariable(t *testing.T) { | ||
tests := []struct { | ||
expr string | ||
wantErr bool | ||
}{ | ||
{ | ||
expr: "label_names(cpu_seconds_total)", | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: "label_names(cpu_seconds_.*)", | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: "label_values(cpu_seconds_total)", | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: "label_values(cpu_seconds_total, app)", | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: `label_values(cpu_seconds_total{namespace="$namespace"})`, | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: `label_values(cpu_seconds_total{namespace="$namespace"}, app)`, | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: "metrics(cpu_seconds_total)", | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: "metrics(cpu_seconds_.*)", | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: `query_result(cpu_seconds_total{namespace="$namespace"})`, | ||
wantErr: true, | ||
}, | ||
{ | ||
expr: `cpu_seconds_total{namespace="$namespace"}`, | ||
wantErr: true, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
dql, err := toDQL(tt.expr) | ||
if err != nil { | ||
if tt.wantErr { | ||
assert.Error(t, err) | ||
} else { | ||
assert.NoError(t, err) | ||
} | ||
continue | ||
} | ||
fmt.Println(dql) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters