github.com/grafana/pyroscope@v1.18.0/pkg/frontend/readpath/queryfrontend/query_select_merge_span_profile.go (about) 1 package queryfrontend 2 3 import ( 4 "context" 5 6 "connectrpc.com/connect" 7 "github.com/grafana/dskit/tenant" 8 9 querierv1 "github.com/grafana/pyroscope/api/gen/proto/go/querier/v1" 10 queryv1 "github.com/grafana/pyroscope/api/gen/proto/go/query/v1" 11 phlaremodel "github.com/grafana/pyroscope/pkg/model" 12 "github.com/grafana/pyroscope/pkg/validation" 13 ) 14 15 // TODO(kolesnikovae): Implement span selector. 16 17 func (q *QueryFrontend) SelectMergeSpanProfile( 18 ctx context.Context, 19 c *connect.Request[querierv1.SelectMergeSpanProfileRequest], 20 ) (*connect.Response[querierv1.SelectMergeSpanProfileResponse], 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.SelectMergeSpanProfileResponse{}), 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 maxNodes, err := validation.ValidateMaxNodes(q.limits, tenantIDs, c.Msg.GetMaxNodes()) 39 if err != nil { 40 return nil, connect.NewError(connect.CodeInvalidArgument, err) 41 } 42 labelSelector, err := buildLabelSelectorWithProfileType(c.Msg.LabelSelector, c.Msg.ProfileTypeID) 43 if err != nil { 44 return nil, connect.NewError(connect.CodeInvalidArgument, err) 45 } 46 report, err := q.querySingle(ctx, &queryv1.QueryRequest{ 47 StartTime: c.Msg.Start, 48 EndTime: c.Msg.End, 49 LabelSelector: labelSelector, 50 Query: []*queryv1.Query{{ 51 QueryType: queryv1.QueryType_QUERY_TREE, 52 Tree: &queryv1.TreeQuery{ 53 MaxNodes: maxNodes, 54 SpanSelector: c.Msg.SpanSelector, 55 }, 56 }}, 57 }) 58 if err != nil { 59 return nil, err 60 } 61 if report == nil { 62 return connect.NewResponse(&querierv1.SelectMergeSpanProfileResponse{}), nil 63 } 64 65 var resp querierv1.SelectMergeSpanProfileResponse 66 switch c.Msg.Format { 67 case querierv1.ProfileFormat_PROFILE_FORMAT_TREE: 68 resp.Tree = report.Tree.Tree 69 default: 70 t, err := phlaremodel.UnmarshalTree(report.Tree.Tree) 71 if err != nil { 72 return nil, err 73 } 74 resp.Flamegraph = phlaremodel.NewFlameGraph(t, c.Msg.GetMaxNodes()) 75 } 76 return connect.NewResponse(&resp), nil 77 }