github.com/grafana/pyroscope@v1.18.0/pkg/frontend/readpath/queryfrontend/query_series_labels_compat.go (about)

     1  package queryfrontend
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"slices"
     7  	"sort"
     8  
     9  	"connectrpc.com/connect"
    10  	"github.com/go-kit/log/level"
    11  	"github.com/pkg/errors"
    12  
    13  	metastorev1 "github.com/grafana/pyroscope/api/gen/proto/go/metastore/v1"
    14  	querierv1 "github.com/grafana/pyroscope/api/gen/proto/go/querier/v1"
    15  	typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1"
    16  	phlaremodel "github.com/grafana/pyroscope/pkg/model"
    17  )
    18  
    19  var (
    20  	errMissingServiceName = errors.New("service name is missing")
    21  	errMissingProfileType = errors.New("profile type is missing")
    22  	errInvalidProfileType = errors.New("invalid profile type")
    23  )
    24  
    25  var profileTypeLabels2 = []string{
    26  	phlaremodel.LabelNameProfileType,
    27  	phlaremodel.LabelNameServiceName,
    28  }
    29  
    30  var profileTypeLabels5 = []string{
    31  	phlaremodel.LabelNameProfileName,
    32  	phlaremodel.LabelNameProfileType,
    33  	phlaremodel.LabelNameType,
    34  	"pyroscope_app",
    35  	phlaremodel.LabelNameServiceName,
    36  }
    37  
    38  func (q *QueryFrontend) isProfileTypeQuery(labels, matchers []string) bool {
    39  	if len(matchers) > 0 {
    40  		return false
    41  	}
    42  	var s []string
    43  	switch len(labels) {
    44  	case 2:
    45  		s = profileTypeLabels2
    46  	case 5:
    47  		s = profileTypeLabels5
    48  	default:
    49  		return false
    50  	}
    51  	sort.Strings(labels)
    52  	return slices.Compare(s, labels) == 0
    53  }
    54  
    55  func (q *QueryFrontend) queryProfileTypeMetadataLabels(
    56  	ctx context.Context,
    57  	tenants []string,
    58  	startTime int64,
    59  	endTime int64,
    60  	labels []string,
    61  ) (*connect.Response[querierv1.SeriesResponse], error) {
    62  	meta, err := q.metadataQueryClient.QueryMetadataLabels(ctx, &metastorev1.QueryMetadataLabelsRequest{
    63  		TenantId:  tenants,
    64  		StartTime: startTime,
    65  		EndTime:   endTime,
    66  		Query:     "{}",
    67  		Labels: []string{
    68  			phlaremodel.LabelNameServiceName,
    69  			phlaremodel.LabelNameProfileType,
    70  		},
    71  	})
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	meta.Labels = q.buildProfileTypeMetadataLabels(meta.Labels, labels)
    76  	return connect.NewResponse(&querierv1.SeriesResponse{LabelsSet: meta.Labels}), nil
    77  }
    78  
    79  func (q *QueryFrontend) buildProfileTypeMetadataLabels(labels []*typesv1.Labels, names []string) []*typesv1.Labels {
    80  	for _, ls := range labels {
    81  		if err := sanitizeProfileTypeMetadataLabels(ls, names); err != nil {
    82  			level.Warn(q.logger).Log("msg", "malformed label set", "labels", phlaremodel.LabelPairsString(ls.Labels), "err", err)
    83  			ls.Labels = nil
    84  		}
    85  	}
    86  	labels = slices.DeleteFunc(labels, func(ls *typesv1.Labels) bool {
    87  		return len(ls.Labels) == 0
    88  	})
    89  	slices.SortFunc(labels, func(a, b *typesv1.Labels) int {
    90  		return phlaremodel.CompareLabelPairs(a.Labels, b.Labels)
    91  	})
    92  	return labels
    93  }
    94  
    95  func sanitizeProfileTypeMetadataLabels(ls *typesv1.Labels, names []string) error {
    96  	var serviceName, profileType string
    97  	for _, l := range ls.Labels {
    98  		switch l.Name {
    99  		case phlaremodel.LabelNameServiceName:
   100  			serviceName = l.Value
   101  		case phlaremodel.LabelNameProfileType:
   102  			profileType = l.Value
   103  		}
   104  	}
   105  	if serviceName == "" {
   106  		return errMissingServiceName
   107  	}
   108  	if profileType == "" {
   109  		return errMissingProfileType
   110  	}
   111  	pt, err := phlaremodel.ParseProfileTypeSelector(profileType)
   112  	if err != nil {
   113  		return fmt.Errorf("%w: %w", errInvalidProfileType, err)
   114  	}
   115  	if len(names) == 5 {
   116  		// Replace the labels with the expected ones.
   117  		ls.Labels = append(ls.Labels[:0], []*typesv1.LabelPair{
   118  			{Name: phlaremodel.LabelNameProfileType, Value: profileType},
   119  			{Name: phlaremodel.LabelNameServiceName, Value: serviceName},
   120  			{Name: phlaremodel.LabelNameProfileName, Value: pt.Name},
   121  			{Name: phlaremodel.LabelNameType, Value: pt.SampleType},
   122  		}...)
   123  	}
   124  	sort.Sort(phlaremodel.Labels(ls.Labels))
   125  	return nil
   126  }