mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 09:47:54 +00:00
Breaking down some more components, adding tests.
* Some bug fixes found during testing/test repair. * Trying to tease apart the various responsibilities of `metricNamer` into smaller chunks and adding tests for each individual chunk. * Updating the `provider_test` and `series_registry_test` to fix failures.
This commit is contained in:
parent
76217a552b
commit
fc88e6e57a
18 changed files with 1038 additions and 516 deletions
96
pkg/custom-provider/query_builder.go
Normal file
96
pkg/custom-provider/query_builder.go
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package provider
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
||||
)
|
||||
|
||||
type QueryBuilder interface {
|
||||
BuildSelector(seriesName string, groupBy string, groupBySlice []string, queryParts []queryPart) (prom.Selector, error)
|
||||
}
|
||||
|
||||
type queryBuilder struct {
|
||||
metricsQueryTemplate *template.Template
|
||||
}
|
||||
|
||||
func NewQueryBuilder(metricsQuery string) (QueryBuilder, error) {
|
||||
metricsQueryTemplate, err := template.New("metrics-query").Delims("<<", ">>").Parse(metricsQuery)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse metrics query template %q: %v", metricsQuery, err)
|
||||
}
|
||||
|
||||
return &queryBuilder{
|
||||
metricsQueryTemplate: metricsQueryTemplate,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *queryBuilder) BuildSelector(seriesName string, groupBy string, groupBySlice []string, queryParts []queryPart) (prom.Selector, error) {
|
||||
//Convert our query parts into the types we need for our template.
|
||||
exprs, valuesByName := n.processQueryParts(queryParts)
|
||||
|
||||
args := queryTemplateArgs{
|
||||
Series: seriesName,
|
||||
LabelMatchers: strings.Join(exprs, ","),
|
||||
LabelValuesByName: valuesByName,
|
||||
GroupBy: groupBy,
|
||||
GroupBySlice: groupBySlice,
|
||||
}
|
||||
|
||||
selector, err := n.createSelectorFromTemplateArgs(args)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return selector, nil
|
||||
}
|
||||
|
||||
func (n *queryBuilder) createSelectorFromTemplateArgs(args queryTemplateArgs) (prom.Selector, error) {
|
||||
//Turn our template arguments into a Selector.
|
||||
queryBuff := new(bytes.Buffer)
|
||||
if err := n.metricsQueryTemplate.Execute(queryBuff, args); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if queryBuff.Len() == 0 {
|
||||
return "", fmt.Errorf("empty query produced by metrics query template")
|
||||
}
|
||||
|
||||
return prom.Selector(queryBuff.String()), nil
|
||||
}
|
||||
|
||||
func (n *queryBuilder) processQueryParts(queryParts []queryPart) ([]string, map[string][]string) {
|
||||
//Contains the expressions that we want to include as part of the query to Prometheus.
|
||||
//e.g. "namespace=my-namespace"
|
||||
//e.g. "some_label=some-value"
|
||||
var exprs []string
|
||||
|
||||
//Contains the list of label values we're targeting, by namespace.
|
||||
//e.g. "some_label" => ["value-one", "value-two"]
|
||||
valuesByName := map[string][]string{}
|
||||
|
||||
//Convert our query parts into template arguments.
|
||||
for _, qPart := range queryParts {
|
||||
//Be resilient against bad inputs.
|
||||
//We obviously can't generate label filters for these cases.
|
||||
if qPart.labelName == "" || len(qPart.values) == 0 {
|
||||
continue
|
||||
}
|
||||
targetValue := qPart.values[0]
|
||||
matcher := prom.LabelEq
|
||||
|
||||
if len(qPart.values) > 1 {
|
||||
targetValue = strings.Join(qPart.values, "|")
|
||||
matcher = prom.LabelMatches
|
||||
}
|
||||
|
||||
expression := matcher(qPart.labelName, targetValue)
|
||||
exprs = append(exprs, expression)
|
||||
valuesByName[qPart.labelName] = qPart.values
|
||||
}
|
||||
|
||||
return exprs, valuesByName
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue