From 703b260903ba2cb23fb01c721a173027fc1e3c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Fri, 22 Jun 2018 11:53:10 +0200 Subject: [PATCH] Implement missing bits in result listing --- internal/cli/list/list.go | 47 +++++++++++++++--------- internal/log/handlers/cli/cli.go | 15 ++++++++ internal/log/handlers/cli/result_item.go | 21 +++++++++-- internal/log/handlers/cli/util.go | 10 +++++ internal/output/output.go | 25 +++++++++++++ 5 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 internal/log/handlers/cli/util.go diff --git a/internal/cli/list/list.go b/internal/cli/list/list.go index 80e1395..d62d293 100644 --- a/internal/cli/list/list.go +++ b/internal/cli/list/list.go @@ -23,24 +23,9 @@ func init() { return err } - log.Info("Results") - for idx, result := range doneResults { - output.ResultItem(output.ResultItemData{ - ID: result.ID, - Index: idx, - TotalCount: len(doneResults), - Name: result.Name, - StartTime: result.StartTime, - NetworkName: result.NetworkName, - Country: result.Country, - ASN: result.ASN, - Summary: result.Summary, - Done: result.Done, - DataUsageUp: result.DataUsageUp, - DataUsageDown: result.DataUsageDown, - }) + if len(incompleteResults) > 0 { + output.SectionTitle("Incomplete results") } - log.Info("Incomplete results") for idx, result := range incompleteResults { output.ResultItem(output.ResultItemData{ ID: result.ID, @@ -57,6 +42,34 @@ func init() { DataUsageDown: result.DataUsageDown, }) } + + resultSummary := output.ResultSummaryData{} + netCount := make(map[string]int) + output.SectionTitle("Results") + for idx, result := range doneResults { + output.ResultItem(output.ResultItemData{ + ID: result.ID, + Index: idx, + TotalCount: len(doneResults), + Name: result.Name, + StartTime: result.StartTime, + NetworkName: result.NetworkName, + Country: result.Country, + ASN: result.ASN, + Summary: result.Summary, + Done: result.Done, + DataUsageUp: result.DataUsageUp, + DataUsageDown: result.DataUsageDown, + }) + resultSummary.TotalTests++ + netCount[result.ASN]++ + resultSummary.TotalDataUsageUp += result.DataUsageUp + resultSummary.TotalDataUsageDown += result.DataUsageDown + } + resultSummary.TotalNetworks = int64(len(netCount)) + + output.ResultSummary(resultSummary) + return nil }) } diff --git a/internal/log/handlers/cli/cli.go b/internal/log/handlers/cli/cli.go index fbb04cd..1b87655 100644 --- a/internal/log/handlers/cli/cli.go +++ b/internal/log/handlers/cli/cli.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "os" + "strings" "sync" "time" @@ -60,6 +61,16 @@ func New(w io.Writer) *Handler { } } +func logSectionTitle(w io.Writer, f log.Fields) error { + colWidth := 24 + + title := f.Get("title").(string) + fmt.Fprintf(w, "┏"+strings.Repeat("━", colWidth+2)+"┓\n") + fmt.Fprintf(w, "┃ %s ┃\n", RightPad(title, colWidth)) + fmt.Fprintf(w, "┗"+strings.Repeat("━", colWidth+2)+"┛\n") + return nil +} + // TypedLog is used for handling special "typed" logs to the CLI func (h *Handler) TypedLog(t string, e *log.Entry) error { switch t { @@ -70,6 +81,10 @@ func (h *Handler) TypedLog(t string, e *log.Entry) error { return nil case "result_item": return logResultItem(h.Writer, e.Fields) + case "result_summary": + return logResultSummary(h.Writer, e.Fields) + case "section_title": + return logSectionTitle(h.Writer, e.Fields) default: return h.DefaultLog(e) } diff --git a/internal/log/handlers/cli/result_item.go b/internal/log/handlers/cli/result_item.go index 1f3ec8e..391fa46 100644 --- a/internal/log/handlers/cli/result_item.go +++ b/internal/log/handlers/cli/result_item.go @@ -10,10 +10,6 @@ import ( "github.com/apex/log" ) -func RightPad(str string, length int) string { - return str + strings.Repeat(" ", length-len(str)) -} - // XXX Copy-pasta from nettest/groups // PerformanceSummary is the result summary for a performance test type PerformanceSummary struct { @@ -145,3 +141,20 @@ func logResultItem(w io.Writer, f log.Fields) error { } return nil } + +func logResultSummary(w io.Writer, f log.Fields) error { + + networks := f.Get("total_networks").(int64) + tests := f.Get("total_tests").(int64) + dataUp := f.Get("total_data_usage_up").(int64) + dataDown := f.Get("total_data_usage_down").(int64) + + // └┬──────────────┬──────────────┬──────────────┬ + fmt.Fprintf(w, " │ %s │ %s │ %s │\n", + RightPad(fmt.Sprintf("%d tests", tests), 12), + RightPad(fmt.Sprintf("%d nets", networks), 12), + RightPad(fmt.Sprintf("%d ⬆ %d ⬇", dataUp, dataDown), 12)) + fmt.Fprintf(w, " └──────────────┴──────────────┴──────────────┘\n") + + return nil +} diff --git a/internal/log/handlers/cli/util.go b/internal/log/handlers/cli/util.go new file mode 100644 index 0000000..41a42e2 --- /dev/null +++ b/internal/log/handlers/cli/util.go @@ -0,0 +1,10 @@ +package cli + +import ( + "strings" + "unicode/utf8" +) + +func RightPad(str string, length int) string { + return str + strings.Repeat(" ", length-utf8.RuneCountInString(str)) +} diff --git a/internal/output/output.go b/internal/output/output.go index f658765..8bb1cd2 100644 --- a/internal/output/output.go +++ b/internal/output/output.go @@ -51,3 +51,28 @@ func ResultItem(result ResultItemData) { "total_count": result.TotalCount, }).Info("result item") } + +type ResultSummaryData struct { + TotalTests int64 + TotalDataUsageUp int64 + TotalDataUsageDown int64 + TotalNetworks int64 +} + +func ResultSummary(result ResultSummaryData) { + log.WithFields(log.Fields{ + "type": "result_summary", + "total_tests": result.TotalTests, + "total_data_usage_up": result.TotalDataUsageUp, + "total_data_usage_down": result.TotalDataUsageDown, + "total_networks": result.TotalNetworks, + }).Info("result summary") +} + +// SectionTitle is the title of a section +func SectionTitle(text string) { + log.WithFields(log.Fields{ + "type": "section_title", + "title": text, + }).Info(text) +}