| // 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) |
| } |
| } |