Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions pkg/promclient/filtermatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (
"github.com/prometheus/prometheus/promql/parser"
)

func NewFilterMatcherVisitor(ls model.LabelSet) *FilterMatcherVisitor {
func NewFilterMatcherVisitor(ls, extLs model.LabelSet) *FilterMatcherVisitor {
return &FilterMatcherVisitor{
ls: ls,
extLs: extLs,
filterMatch: true,
}
}
Expand All @@ -19,14 +20,15 @@ func NewFilterMatcherVisitor(ls model.LabelSet) *FilterMatcherVisitor {
type FilterMatcherVisitor struct {
l sync.Mutex
ls model.LabelSet
extLs model.LabelSet
filterMatch bool
}

// Visit checks if the given node matches the labels in the filter
func (l *FilterMatcherVisitor) Visit(node parser.Node, path []parser.Node) (w parser.Visitor, err error) {
switch nodeTyped := node.(type) {
case *parser.VectorSelector:
filteredMatchers, ok := FilterMatchers(l.ls, nodeTyped.LabelMatchers)
filteredMatchers, ok := FilterMatchers(l.ls, l.extLs, nodeTyped.LabelMatchers)
l.l.Lock()
l.filterMatch = l.filterMatch && ok
l.l.Unlock()
Expand All @@ -37,7 +39,7 @@ func (l *FilterMatcherVisitor) Visit(node parser.Node, path []parser.Node) (w pa
return nil, nil
}
case *parser.MatrixSelector:
filteredMatchers, ok := FilterMatchers(l.ls, nodeTyped.VectorSelector.(*parser.VectorSelector).LabelMatchers)
filteredMatchers, ok := FilterMatchers(l.ls, l.extLs, nodeTyped.VectorSelector.(*parser.VectorSelector).LabelMatchers)
l.l.Lock()
l.filterMatch = l.filterMatch && ok
l.l.Unlock()
Expand All @@ -54,7 +56,7 @@ func (l *FilterMatcherVisitor) Visit(node parser.Node, path []parser.Node) (w pa

// FilterMatchers applies the matchers to the given labelset to determine if there is a match
// and to return all remaining matchers to be matched
func FilterMatchers(ls model.LabelSet, matchers []*labels.Matcher) ([]*labels.Matcher, bool) {
func FilterMatchers(ls, extLs model.LabelSet, matchers []*labels.Matcher) ([]*labels.Matcher, bool) {
filteredMatchers := make([]*labels.Matcher, 0, len(matchers))

// Look over the matchers passed in, if any exist in our labels, we'll do the matcher, and then strip
Expand All @@ -64,6 +66,8 @@ func FilterMatchers(ls model.LabelSet, matchers []*labels.Matcher) ([]*labels.Ma
if !matcher.Matches(string(localValue)) {
return nil, false
}
} else if v, ok := extLs[model.LabelName(matcher.Name)]; ok && matcher.Matches(string(v)) {
continue // If the selector matches the external labels, we skip it
} else {
filteredMatchers = append(filteredMatchers, matcher)
}
Expand Down
61 changes: 40 additions & 21 deletions pkg/promclient/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,30 @@ func MergeLabelSets(a, b []model.LabelSet) []model.LabelSet {
return a
}

// AddLabelClient proxies a client and adds the given labels to all results
type AddLabelClient struct {
func NewAddLabelClient(api API, labels model.LabelSet, externalLabels model.LabelSet) *addLabelClient {
allLabels := labels.Clone().Merge(externalLabels)
return &addLabelClient{
API: api,
Labels: labels,
ExternalLabels: externalLabels,
allLabels: allLabels,
}
}

// addLabelClient proxies a client and adds the given labels to all results
type addLabelClient struct {
API
Labels model.LabelSet
Labels model.LabelSet
ExternalLabels model.LabelSet
allLabels model.LabelSet // All labels, including Labels and ExternalLabels
}

// Key defines the labelset which identifies this client
func (c *AddLabelClient) Key() model.LabelSet {
return c.Labels
func (c *addLabelClient) Key() model.LabelSet {
return c.allLabels
}

func (c *AddLabelClient) filterMatchers(matchers []string) ([]string, bool, error) {
func (c *addLabelClient) filterMatchers(matchers []string) ([]string, bool, error) {
ret := make([]string, 0, len(matchers))
for _, matcher := range matchers {
selectors, err := parser.ParseMetricSelector(matcher)
Expand All @@ -75,6 +87,8 @@ func (c *AddLabelClient) filterMatchers(matchers []string) ([]string, bool, erro
if !s.Matches(string(v)) {
return nil, false, nil
}
} else if v, ok := c.ExternalLabels[model.LabelName(s.Name)]; ok && s.Matches(string(v)) {
continue // If the selector matches the external labels, we skip it
} else { // Otherwise if the selector isn't part of the `Labels` we add; we pass it along
filteredSelectors = append(filteredSelectors, s)
}
Expand All @@ -93,7 +107,7 @@ func (c *AddLabelClient) filterMatchers(matchers []string) ([]string, bool, erro
}

// LabelNames returns all the unique label names present in the block in sorted order.
func (c *AddLabelClient) LabelNames(ctx context.Context, matchers []string, startTime time.Time, endTime time.Time) ([]string, v1.Warnings, error) {
func (c *addLabelClient) LabelNames(ctx context.Context, matchers []string, startTime time.Time, endTime time.Time) ([]string, v1.Warnings, error) {
matchers, ok, err := c.filterMatchers(matchers)
if err != nil {
return nil, nil, err
Expand All @@ -107,7 +121,7 @@ func (c *AddLabelClient) LabelNames(ctx context.Context, matchers []string, star
return nil, nil, err
}

for k := range c.Labels {
for k := range c.allLabels {
found := false
for _, labelName := range l {
if labelName == string(k) {
Expand All @@ -123,7 +137,7 @@ func (c *AddLabelClient) LabelNames(ctx context.Context, matchers []string, star
}

// LabelValues performs a query for the values of the given label.
func (c *AddLabelClient) LabelValues(ctx context.Context, label string, matchers []string, startTime time.Time, endTime time.Time) (model.LabelValues, v1.Warnings, error) {
func (c *addLabelClient) LabelValues(ctx context.Context, label string, matchers []string, startTime time.Time, endTime time.Time) (model.LabelValues, v1.Warnings, error) {
matchers, ok, err := c.filterMatchers(matchers)
if err != nil {
return nil, nil, err
Expand All @@ -138,22 +152,22 @@ func (c *AddLabelClient) LabelValues(ctx context.Context, label string, matchers
}

// do we have labels that match in our state
if value, ok := c.Labels[model.LabelName(label)]; ok {
if value, ok := c.allLabels[model.LabelName(label)]; ok {
return MergeLabelValues(val, model.LabelValues{value}), w, nil
}
return val, w, nil
}

// Query performs a query for the given time.
func (c *AddLabelClient) Query(ctx context.Context, query string, ts time.Time) (model.Value, v1.Warnings, error) {
func (c *addLabelClient) Query(ctx context.Context, query string, ts time.Time) (model.Value, v1.Warnings, error) {
// Parse out the promql query into expressions etc.
e, err := parser.ParseExpr(query)
if err != nil {
return nil, nil, err
}

// Walk the expression, to filter out any LabelMatchers that match etc.
filterVisitor := NewFilterMatcherVisitor(c.Labels)
filterVisitor := NewFilterMatcherVisitor(c.Labels, c.ExternalLabels)
if _, err := parser.Walk(ctx, filterVisitor, &parser.EvalStmt{Expr: e}, e, nil, nil); err != nil {
return nil, nil, err
}
Expand All @@ -165,22 +179,22 @@ func (c *AddLabelClient) Query(ctx context.Context, query string, ts time.Time)
if err != nil {
return nil, w, err
}
if err := promhttputil.ValueAddLabelSet(val, c.Labels); err != nil {
if err := promhttputil.ValueAddLabelSet(val, c.Labels, c.ExternalLabels); err != nil {
return nil, w, err
}
return val, w, nil
}

// QueryRange performs a query for the given range.
func (c *AddLabelClient) QueryRange(ctx context.Context, query string, r v1.Range) (model.Value, v1.Warnings, error) {
func (c *addLabelClient) QueryRange(ctx context.Context, query string, r v1.Range) (model.Value, v1.Warnings, error) {
// Parse out the promql query into expressions etc.
e, err := parser.ParseExpr(query)
if err != nil {
return nil, nil, err
}

// Walk the expression, to filter out any LabelMatchers that match etc.
filterVisitor := NewFilterMatcherVisitor(c.Labels)
filterVisitor := NewFilterMatcherVisitor(c.Labels, c.ExternalLabels)
if _, err := parser.Walk(ctx, filterVisitor, &parser.EvalStmt{Expr: e}, e, nil, nil); err != nil {
return nil, nil, err
}
Expand All @@ -192,14 +206,14 @@ func (c *AddLabelClient) QueryRange(ctx context.Context, query string, r v1.Rang
if err != nil {
return nil, w, err
}
if err := promhttputil.ValueAddLabelSet(val, c.Labels); err != nil {
if err := promhttputil.ValueAddLabelSet(val, c.Labels, c.ExternalLabels); err != nil {
return nil, w, err
}
return val, w, nil
}

// Series finds series by label matchers.
func (c *AddLabelClient) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, v1.Warnings, error) {
func (c *addLabelClient) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, v1.Warnings, error) {
// Now we need to filter the matches sent to us for the labels associated with this
// servergroup
filteredMatches := make([]string, 0, len(matches))
Expand All @@ -211,7 +225,7 @@ func (c *AddLabelClient) Series(ctx context.Context, matches []string, startTime
}

// Walk the expression, to filter out any LabelMatchers that match etc.
filterVisitor := NewFilterMatcherVisitor(c.Labels)
filterVisitor := NewFilterMatcherVisitor(c.Labels, c.ExternalLabels)
if _, err := parser.Walk(ctx, filterVisitor, &parser.EvalStmt{Expr: e}, e, nil, nil); err != nil {
return nil, nil, err
}
Expand All @@ -238,14 +252,19 @@ func (c *AddLabelClient) Series(ctx context.Context, matches []string, startTime
for k, v := range c.Labels {
lset[k] = v
}
for k, v := range c.ExternalLabels {
if _, ok := lset[k]; !ok {
lset[k] = v
}
}
}

return v, w, nil
}

// GetValue loads the raw data for a given set of matchers in the time range
func (c *AddLabelClient) GetValue(ctx context.Context, start, end time.Time, matchers []*labels.Matcher) (model.Value, v1.Warnings, error) {
filteredMatchers, ok := FilterMatchers(c.Labels, matchers)
func (c *addLabelClient) GetValue(ctx context.Context, start, end time.Time, matchers []*labels.Matcher) (model.Value, v1.Warnings, error) {
filteredMatchers, ok := FilterMatchers(c.Labels, c.ExternalLabels, matchers)
if !ok {
return nil, nil, nil
}
Expand All @@ -254,7 +273,7 @@ func (c *AddLabelClient) GetValue(ctx context.Context, start, end time.Time, mat
if err != nil {
return nil, w, err
}
if err := promhttputil.ValueAddLabelSet(val, c.Labels); err != nil {
if err := promhttputil.ValueAddLabelSet(val, c.Labels, c.ExternalLabels); err != nil {
return nil, w, err
}

Expand Down
13 changes: 7 additions & 6 deletions pkg/promclient/label_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,12 @@ func TestAddLabelClient(t *testing.T) {
}

tests := []struct {
labelSet model.LabelSet
err bool
matchers []string
labelValues []string
labelNames []string
labelSet model.LabelSet
externalLabelSet model.LabelSet
err bool
matchers []string
labelValues []string
labelNames []string
}{
{
labelSet: model.LabelSet{"b": "1"},
Expand Down Expand Up @@ -235,7 +236,7 @@ func TestAddLabelClient(t *testing.T) {
}

for i, test := range tests {
a := &AddLabelClient{stub, test.labelSet}
a := NewAddLabelClient(stub, test.labelSet, test.externalLabelSet)
t.Run(strconv.Itoa(i), func(t *testing.T) {
t.Run("LabelNames", func(t *testing.T) {
v, _, err := a.LabelValues(context.TODO(), "a", test.matchers, time.Time{}, time.Time{})
Expand Down
Loading