cmd/ejobs: truncate -stream output to only display Diagnostics

- By default, -stream will display Diagnostics with file and line
  information.
- If -verbose is specified, then the entire JSON payload will be dumped.

Change-Id: I798bbba821fecb0ba7ffe15b4e74048bbba6eb5b
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/716880
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Markus Kusano <kusano@google.com>
Auto-Submit: Ethan Lee <ethanalee@google.com>
diff --git a/cmd/ejobs/main.go b/cmd/ejobs/main.go
index f151cb3..f865fdc 100644
--- a/cmd/ejobs/main.go
+++ b/cmd/ejobs/main.go
@@ -57,6 +57,7 @@
 	waitInterval time.Duration // for wait
 	outfile      string        // for results
 	stream       bool          // for results
+	verbose      bool          // for results
 	userFilter   string        // for list
 )
 
@@ -94,12 +95,13 @@
 			fs.DurationVar(&waitInterval, "i", 0, "display updates at this interval")
 		},
 	},
-	{"results", "[-f] [-e] [-o FILE.json] JOBID",
+	{"results", "[-f] [-e] [-o FILE.json] [-stream] [-verbose] JOBID",
 		"download results as JSON",
 		doResults,
 		func(fs *flag.FlagSet) {
 			fs.StringVar(&outfile, "o", "", "output filename")
 			fs.BoolVar(&stream, "stream", false, "stream output")
+			fs.BoolVar(&verbose, "verbose", false, "when streaming, dump the full result, not just diagnostics")
 		},
 	},
 }
@@ -554,6 +556,9 @@
 }
 
 func doResults(ctx context.Context, args []string) (err error) {
+	if verbose && !stream {
+		return errors.New("-verbose flag can only be used with -stream")
+	}
 	if len(args) == 0 {
 		return errors.New("wrong number of args: want [-f] [-o FILE.json] JOB_ID")
 	}
@@ -648,13 +653,21 @@
 		if err != nil {
 			return 0, fmt.Errorf("iterating BigQuery results failed: %w", err)
 		}
+		if !verbose && r.Diagnostics == nil {
+			continue
+		}
 		resultID := fmt.Sprintf("%s@%s", r.ModulePath, r.Version)
 		if _, ok := processedIDs[resultID]; ok {
 			continue
 		}
 
 		count++
-		b, err := json.MarshalIndent(&r, "", "  ")
+		var b []byte
+		if verbose {
+			b, err = json.MarshalIndent(&r, "", " ")
+		} else {
+			b, err = json.MarshalIndent(r.Diagnostics, "", " ")
+		}
 		if err != nil {
 			return 0, fmt.Errorf("marshalling result: %w", err)
 		}
diff --git a/cmd/ejobs/main_test.go b/cmd/ejobs/main_test.go
index 9f46873..65232a5 100644
--- a/cmd/ejobs/main_test.go
+++ b/cmd/ejobs/main_test.go
@@ -48,8 +48,21 @@
 func TestFetchAndPrintResults(t *testing.T) {
 	mockClient := &mockBQClient{
 		expectedResults: []*analysis.Result{
-			{ModulePath: "example.com/one", Version: "v1.0.0", CreatedAt: time.Now()},
-			{ModulePath: "example.com/two", Version: "v1.2.3", CreatedAt: time.Now().Add(1 * time.Second)},
+			{
+				ModulePath: "example.com/one",
+				Version:    "v1.0.0",
+				CreatedAt:  time.Now(),
+				Diagnostics: []*analysis.Diagnostic{
+					{
+						PackageID:    "example.com/one [example.com/one.test]",
+						AnalyzerName: "fuzzdetect",
+						Category:     "",
+						Position:     "https://go-mod-viewer.appspot.com/example.com@v1.0.0/one/quorum_test.go#L59",
+						Message:      "found the use of fuzzing",
+						Source:       bq.NullString{StringVal: "\nfunc FuzzCalculateQuorum(f *testing.F) {\n\t// Add examples to our fuzz corpus", Valid: true},
+					},
+				},
+			},
 		},
 	}
 	var out bytes.Buffer