blob: 18b1476c872aa5c14315339d03652246b88f0e16 [file] [log] [blame]
package metrics
import (
"fmt"
"strings"
"time"
"github.com/bazelbuild/continuous-integration/metrics/clients"
"github.com/bazelbuild/continuous-integration/metrics/data"
)
type WorkerAvailability struct {
client clients.BuildkiteClient
orgs []string
columns []Column
}
func (wa *WorkerAvailability) Name() string {
return "worker_availability"
}
func (wa *WorkerAvailability) Columns() []Column {
return wa.columns
}
func (wa *WorkerAvailability) Type() MetricType {
return TimeBasedMetric
}
func (wa *WorkerAvailability) RelevantDelta() int {
return 24 * 60 * 60 // 24 hours
}
func (wa *WorkerAvailability) Collect() (data.DataSet, error) {
ts := time.Now()
result := data.CreateDataSet(GetColumnNames(wa.columns))
for _, org := range wa.orgs {
allPlatforms, err := wa.getIdleAndBusyCountsPerPlatform(org)
if err != nil {
return nil, err
}
for platform, counts := range allPlatforms {
err = result.AddRow(ts, org, platform, counts[0], counts[1])
if err != nil {
return nil, err
}
}
}
return result, nil
}
func (wa *WorkerAvailability) getIdleAndBusyCountsPerPlatform(org string) (map[string]*[2]int, error) {
agents, err := wa.client.GetAgents(org)
if err != nil {
return nil, fmt.Errorf("Cannot retrieve agents from Buildkite: %v", err)
}
allPlatforms := make(map[string]*[2]int)
for _, a := range agents {
platform, err := getPlatformForHost(*a.Hostname)
if err != nil {
return nil, err
}
if _, ok := allPlatforms[platform]; !ok {
allPlatforms[platform] = &[2]int{0, 0}
}
var index int
if a.Job != nil {
index = 1
}
allPlatforms[platform][index] += 1
}
return allPlatforms, nil
}
func getPlatformForHost(hostName string) (string, error) {
pos := strings.LastIndex(hostName, "-")
if pos < 0 {
return "", fmt.Errorf("Unknown host name '%s' cannot be resolved to a platform.", hostName)
}
return hostName[:pos], nil
}
// CREATE TABLE worker_availability (timestamp DATETIME, org VARCHAR(255), platform VARCHAR(255), idle_count INT, busy_count INT, PRIMARY KEY(timestamp, org, platform));
func CreateWorkerAvailability(client clients.BuildkiteClient, orgs ...string) *WorkerAvailability {
columns := []Column{Column{"timestamp", true}, Column{"org", true}, Column{"platform", true}, Column{"idle_count", false}, Column{"busy_count", false}}
return &WorkerAvailability{client: client, orgs: orgs, columns: columns}
}