diff options
Diffstat (limited to 'tools/parsers/parser_main.go')
-rw-r--r-- | tools/parsers/parser_main.go | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/tools/parsers/parser_main.go b/tools/parsers/parser_main.go new file mode 100644 index 000000000..01396494a --- /dev/null +++ b/tools/parsers/parser_main.go @@ -0,0 +1,147 @@ +// Copyright 2020 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Binary parser parses Benchmark data from golang benchmarks, +// puts it into a Schema for BigQuery, and sends it to BigQuery. +// parser will also initialize a table with the Benchmarks BigQuery schema. +package main + +import ( + "context" + "fmt" + "io/ioutil" + "log" + "os" + + "gvisor.dev/gvisor/runsc/flag" + bq "gvisor.dev/gvisor/tools/bigquery" + "gvisor.dev/gvisor/tools/parsers" +) + +const ( + initString = "init" + initDescription = "initializes a new table with benchmarks schema" + parseString = "parse" + parseDescription = "parses given benchmarks file and sends it to BigQuery table." +) + +var ( + // The init command will create a new dataset/table in the given project and initialize + // the table with the schema in //tools/bigquery/bigquery.go. If the table/dataset exists + // or has been initialized, init has no effect and successfully returns. + initCmd = flag.NewFlagSet(initString, flag.ContinueOnError) + initProject = initCmd.String("project", "", "GCP project to send benchmarks.") + initDataset = initCmd.String("dataset", "", "dataset to send benchmarks data.") + initTable = initCmd.String("table", "", "table to send benchmarks data.") + + // The parse command parses benchmark data in `file` and sends it to the + // requested table. + parseCmd = flag.NewFlagSet(parseString, flag.ContinueOnError) + file = parseCmd.String("file", "", "file to parse for benchmarks") + name = parseCmd.String("suite_name", "", "name of the benchmark suite") + parseProject = parseCmd.String("project", "", "GCP project to send benchmarks.") + parseDataset = parseCmd.String("dataset", "", "dataset to send benchmarks data.") + parseTable = parseCmd.String("table", "", "table to send benchmarks data.") + official = parseCmd.Bool("official", false, "mark input data as official.") + runtime = parseCmd.String("runtime", "", "runtime used to run the benchmark") + debug = parseCmd.Bool("debug", false, "print debug logs") +) + +// initBenchmarks initializes a dataset/table in a BigQuery project. +func initBenchmarks(ctx context.Context) error { + return bq.InitBigQuery(ctx, *initProject, *initDataset, *initTable, nil) +} + +// parseBenchmarks parses the given file into the BigQuery schema, +// adds some custom data for the commit, and sends the data to BigQuery. +func parseBenchmarks(ctx context.Context) error { + debugLog("Reading file: %s", *file) + data, err := ioutil.ReadFile(*file) + if err != nil { + return fmt.Errorf("failed to read file %s: %v", *file, err) + } + debugLog("Parsing output: %s", string(data)) + suite, err := parsers.ParseOutput(string(data), *name, *official) + if err != nil { + return fmt.Errorf("failed parse data: %v", err) + } + debugLog("Parsed benchmarks: %d", len(suite.Benchmarks)) + if len(suite.Benchmarks) < 1 { + fmt.Fprintf(os.Stderr, "Failed to find benchmarks for file: %s", *file) + return nil + } + + extraConditions := []*bq.Condition{ + { + Name: "runtime", + Value: *runtime, + }, + { + Name: "version", + Value: version, + }, + } + + suite.Official = *official + suite.Conditions = append(suite.Conditions, extraConditions...) + debugLog("Sending benchmarks") + return bq.SendBenchmarks(ctx, suite, *parseProject, *parseDataset, *parseTable, nil) +} + +func main() { + ctx := context.Background() + switch { + // the "init" command + case len(os.Args) >= 2 && os.Args[1] == initString: + if err := initCmd.Parse(os.Args[2:]); err != nil { + log.Fatalf("Failed parse flags: %v\n", err) + os.Exit(1) + } + if err := initBenchmarks(ctx); err != nil { + failure := "failed to initialize project: %s dataset: %s table: %s: %v\n" + log.Fatalf(failure, *parseProject, *parseDataset, *parseTable, err) + os.Exit(1) + } + // the "parse" command. + case len(os.Args) >= 2 && os.Args[1] == parseString: + if err := parseCmd.Parse(os.Args[2:]); err != nil { + log.Fatalf("Failed parse flags: %v\n", err) + os.Exit(1) + } + if err := parseBenchmarks(ctx); err != nil { + log.Fatalf("Failed parse benchmarks: %v\n", err) + os.Exit(1) + } + default: + printUsage() + os.Exit(1) + } +} + +// printUsage prints the top level usage string. +func printUsage() { + usage := `Usage: parser <command> <flags> ... + +Available commands: + %s %s + %s %s +` + log.Printf(usage, initCmd.Name(), initDescription, parseCmd.Name(), parseDescription) +} + +func debugLog(msg string, args ...interface{}) { + if *debug { + log.Printf(msg, args...) + } +} |