Files
kubesphere/pkg/models/monitoring/expressions/prometheus.go
Guangzhe Huang 1fcb5116df update comment
2020-06-19 16:55:39 +08:00

99 lines
2.2 KiB
Go

package expressions
import (
"fmt"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/storage/metric"
)
func init() {
register("prometheus", labelReplace)
}
func labelReplace(input, ns string) (string, error) {
root, err := promql.ParseExpr(input)
if err != nil {
return "", err
}
setRecursive(root, ns)
if err != nil {
return "", err
}
return root.String(), nil
}
// Inspired by https://github.com/prometheus-community/prom-label-proxy
func setRecursive(node promql.Node, namespace string) (err error) {
switch n := node.(type) {
case *promql.EvalStmt:
if err := setRecursive(n.Expr, namespace); err != nil {
return err
}
case promql.Expressions:
for _, e := range n {
if err := setRecursive(e, namespace); err != nil {
return err
}
}
case *promql.AggregateExpr:
if err := setRecursive(n.Expr, namespace); err != nil {
return err
}
case *promql.BinaryExpr:
if err := setRecursive(n.LHS, namespace); err != nil {
return err
}
if err := setRecursive(n.RHS, namespace); err != nil {
return err
}
case *promql.Call:
if err := setRecursive(n.Args, namespace); err != nil {
return err
}
case *promql.ParenExpr:
if err := setRecursive(n.Expr, namespace); err != nil {
return err
}
case *promql.UnaryExpr:
if err := setRecursive(n.Expr, namespace); err != nil {
return err
}
case *promql.NumberLiteral, *promql.StringLiteral:
// nothing to do
case *promql.MatrixSelector:
n.LabelMatchers = enforceLabelMatchers(n.LabelMatchers, namespace)
case *promql.VectorSelector:
n.LabelMatchers = enforceLabelMatchers(n.LabelMatchers, namespace)
default:
return fmt.Errorf("promql.Walk: unhandled node type %T", node)
}
return err
}
func enforceLabelMatchers(matchers metric.LabelMatchers, namespace string) metric.LabelMatchers {
var found bool
for i, m := range matchers {
if m.Name == "namespace" {
matchers[i] = &metric.LabelMatcher{
Name: "namespace",
Type: metric.Equal,
Value: model.LabelValue(namespace),
}
found = true
break
}
}
if !found {
matchers = append(matchers, &metric.LabelMatcher{
Name: "namespace",
Type: metric.Equal,
Value: model.LabelValue(namespace),
})
}
return matchers
}