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

     1  package queryfrontend
     2  
     3  import (
     4  	"context"
     5  
     6  	"connectrpc.com/connect"
     7  	"github.com/go-kit/log/level"
     8  	"github.com/grafana/dskit/tenant"
     9  
    10  	typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1"
    11  
    12  	querierv1 "github.com/grafana/pyroscope/api/gen/proto/go/querier/v1"
    13  	queryv1 "github.com/grafana/pyroscope/api/gen/proto/go/query/v1"
    14  	"github.com/grafana/pyroscope/pkg/featureflags"
    15  	"github.com/grafana/pyroscope/pkg/validation"
    16  )
    17  
    18  func (q *QueryFrontend) filterLabelNames(
    19  	ctx context.Context,
    20  	c *connect.Request[querierv1.SeriesRequest],
    21  	labelNames []string,
    22  	matchers []string,
    23  ) ([]string, error) {
    24  	if capabilities, ok := featureflags.GetClientCapabilities(ctx); ok && capabilities.AllowUtf8LabelNames {
    25  		return labelNames, nil
    26  	}
    27  
    28  	toFilter := make([]string, len(labelNames))
    29  	copy(toFilter, labelNames)
    30  
    31  	// Filter out label names not passing legacy validation if utf8 label names not enabled
    32  	if len(labelNames) == 0 {
    33  		// Querying for all label names; must retrieve all label names to then filter out
    34  		response, err := q.LabelNames(ctx, connect.NewRequest(&typesv1.LabelNamesRequest{
    35  			Start:    c.Msg.Start,
    36  			End:      c.Msg.End,
    37  			Matchers: matchers,
    38  		}))
    39  
    40  		if err != nil {
    41  			return nil, err
    42  		}
    43  		if response != nil {
    44  			toFilter = response.Msg.Names
    45  		}
    46  	}
    47  
    48  	filtered := make([]string, 0, len(labelNames))
    49  	for _, name := range toFilter {
    50  		if _, _, ok := validation.SanitizeLegacyLabelName(name); !ok {
    51  			level.Debug(q.logger).Log("msg", "filtering out label", "label_name", name)
    52  			continue
    53  		}
    54  		filtered = append(filtered, name)
    55  	}
    56  	return filtered, nil
    57  }
    58  
    59  func (q *QueryFrontend) Series(
    60  	ctx context.Context,
    61  	c *connect.Request[querierv1.SeriesRequest],
    62  ) (*connect.Response[querierv1.SeriesResponse], error) {
    63  	tenantIDs, err := tenant.TenantIDs(ctx)
    64  	if err != nil {
    65  		return nil, connect.NewError(connect.CodeInvalidArgument, err)
    66  	}
    67  	empty, err := validation.SanitizeTimeRange(q.limits, tenantIDs, &c.Msg.Start, &c.Msg.End)
    68  	if err != nil {
    69  		return nil, connect.NewError(connect.CodeInvalidArgument, err)
    70  	}
    71  	if empty {
    72  		return connect.NewResponse(&querierv1.SeriesResponse{}), nil
    73  	}
    74  
    75  	if q.isProfileTypeQuery(c.Msg.LabelNames, c.Msg.Matchers) {
    76  		level.Debug(q.logger).Log("msg", "listing profile types from metadata as series labels")
    77  		return q.queryProfileTypeMetadataLabels(ctx, tenantIDs, c.Msg.Start, c.Msg.End, c.Msg.LabelNames)
    78  	}
    79  
    80  	labelSelector, err := buildLabelSelectorFromMatchers(c.Msg.Matchers)
    81  	if err != nil {
    82  		return nil, connect.NewError(connect.CodeInvalidArgument, err)
    83  	}
    84  
    85  	labelNames, err := q.filterLabelNames(ctx, c, c.Msg.LabelNames, c.Msg.Matchers)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	report, err := q.querySingle(ctx, &queryv1.QueryRequest{
    91  		StartTime:     c.Msg.Start,
    92  		EndTime:       c.Msg.End,
    93  		LabelSelector: labelSelector,
    94  		Query: []*queryv1.Query{{
    95  			QueryType: queryv1.QueryType_QUERY_SERIES_LABELS,
    96  			SeriesLabels: &queryv1.SeriesLabelsQuery{
    97  				LabelNames: labelNames,
    98  			},
    99  		}},
   100  	})
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	if report == nil {
   105  		return connect.NewResponse(&querierv1.SeriesResponse{}), nil
   106  	}
   107  
   108  	return connect.NewResponse(&querierv1.SeriesResponse{LabelsSet: report.SeriesLabels.SeriesLabels}), nil
   109  }