blob: ecdc440722f28799aed5eb7d61c34775363c4b3e [file] [log] [blame]
// Command-line application for interacting with BigTable backed Perf storage.
package main
import (
"context"
"fmt"
"net/url"
"os"
"cloud.google.com/go/bigtable"
"github.com/spf13/cobra"
"go.skia.org/infra/go/auth"
"go.skia.org/infra/go/query"
"go.skia.org/infra/go/sklog"
"go.skia.org/infra/perf/go/btts"
"go.skia.org/infra/perf/go/config"
)
var (
store *btts.BigTableTraceStore
)
// flags
var (
logToStdErr bool
bigTableConfig string
tile int32
queryFlag string
)
func main() {
ctx := context.Background()
cmd := cobra.Command{
Use: "perf-tool [sub]",
PersistentPreRunE: func(c *cobra.Command, args []string) error {
logMode := sklog.SLogNone
if logToStdErr {
logMode = sklog.SLogStderr
}
sklog.SetLogger(sklog.NewStdErrCloudLogger(logMode))
ts, err := auth.NewDefaultTokenSource(true, bigtable.Scope)
if err != nil {
return fmt.Errorf("Failed to auth: %s", err)
}
// Create the store client.
cfg := config.PERF_BIGTABLE_CONFIGS[bigTableConfig]
store, err = btts.NewBigTableTraceStoreFromConfig(ctx, cfg, ts, false)
if err != nil {
return fmt.Errorf("Failed to create client: %s", err)
}
return nil
},
}
cmd.PersistentFlags().StringVar(&bigTableConfig, "big_table_config", "nano", "The name of the config to use when using a BigTable trace store.")
cmd.PersistentFlags().BoolVar(&logToStdErr, "logtostderr", false, "Otherwise logs are not produced.")
configCmd := &cobra.Command{
Use: "config [sub]",
}
configListCmd := &cobra.Command{
Use: "list",
Short: "List all the available configs.",
Run: configListAction,
}
configCmd.AddCommand(configListCmd)
indicesCmd := &cobra.Command{
Use: "indices [sub]",
}
indicesCmd.PersistentFlags().Int32Var(&tile, "tile", -1, "The tile to query")
indicesCountCmd := &cobra.Command{
Use: "count",
Short: "Counts the number of index rows.",
Long: "Counts the index rows for the last (most recent) tile, or the tile specified by --tile.",
RunE: indicesCountAction,
}
indicesWriteCmd := &cobra.Command{
Use: "write",
Short: "Write indices",
Long: "Rewrites the indices for the last (most recent) tile, or the tile specified by --tile.",
RunE: indicesWriteAction,
}
indicesWriteAllCmd := &cobra.Command{
Use: "write-all",
Short: "Write indices for all tiles.",
Long: "Rewrites the indices for all tiles, --tiles is ignored. Starts with latest tile and keeps moving to previous tiles until it finds a tile with no traces.",
RunE: indicesWriteAllAction,
}
indicesWriteCmd.Flags().Int32Var(&tile, "tile", -1, "The tile to query")
indicesCmd.AddCommand(
indicesCountCmd,
indicesWriteCmd,
indicesWriteAllCmd,
)
tilesCmd := &cobra.Command{
Use: "tiles [sub]",
}
tilesLast := &cobra.Command{
Use: "last",
Short: "Prints the offset of the last (most recent) tile.",
RunE: tilesLastAction,
}
tilesCmd.AddCommand(
tilesLast,
)
tracesCmd := &cobra.Command{
Use: "traces [sub]",
}
tracesCmd.PersistentFlags().Int32Var(&tile, "tile", -1, "The tile to query")
tracesCmd.PersistentFlags().StringVar(&queryFlag, "query", "", "The query to run. Defaults to the empty query which matches all traces.")
tracesCountCmd := &cobra.Command{
Use: "count",
Short: "Prints the number of traces in the last (most recent) tile, or the tile specified by the --tile flag.",
RunE: tracesCountAction,
}
tracesListCmd := &cobra.Command{
Use: "list",
Long: "Prints the IDs of traces in the last (most recent) tile, or the tile specified by the --tile flag, that match --query.",
RunE: tracesListAction,
}
tracesListByIndexCmd := &cobra.Command{
Use: "list-by-index",
Short: "Prints the IDs of traces in the last (most recent) tile, or the tile specified by the --tile flag, that match --query.",
RunE: tracesListByIndexAction,
}
tracesCmd.AddCommand(
tracesCountCmd,
tracesListCmd,
tracesListByIndexCmd,
)
cmd.AddCommand(
configCmd,
indicesCmd,
tilesCmd,
tracesCmd,
)
if err := cmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func tilesLastAction(c *cobra.Command, args []string) error {
tileKey, err := store.GetLatestTile()
if err != nil {
return err
}
fmt.Println(tileKey.Offset())
return nil
}
func tracesCountAction(c *cobra.Command, args []string) error {
var tileKey btts.TileKey
if tile == -1 {
var err error
tileKey, err = store.GetLatestTile()
if err != nil {
return err
}
} else {
tileKey = btts.TileKeyFromOffset(tile)
}
values, err := url.ParseQuery(queryFlag)
if err != nil {
return err
}
q, err := query.New(values)
if err != nil {
return err
}
count, err := store.QueryCount(context.Background(), tileKey, q)
if err != nil {
return err
}
fmt.Println(count)
return nil
}
func tracesListAction(c *cobra.Command, args []string) error {
var tileKey btts.TileKey
if tile == -1 {
var err error
tileKey, err = store.GetLatestTile()
if err != nil {
return err
}
} else {
tileKey = btts.TileKeyFromOffset(tile)
}
values, err := url.ParseQuery(queryFlag)
if err != nil {
return err
}
q, err := query.New(values)
if err != nil {
return err
}
ts, err := store.QueryTraces(context.Background(), tileKey, q)
if err != nil {
return err
}
for id := range ts {
fmt.Println(id)
}
return nil
}
func tracesListByIndexAction(c *cobra.Command, args []string) error {
var tileKey btts.TileKey
if tile == -1 {
var err error
tileKey, err = store.GetLatestTile()
if err != nil {
return err
}
} else {
tileKey = btts.TileKeyFromOffset(tile)
}
values, err := url.ParseQuery(queryFlag)
if err != nil {
return err
}
q, err := query.New(values)
if err != nil {
return err
}
ts, err := store.QueryTracesByIndex(context.Background(), tileKey, q)
if err != nil {
return err
}
for id := range ts {
fmt.Println(id)
}
return nil
}
func indicesWriteAction(c *cobra.Command, args []string) error {
var tileKey btts.TileKey
if tile == -1 {
var err error
tileKey, err = store.GetLatestTile()
if err != nil {
return fmt.Errorf("Failed to get latest tile: %s", err)
}
} else {
tileKey = btts.TileKeyFromOffset(tile)
}
return store.WriteIndices(context.Background(), tileKey)
}
func indicesWriteAllAction(c *cobra.Command, args []string) error {
tileKey, err := store.GetLatestTile()
if err != nil {
return fmt.Errorf("Failed to get latest tile: %s", err)
}
// Empty query to match all traces.
q, err := query.New(url.Values{})
if err != nil {
return err
}
for {
if err := store.WriteIndices(context.Background(), tileKey); err != nil {
return err
}
tileKey = tileKey.PrevTile()
count, err := store.QueryCount(context.Background(), tileKey, q)
if err != nil {
return err
}
if count == 0 {
break
}
}
return nil
}
func indicesCountAction(c *cobra.Command, args []string) error {
var tileKey btts.TileKey
if tile == -1 {
var err error
tileKey, err = store.GetLatestTile()
if err != nil {
return fmt.Errorf("Failed to get latest tile: %s", err)
}
} else {
tileKey = btts.TileKeyFromOffset(tile)
}
count, err := store.CountIndices(context.Background(), tileKey)
if err == nil {
fmt.Println(count)
}
return err
}
func configListAction(c *cobra.Command, args []string) {
for k := range config.PERF_BIGTABLE_CONFIGS {
fmt.Println(k)
}
}