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  }