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

     1  package queryfrontend
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"connectrpc.com/connect"
     8  	"github.com/grafana/dskit/tenant"
     9  	"github.com/pkg/errors"
    10  
    11  	querierv1 "github.com/grafana/pyroscope/api/gen/proto/go/querier/v1"
    12  	queryv1 "github.com/grafana/pyroscope/api/gen/proto/go/query/v1"
    13  	phlaremodel "github.com/grafana/pyroscope/pkg/model"
    14  	"github.com/grafana/pyroscope/pkg/validation"
    15  )
    16  
    17  func (q *QueryFrontend) SelectSeries(
    18  	ctx context.Context,
    19  	c *connect.Request[querierv1.SelectSeriesRequest],
    20  ) (*connect.Response[querierv1.SelectSeriesResponse], error) {
    21  	tenantIDs, err := tenant.TenantIDs(ctx)
    22  	if err != nil {
    23  		return nil, connect.NewError(connect.CodeInvalidArgument, err)
    24  	}
    25  	empty, err := validation.SanitizeTimeRange(q.limits, tenantIDs, &c.Msg.Start, &c.Msg.End)
    26  	if err != nil {
    27  		return nil, connect.NewError(connect.CodeInvalidArgument, err)
    28  	}
    29  	if empty {
    30  		return connect.NewResponse(&querierv1.SelectSeriesResponse{}), nil
    31  	}
    32  
    33  	_, err = phlaremodel.ParseProfileTypeSelector(c.Msg.ProfileTypeID)
    34  	if err != nil {
    35  		return nil, connect.NewError(connect.CodeInvalidArgument, err)
    36  	}
    37  
    38  	if c.Msg.Step == 0 {
    39  		return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("step must be non-zero"))
    40  	}
    41  
    42  	stepMs := time.Duration(c.Msg.Step * float64(time.Second)).Milliseconds()
    43  	start := c.Msg.Start - stepMs
    44  
    45  	labelSelector, err := buildLabelSelectorWithProfileType(c.Msg.LabelSelector, c.Msg.ProfileTypeID)
    46  	if err != nil {
    47  		return nil, connect.NewError(connect.CodeInvalidArgument, err)
    48  	}
    49  	report, err := q.querySingle(ctx, &queryv1.QueryRequest{
    50  		StartTime:     start,
    51  		EndTime:       c.Msg.End,
    52  		LabelSelector: labelSelector,
    53  		Query: []*queryv1.Query{{
    54  			QueryType: queryv1.QueryType_QUERY_TIME_SERIES,
    55  			TimeSeries: &queryv1.TimeSeriesQuery{
    56  				Step:         c.Msg.GetStep(),
    57  				GroupBy:      c.Msg.GetGroupBy(),
    58  				Limit:        c.Msg.GetLimit(),
    59  				ExemplarType: c.Msg.GetExemplarType(),
    60  			},
    61  		}},
    62  	})
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	if report == nil {
    67  		return connect.NewResponse(&querierv1.SelectSeriesResponse{}), nil
    68  	}
    69  	series := phlaremodel.TopSeries(report.TimeSeries.TimeSeries, int(c.Msg.GetLimit()))
    70  	return connect.NewResponse(&querierv1.SelectSeriesResponse{Series: series}), nil
    71  }