Add required diagnostic CLI options.
Change-Id: Ifeb4bc72802b25441caa3a64a83e6712b5f7869b
diff --git a/catapult/cmd/catapult/make_histogram.go b/catapult/cmd/catapult/make_histogram.go
index cbc677f..f5085d0 100644
--- a/catapult/cmd/catapult/make_histogram.go
+++ b/catapult/cmd/catapult/make_histogram.go
@@ -15,34 +15,92 @@
"fuchsia.googlesource.com/testing/catapult"
schema "fuchsia.googlesource.com/testing/perf/schema/v1"
"github.com/google/subcommands"
+ uuid "github.com/satori/go.uuid"
)
-type MakeHistogramCommand struct{}
+// sharedDiagnostics contains the values to use in the HistogramSet generated
+// by this subcommand.
+//
+// Catapult requires a specific set of shared diagnostics to be present on a
+// HistogramSet before uploading to the dashboard. Those required diagnostics
+// are:
+//
+// * bots - a GenericSet of strings containing bot hostnames
+// * benchmarks - a GenericSet of strings containing Telemetry
+// benchmark names.
+// * chromiumCommitPositions - a GenericSet of numbers containing
+// Chromium commit positions.
+// * masters - a GenericSet of strings containing buildbot master hostnames.
+//
+// There are other, optional diagnostics. Those may be added to this struct as
+// needed.
+//
+// Because the names of some diagnostics are not relevant to users of this tool
+// it is ok for this subcommand and this struct to use different names for any
+// of them so long as the names are mapped back to their counterparts when the
+// HistogramSet is constructed.
+//
+// To learn more about Catapult Diagnostics, see:
+// https://github.com/catapult-project/catapult/blob/master/docs/how-to-write-metrics.md
+type sharedDiagnostics struct {
+ // testSuite specifies the test suite that we are creating a
+ // HistogramSet for. e.g. "zircon" "ledger"
+ //
+ // Corresponds to the diagnostic "benchmarks".
+ testSuite string
+
+ // builder specifies the LUCI builder that ran these tests.
+ //
+ // Corresponds to the diagnostic "bots".
+ builder string
+
+ // bucket specifies the LUCI bucket containing the job that ran
+ // these tests.
+ //
+ // Corresponds to the diagnostic "masters".
+ bucket string
+
+ // TODO(kjharland): Add placeholder for chromiumCommitPositions
+ // once the catapult team confirms what we can use this field
+ // for.
+}
+
+type MakeHistogramCommand struct {
+ sharedDiagnostics sharedDiagnostics
+}
func (*MakeHistogramCommand) Name() string {
return "make_histogram"
}
func (*MakeHistogramCommand) Usage() string {
- return "make_histogram [input_file]"
+ return "make_histogram [options] input_file"
}
func (*MakeHistogramCommand) Synopsis() string {
return "Converts performance test output to a catapult HistogramSet"
}
-func (*MakeHistogramCommand) SetFlags(flags *flag.FlagSet) {}
+func (cmd *MakeHistogramCommand) SetFlags(flags *flag.FlagSet) {
+ flags.StringVar(&cmd.sharedDiagnostics.testSuite, "test-suite", "",
+ "Test suite corresponding to the input file")
+ flags.StringVar(&cmd.sharedDiagnostics.builder, "builder", "",
+ "LUCI builder that generated the test results")
+ flags.StringVar(&cmd.sharedDiagnostics.bucket, "bucket", "",
+ "Buildbucket bucket containing the job that ran the test")
+}
-// Execute Converts performance test output to a catapult HistogramSet
+// Execute converts performance test output to a catapult HistogramSet
// The histogram set created by this command does not contain the necessary
// diagnostics for sending to catapult. To add these diagnostics, use:
//
-// $ catapult add_diagnostics ....
+// $ catapult add_diagnostics ....
//
// See https://github.com/catapult-project/catapult/blob/master/docs/histogram-set-json-format.md
-func (*MakeHistogramCommand) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
- var variants struct {
- Variants []schema.Variant `json:"variants"`
+func (cmd *MakeHistogramCommand) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
+ if f.NArg() != 1 {
+ log.Println("missing input_file")
+ return subcommands.ExitFailure
}
inputFile := f.Arg(0)
@@ -52,13 +110,20 @@
return subcommands.ExitFailure
}
+ histogramSet := new(catapult.HistogramSet)
+
+ var variants struct {
+ Variants []schema.Variant `json:"variants"`
+ }
+
if err := json.Unmarshal(blob, &variants); err != nil {
log.Println(err)
return subcommands.ExitFailure
}
- histogramSet := catapult.HistogramSet{}
+ // Generate Histograms from test results.
histograms := catapult.ConvertVariantsToHistograms(variants.Variants)
+
// Track whether any single Histogram addition failed. We do this instead of
// exiting after a single error to expose as many errors as possible.
anyAddFailed := false
@@ -66,19 +131,41 @@
if err := histogramSet.AddHistogram(histogram); err != nil {
log.Println(err)
anyAddFailed = true
-
}
}
if anyAddFailed {
return subcommands.ExitFailure
}
- js, err := json.Marshal(&histogramSet)
+ // Add all shared diagnostics, mapping to the appropriate Catapult
+ // diagnostic names.
+ diagnosticInfoPairs := []struct {
+ Name string
+ Value string
+ }{
+ {"benchmarks", cmd.sharedDiagnostics.testSuite},
+ {"bots", cmd.sharedDiagnostics.builder},
+ {"masters", cmd.sharedDiagnostics.bucket},
+ // Required for uploading, even if value is just empty.
+ {"chromiumCommitPositions", ""},
+ }
+ for _, info := range diagnosticInfoPairs {
+ histogramSet.AddSharedDiagnostic(info.Name, &catapult.GenericSetDiagnostic{
+ Type: catapult.DiagnosticTypeGenericSet,
+ GUID: uuid.NewV4().String(),
+ Values: []string{info.Value},
+ })
+ }
+
+ // Serialize and log the new HistogramSet.
+ js, err := json.Marshal(histogramSet.ToJSON())
if err != nil {
log.Println(err)
return subcommands.ExitFailure
}
+ // TODO(kjharland): Add option to write to a file so this can be used
+ // from a recipe.
fmt.Println(string(js))
return subcommands.ExitSuccess
}
diff --git a/catapult/histogram_set.go b/catapult/histogram_set.go
index 1a6f2c6..2858be8 100644
--- a/catapult/histogram_set.go
+++ b/catapult/histogram_set.go
@@ -44,8 +44,11 @@
guid := diagnostic.GetGUID()
// Reference the diagnostic's GUID in each Histogram in this set.
- for _, histogram := range h.histograms {
- histogram.AddDiagnostic(name, guid)
+ //
+ // Use the loop index instead of the loop variable since this directly
+ // mutates the histogram.
+ for i := range h.histograms {
+ h.histograms[i].AddDiagnostic(name, guid)
}
}
diff --git a/catapult/histogram_set_test.go b/catapult/histogram_set_test.go
index aa93e5a..e324524 100644
--- a/catapult/histogram_set_test.go
+++ b/catapult/histogram_set_test.go
@@ -106,8 +106,10 @@
Diagnostics: make(map[string]string),
})
histogramSet.AddHistogram(catapult.Histogram{
- Name: "test_histogram_2",
- Diagnostics: make(map[string]string),
+ Name: "test_histogram_2",
+ // Intentionally leaving this Diagnostics map as nil to
+ // make sure the map still recieves a reference to the
+ // new Diagnostic.
})
histogramSet.AddSharedDiagnostic("test_diagnostic", diagnostic)