Skip to content

Commit

Permalink
profilecli: Add a label values cardinality subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
simonswine committed Jun 12, 2024
1 parent 30af212 commit e463d71
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
7 changes: 7 additions & 0 deletions cmd/profilecli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ func main() {
queryMergeParams := addQueryMergeParams(queryMergeCmd)
querySeriesCmd := queryCmd.Command("series", "Request series labels.")
querySeriesParams := addQuerySeriesParams(querySeriesCmd)
queryLabelValuesCardinalityCmd := queryCmd.Command("label-values-cardinality", "Request label values cardinality.")
queryLabelValuesCardinalityParams := addQueryLabelValuesCardinalityParams(queryLabelValuesCardinalityCmd)

queryTracerCmd := app.Command("query-tracer", "Analyze query traces.")
queryTracerParams := addQueryTracerParams(queryTracerCmd)
Expand Down Expand Up @@ -116,6 +118,11 @@ func main() {
os.Exit(checkError(err))
}

case queryLabelValuesCardinalityCmd.FullCommand():
if err := queryLabelValuesCardinality(ctx, queryLabelValuesCardinalityParams); err != nil {
os.Exit(checkError(err))
}

case queryTracerCmd.FullCommand():
if err := queryTracer(ctx, queryTracerParams); err != nil {
os.Exit(checkError(err))
Expand Down
76 changes: 76 additions & 0 deletions cmd/profilecli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"os"
"sort"
"strings"
"time"

Expand All @@ -26,6 +27,7 @@ import (
"github.com/klauspost/compress/gzip"
"github.com/mattn/go-isatty"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
)

const (
Expand Down Expand Up @@ -261,3 +263,77 @@ func querySeries(ctx context.Context, params *querySeriesParams) (err error) {
return nil

}

type queryLabelValuesCardinalityParams struct {
*queryParams
TopN uint64
}

func addQueryLabelValuesCardinalityParams(queryCmd commander) *queryLabelValuesCardinalityParams {
params := new(queryLabelValuesCardinalityParams)
params.queryParams = addQueryParams(queryCmd)
queryCmd.Flag("top-n", "Show the top N high cardinality label values").Default("20").Uint64Var(&params.TopN)
return params
}

func queryLabelValuesCardinality(ctx context.Context, params *queryLabelValuesCardinalityParams) (err error) {
from, to, err := params.parseFromTo()
if err != nil {
return err
}

level.Info(logger).Log("msg", "query label names", "url", params.URL, "from", from, "to", to, "labelNames", fmt.Sprintf("%q"))

Check failure on line 285 in cmd/profilecli/query.go

View workflow job for this annotation

GitHub Actions / lint

fmt.Sprintf format %q reads arg #1, but call has 0 args

Check failure on line 285 in cmd/profilecli/query.go

View workflow job for this annotation

GitHub Actions / test

fmt.Sprintf format %q reads arg #1, but call has 0 args

Check failure on line 285 in cmd/profilecli/query.go

View workflow job for this annotation

GitHub Actions / test

fmt.Sprintf format %q reads arg #1, but call has 0 args

qc := params.phlareClient.queryClient()
resp, err := qc.LabelNames(ctx, connect.NewRequest(&typesv1.LabelNamesRequest{
Start: from.UnixMilli(),
End: to.UnixMilli(),
Matchers: []string{params.Query},
}))
if err != nil {
return errors.Wrap(err, "failed to query")
}

level.Info(logger).Log("msg", fmt.Sprintf("received %d label names", len(resp.Msg.Names)))

g, gctx := errgroup.WithContext(ctx)
g.SetLimit(16)
result := make([]int, len(resp.Msg.Names))

for idx := range resp.Msg.Names {
idx := idx
g.Go(func() error {
name := resp.Msg.Names[idx]
resp, err := qc.LabelValues(gctx, connect.NewRequest(&typesv1.LabelValuesRequest{
Name: name,
Start: from.UnixMilli(),
End: to.UnixMilli(),
Matchers: []string{params.Query},
}))
if err != nil {
return fmt.Errorf("failed to query label values for %s: %w", name, err)
}

result[idx] = len(resp.Msg.Names)

return nil
})
}
if err := g.Wait(); err != nil {
return err
}

// sort the result
sort.Slice(resp.Msg.Names, func(i, j int) bool {
return result[i] > result[j]
})
sort.Slice(result, func(i, j int) bool {
return result[i] > result[j]
})

for idx := range resp.Msg.Names[:params.TopN] {
fmt.Println(resp.Msg.Names[idx], result[idx])
}

return nil
}

0 comments on commit e463d71

Please sign in to comment.