X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/6f27bbc6e8797f5faeeb110fa7702900a09813e9..1915e6b0d2a35af51041726a4398cf91a6095859:/lib/costanalyzer/costanalyzer.go diff --git a/lib/costanalyzer/costanalyzer.go b/lib/costanalyzer/costanalyzer.go index 46ff655dd6..df8fd49605 100644 --- a/lib/costanalyzer/costanalyzer.go +++ b/lib/costanalyzer/costanalyzer.go @@ -35,6 +35,7 @@ type nodeInfo struct { // Modern ProviderType string Price float64 + Preemptible bool } type arrayFlags []string @@ -77,19 +78,19 @@ Usage: container was reused between several container requests, its cost will only be counted once. - To get the node costs, the progam queries the Arvados API for current cost - data for each node type used. This means that the reported cost always - reflects the cost data as currently defined in the Arvados API configuration - file. - Caveats: - - the Arvados API configuration cost data may be out of sync with the cloud - provider. - - when generating reports for older container requests, the cost data in the - Arvados API configuration file may have changed since the container request - was fulfilled. This program uses the cost data stored at the time of the + + - This program uses the cost data from config.yml at the time of the execution of the container, stored in the 'node.json' file in its log - collection. + collection. If the cost data was not correctly configured at the time the + container was executed, the output from this program will be incorrect. + + - If a container was run on a preemptible ("spot") instance, the cost data + reported by this program may be wildly inaccurate, because it does not have + access to the spot pricing in effect for the node then the container ran. The + UUID report file that is generated when the '-output' option is specified has + a column that indicates the preemptible state of the instance that ran the + container. In order to get the data for the uuids supplied, the ARVADOS_API_HOST and ARVADOS_API_TOKEN environment variables must be set. @@ -120,7 +121,7 @@ Options: if len(uuids) < 1 { flags.Usage() - err = fmt.Errorf("Error: no uuid(s) provided") + err = fmt.Errorf("error: no uuid(s) provided") exitCode = 2 return } @@ -181,7 +182,7 @@ func addContainerLine(logger *logrus.Logger, node nodeInfo, cr arvados.Container size = node.ProviderType } cost = delta.Seconds() / 3600 * price - csv += size + "," + strconv.FormatFloat(price, 'f', 8, 64) + "," + strconv.FormatFloat(cost, 'f', 8, 64) + "\n" + csv += size + "," + fmt.Sprintf("%+v", node.Preemptible) + "," + strconv.FormatFloat(price, 'f', 8, 64) + "," + strconv.FormatFloat(cost, 'f', 8, 64) + "\n" return } @@ -285,7 +286,7 @@ func loadObject(logger *logrus.Logger, ac *arvados.Client, path string, uuid str func getNode(arv *arvadosclient.ArvadosClient, ac *arvados.Client, kc *keepclient.KeepClient, cr arvados.ContainerRequest) (node nodeInfo, err error) { if cr.LogUUID == "" { - err = errors.New("No log collection") + err = errors.New("no log collection") return } @@ -369,7 +370,7 @@ func generateCrCsv(logger *logrus.Logger, uuid string, arv *arvadosclient.Arvado cost = make(map[string]float64) - csv := "CR UUID,CR name,Container UUID,State,Started At,Finished At,Duration in seconds,Compute node type,Hourly node cost,Total cost\n" + csv := "CR UUID,CR name,Container UUID,State,Started At,Finished At,Duration in seconds,Compute node type,Preemptible,Hourly node cost,Total cost\n" var tmpCsv string var tmpTotalCost float64 var totalCost float64 @@ -509,7 +510,7 @@ func costanalyzer(prog string, args []string, loader *config.Loader, logger *log var crCsv map[string]float64 crCsv, err = generateCrCsv(logger, uuid, arv, ac, kc, resultsDir, cache) if err != nil { - err = fmt.Errorf("Error generating CSV for uuid %s: %s", uuid, err.Error()) + err = fmt.Errorf("error generating CSV for uuid %s: %s", uuid, err.Error()) exitcode = 2 return } @@ -521,9 +522,9 @@ func costanalyzer(prog string, args []string, loader *config.Loader, logger *log // It is identified by the user uuid. As such, cost analysis for the // "Home" project is not supported by this program. Skip this uuid, but // keep going. - logger.Errorf("Cost analysis is not supported for the 'Home' project: %s", uuid) + logger.Errorf("cost analysis is not supported for the 'Home' project: %s", uuid) } else { - logger.Errorf("This argument does not look like a uuid: %s\n", uuid) + logger.Errorf("this argument does not look like a uuid: %s\n", uuid) exitcode = 3 return } @@ -554,7 +555,7 @@ func costanalyzer(prog string, args []string, loader *config.Loader, logger *log aFile := resultsDir + "/" + time.Now().Format("2006-01-02-15-04-05") + "-aggregate-costaccounting.csv" err = ioutil.WriteFile(aFile, []byte(csv), 0644) if err != nil { - err = fmt.Errorf("Error writing file with path %s: %s", aFile, err.Error()) + err = fmt.Errorf("error writing file with path %s: %s", aFile, err.Error()) exitcode = 1 return }