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  }