github.com/grafana/pyroscope@v1.18.0/pkg/frontend/readpath/queryfrontend/query_diff.go (about) 1 package queryfrontend 2 3 import ( 4 "context" 5 6 "connectrpc.com/connect" 7 "github.com/grafana/dskit/tenant" 8 "golang.org/x/sync/errgroup" 9 10 querierv1 "github.com/grafana/pyroscope/api/gen/proto/go/querier/v1" 11 phlaremodel "github.com/grafana/pyroscope/pkg/model" 12 "github.com/grafana/pyroscope/pkg/validation" 13 ) 14 15 func (q *QueryFrontend) Diff( 16 ctx context.Context, 17 c *connect.Request[querierv1.DiffRequest], 18 ) (*connect.Response[querierv1.DiffResponse], error) { 19 tenantIDs, err := tenant.TenantIDs(ctx) 20 if err != nil { 21 return nil, connect.NewError(connect.CodeInvalidArgument, err) 22 } 23 24 if c.Msg.Left == nil { 25 c.Msg.Left = &querierv1.SelectMergeStacktracesRequest{} 26 } 27 28 if c.Msg.Right == nil { 29 c.Msg.Right = &querierv1.SelectMergeStacktracesRequest{} 30 } 31 32 maxNodes := c.Msg.Left.GetMaxNodes() 33 if n := c.Msg.Right.GetMaxNodes(); n > maxNodes { 34 maxNodes = n 35 } 36 maxNodes, err = validation.ValidateMaxNodes(q.limits, tenantIDs, maxNodes) 37 if err != nil { 38 return nil, connect.NewError(connect.CodeInvalidArgument, err) 39 } 40 c.Msg.Left.MaxNodes = &maxNodes 41 c.Msg.Right.MaxNodes = &maxNodes 42 43 _, err = phlaremodel.ParseProfileTypeSelector(c.Msg.Left.ProfileTypeID) 44 if err != nil { 45 return nil, connect.NewError(connect.CodeInvalidArgument, err) 46 } 47 48 _, err = phlaremodel.ParseProfileTypeSelector(c.Msg.Right.ProfileTypeID) 49 if err != nil { 50 return nil, connect.NewError(connect.CodeInvalidArgument, err) 51 } 52 53 var left, right []byte 54 g, ctx := errgroup.WithContext(ctx) 55 g.Go(func() error { 56 var leftErr error 57 left, leftErr = q.selectMergeStacktracesTree(ctx, connect.NewRequest(c.Msg.Left)) 58 return leftErr 59 }) 60 g.Go(func() error { 61 var rightErr error 62 right, rightErr = q.selectMergeStacktracesTree(ctx, connect.NewRequest(c.Msg.Right)) 63 return rightErr 64 }) 65 if err = g.Wait(); err != nil { 66 return nil, connect.NewError(connect.CodeInvalidArgument, err) 67 } 68 69 diff, err := phlaremodel.NewFlamegraphDiffFromBytes(left, right, maxNodes) 70 if err != nil { 71 return nil, connect.NewError(connect.CodeInvalidArgument, err) 72 } 73 return connect.NewResponse(&querierv1.DiffResponse{Flamegraph: diff}), nil 74 }