github.com/docker/compose-on-kubernetes@v0.5.0/cmd/e2e_benchmark/reporting.go (about) 1 package main 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io" 8 "time" 9 10 "github.com/pkg/errors" 11 ) 12 13 type reporter interface { 14 onTick(start time.Time, states []*workerState) 15 onFinish(start time.Time, states []*workerState, err error) error 16 } 17 18 type jsonReporter struct { 19 w io.Writer 20 } 21 22 func (r jsonReporter) onTick(start time.Time, states []*workerState) { 23 } 24 25 func (r jsonReporter) onFinish(start time.Time, states []*workerState, err error) error { 26 errText := "" 27 if err != nil { 28 errText = err.Error() 29 } 30 bytes, err := json.Marshal(&benchmarkReport{ 31 Start: start, 32 Error: errText, 33 Succeeded: err == nil, 34 WorkerStates: states, 35 }) 36 if err != nil { 37 return err 38 } 39 _, err = r.w.Write(bytes) 40 return err 41 } 42 43 type textReporter struct { 44 printer *statusPrinter 45 interactive bool 46 } 47 48 func (r textReporter) onTick(start time.Time, states []*workerState) { 49 if r.interactive { 50 r.printer.print(states, start, true) 51 } 52 } 53 54 func (r textReporter) onFinish(start time.Time, states []*workerState, err error) error { 55 fmt.Fprintf(r.printer.out, "---\nexecution total time: %v\n", time.Since(start)) 56 if err != nil { 57 fmt.Fprintf(r.printer.out, "benchmark failed: %s\n", err) 58 return nil 59 } 60 fmt.Fprintln(r.printer.out, "workers state:") 61 r.printer.print(states, start, false) 62 fmt.Fprintln(r.printer.out) 63 fmt.Fprintln(r.printer.out, "average timings:") 64 timings := computePhaseTimingAverages(start, states) 65 for _, t := range timings { 66 fmt.Fprintf(r.printer.out, "%s: %v\n", t.name, t.duration) 67 } 68 fmt.Fprintln(r.printer.out, "benchmark succeeded") 69 return nil 70 } 71 72 func buildReporter(out io.Writer, format string) (reporter, error) { 73 switch format { 74 case "json": 75 return jsonReporter{w: out}, nil 76 case "report": 77 return textReporter{interactive: false, printer: &statusPrinter{out: out}}, nil 78 case "interactive": 79 return textReporter{interactive: true, printer: &statusPrinter{out: out}}, nil 80 } 81 return nil, errors.Errorf("unsupported format %s", format) 82 } 83 84 func reportBenchStatus(ctx context.Context, out io.Writer, finishedC chan error, start time.Time, format string, states []*workerState) error { 85 ticker := time.NewTicker(time.Second * 1) 86 reporter, err := buildReporter(out, format) 87 if err != nil { 88 return err 89 } 90 for { 91 select { 92 case err := <-finishedC: 93 if e := reporter.onFinish(start, states, err); e != nil { 94 panic(errors.Wrap(e, "failed to print report")) 95 } 96 return err 97 case <-ticker.C: 98 reporter.onTick(start, states) 99 case <-ctx.Done(): 100 return errors.New("benchmark timeout") 101 } 102 } 103 }