Verify in Prometheus edges query that data for a specific resource type exists (#2826)

Adds a check to Prometheus `edges` queries to verify that data for the requested
resource type exists. Previously, if Prometheus could not find request data for the
requested resource type, it would skip that label and still return data for
other labels in the `by` clause, leading to an incorrect response.
This commit is contained in:
Carol A. Scott 2019-05-15 16:03:48 -07:00 committed by GitHub
parent 512dcd336f
commit bb2921a3d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 2 deletions

View File

@ -65,8 +65,12 @@ func (s *grpcServer) getEdges(ctx context.Context, req *pb.EdgesRequest) ([]*pb.
labelsOutbound := labels.Merge(promDirectionLabels("outbound"))
labelsInbound := labels.Merge(promDirectionLabels("inbound"))
inboundQuery := fmt.Sprintf(inboundIdentityQuery, labelsInbound, resourceType)
outboundQuery := fmt.Sprintf(outboundIdentityQuery, labelsOutbound, resourceType, resourceType)
// checking that data for the specified resource type exists
labelsOutboundStr := generateLabelStringWithExclusion(labelsOutbound, resourceType)
labelsInboundStr := generateLabelStringWithExclusion(labelsInbound, resourceType)
outboundQuery := fmt.Sprintf(outboundIdentityQuery, labelsOutboundStr, resourceType, resourceType)
inboundQuery := fmt.Sprintf(inboundIdentityQuery, labelsInboundStr, resourceType)
inboundResult, err := s.queryProm(ctx, inboundQuery)
if err != nil {

View File

@ -4,6 +4,8 @@ import (
"context"
"fmt"
"math"
"sort"
"strings"
"time"
pb "github.com/linkerd/linkerd2/controller/gen/public"
@ -116,6 +118,20 @@ func promDstQueryLabels(resource *pb.Resource) model.LabelSet {
return set
}
// insert a not-nil check into a LabelSet to verify that data for a specified
// label name exists. due to the `!=` this must be inserted as a string. the
// structure of this code is taken from the Prometheus labelset.go library.
func generateLabelStringWithExclusion(l model.LabelSet, labelName string) string {
lstrs := make([]string, 0, len(l))
for l, v := range l {
lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v))
}
lstrs = append(lstrs, fmt.Sprintf(`%s!=""`, labelName))
sort.Strings(lstrs)
return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
}
// determine if we should add "namespace=<namespace>" to a named query
func shouldAddNamespaceLabel(resource *pb.Resource) bool {
return resource.Type != k8s.Namespace && resource.Namespace != ""