github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/cli/export.go (about)

     1  package cli
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  
     7  	"github.com/pkg/errors"
     8  )
     9  
    10  var (
    11  	GranularityDays    = "day"
    12  	GranularityMinutes = "minute"
    13  	GranularitySeconds = "second"
    14  	GranularityHours   = "hour"
    15  
    16  	HostUtilizationStat     = "host"
    17  	AverageScheduledToStart = "avg"
    18  	OptimalMakespanStat     = "makespan"
    19  )
    20  
    21  // ExportCommand is used to export statistics
    22  type ExportCommand struct {
    23  	GlobalOpts  *Options `no-flag:"true"`
    24  	JSON        bool     `long:"json" description:"set the format to export to json"`
    25  	Granularity string   `long:"granularity" description:"set the granularity, default hour, options are 'second', 'minute', 'hour'"`
    26  	Days        int      `long:"days" description:"set the number of days, default 1, max of 30 days back"`
    27  	StatsType   string   `long:"stat" description:"include the type of stats - 'host' for host utilization,'avg' for average scheduled to start times, 'makespan' for makespan ratios" required:"true"`
    28  	DistroId    string   `long:"distro" description:"distro id - required for average scheduled to start times"`
    29  	Number      int      `long:"number" description:"set the number of revisions (for getting build makespan), default 100"`
    30  	Filepath    string   `long:"filepath" description:"path to directory where csv file is to be saved"`
    31  }
    32  
    33  func (ec *ExportCommand) Execute(_ []string) error {
    34  	_, rc, _, err := getAPIClients(ec.GlobalOpts)
    35  	if err != nil {
    36  		return err
    37  	}
    38  
    39  	if ec.StatsType == "" {
    40  		return errors.New("Must specify a stats type, host")
    41  	}
    42  
    43  	// default granularity to an hour
    44  	if ec.Granularity == "" {
    45  		ec.Granularity = GranularityHours
    46  	}
    47  
    48  	// default days to 1
    49  	if ec.Days == 0 {
    50  		ec.Days = 1
    51  	}
    52  
    53  	if ec.Number == 0 {
    54  		ec.Number = 100
    55  	}
    56  
    57  	isCSV := !ec.JSON
    58  
    59  	var body io.ReadCloser
    60  	var granSeconds int
    61  
    62  	switch ec.StatsType {
    63  	case HostUtilizationStat:
    64  		granSeconds, err = convertGranularityToSeconds(ec.Granularity)
    65  		if err != nil {
    66  			return err
    67  		}
    68  		body, err = rc.GetHostUtilizationStats(granSeconds, ec.Days, isCSV)
    69  		if err != nil {
    70  			return err
    71  		}
    72  	case AverageScheduledToStart:
    73  		if ec.DistroId == "" {
    74  			return errors.New("cannot have empty distro id")
    75  		}
    76  		granSeconds, err = convertGranularityToSeconds(ec.Granularity)
    77  		if err != nil {
    78  			return err
    79  		}
    80  		body, err = rc.GetAverageSchedulerStats(granSeconds, ec.Days, ec.DistroId, isCSV)
    81  		if err != nil {
    82  			return err
    83  		}
    84  	case OptimalMakespanStat:
    85  		body, err = rc.GetOptimalMakespans(ec.Number, isCSV)
    86  		if err != nil {
    87  			return err
    88  		}
    89  
    90  	default:
    91  		return errors.Errorf("%v is not a valid stats type. The current valid types include, host, avg, and makespan", ec.StatsType)
    92  
    93  	}
    94  
    95  	return WriteToFile(body, ec.Filepath)
    96  }
    97  
    98  // convertGranularityToSeconds takes in a string granularity and returns its
    99  func convertGranularityToSeconds(granString string) (int, error) {
   100  	switch granString {
   101  	case GranularityDays:
   102  		return 24 * 60 * 60, nil
   103  	case GranularityHours:
   104  		return 60 * 60, nil
   105  	case GranularityMinutes:
   106  		return 60, nil
   107  	case GranularitySeconds:
   108  		return 1, nil
   109  	default:
   110  		return 0, errors.Errorf("not a valid granularity, %v", granString)
   111  	}
   112  }
   113  
   114  // WriteToFile takes in a body and filepath and writes out the data in the body
   115  func WriteToFile(body io.ReadCloser, filepath string) error {
   116  	defer body.Close()
   117  	file := os.Stdout
   118  	var err error
   119  	if filepath != "" {
   120  		file, err = os.Create(filepath)
   121  		if err != nil {
   122  			return err
   123  		}
   124  		defer file.Close()
   125  	}
   126  	_, err = io.Copy(file, body)
   127  	return err
   128  
   129  }