blob: bdfcfb40566d94ceb4fa1d6c93b6ee604d8d9b33 [file] [log] [blame]
package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"time"
"github.com/bazelbuild/continuous-integration/metrics/clients"
"github.com/bazelbuild/continuous-integration/metrics/metrics"
"github.com/bazelbuild/continuous-integration/metrics/publishers"
"github.com/bazelbuild/continuous-integration/metrics/service"
)
var (
projectID = flag.String("project_id", "bazel-untrusted", "ID of the GCP project.")
datastoreSettingsName = flag.String("datastore_settings_name", "MetricSettings", "Name of the settings entity in Datastore.")
testMode = flag.Bool("test", false, "If true, the service will collect and publish all metrics immediately and only once.")
)
const megaByte = 1024 * 1024
func handleError(metricName string, err error) {
fmt.Printf("[%s] %v\n", metricName, err)
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "You should try https://bazel.build")
}
func minutes(value int) time.Duration {
return time.Duration(value) * time.Minute
}
func logInTestMode(message string) {
log.Printf("[Test mode] %s\n", message)
}
func main() {
flag.Parse()
settings, err := ReadSettingsFromDatastore(*projectID, *datastoreSettingsName)
if err != nil {
log.Fatalf("Could not read settings from Datastore: %v", err)
}
pipelines, err := settings.GetPipelineIDs()
if err != nil {
log.Fatalf("Could not get Buildkite pipeline IDs from Datastore: %v", err)
}
if len(pipelines) == 0 {
log.Fatalf("No pipelines were specified.")
}
bkAPI, err := clients.CreateBuildkiteAPI(settings.BuildkiteApiToken, settings.BuildkiteDebug)
if err != nil {
log.Fatalf("Cannot create Buildkite API client: %v", err)
}
bk := clients.CreateCachedBuildkiteClient(bkAPI, time.Duration(settings.BuildkiteCacheTimeoutMinutes)*time.Minute)
computeClient, err := clients.CreateComputeEngineClient()
if err != nil {
log.Fatalf("Cannot create Compute Engine client: %v", err)
}
storageClient, err := clients.CreateCloudStorageClient()
if err != nil {
log.Fatalf("Cannot create Cloud Storage client: %v", err)
}
stackdriverClient, err := clients.CreateStackdriverClient()
if err != nil {
log.Fatalf("Cannot create Stackdriver client: %v", err)
}
stackdriver := publishers.CreateStackdriverPublisher(stackdriverClient, *projectID)
stdout := publishers.CreateStdoutPublisher(publishers.Csv)
var defaultPublisher publishers.Publisher
if *testMode {
logInTestMode("Using stdout publisher for all metrics.")
defaultPublisher = stdout
} else {
defaultPublisher, err = publishers.CreateCloudSqlPublisher(settings.CloudSqlUser, settings.CloudSqlPassword, settings.CloudSqlInstance, settings.CloudSqlDatabase, settings.CloudSqlLocalPort)
if err != nil {
log.Fatalf("Failed to set up Cloud SQL publisher: %v", err)
}
}
srv := service.CreateService(handleError)
aggPipelinePerformance := metrics.CreateAggregatedPipelinePerformance(bk, 20, pipelines...)
srv.AddMetric(aggPipelinePerformance, minutes(10), defaultPublisher)
buildsPerChange := metrics.CreateBuildsPerChange(bk, 500, pipelines...)
srv.AddMetric(buildsPerChange, minutes(60), defaultPublisher)
buildSuccess := metrics.CreateBuildSuccess(bk, 200, pipelines...)
srv.AddMetric(buildSuccess, minutes(60), defaultPublisher)
ctx := context.Background()
cloudBuildStatus, err := metrics.CreateCloudBuildStatus(ctx, settings.CloudBuildProject, settings.CloudBuildSubscription)
if err != nil {
log.Fatalf("Failed to set up CloudBuildStatus metric: %v", err)
}
srv.AddMetric(cloudBuildStatus, minutes(5), defaultPublisher, stackdriver)
criticalPath := metrics.CreateCriticalPath(bk, 20, pipelines...)
srv.AddMetric(criticalPath, minutes(60), defaultPublisher)
dailyPerformance := metrics.CreateDailyPerformance(bk, 100, pipelines...)
srv.AddMetric(dailyPerformance, minutes(60), defaultPublisher)
flakiness := metrics.CreateFlakiness(storageClient, "bazel-buildkite-stats", "flaky-tests-bep", pipelines...)
srv.AddMetric(flakiness, minutes(60), defaultPublisher)
macPerformance := metrics.CreateMacPerformance(bk, 20, pipelines...)
srv.AddMetric(macPerformance, minutes(60), defaultPublisher)
pipelinePerformance := metrics.CreatePipelinePerformance(bk, 20, pipelines...)
srv.AddMetric(pipelinePerformance, minutes(10), defaultPublisher)
platformLoad := metrics.CreatePlatformLoad(bk, 100, settings.BuildkiteOrgs...)
srv.AddMetric(platformLoad, minutes(1), defaultPublisher, stackdriver)
platformSignificance := metrics.CreatePlatformSignificance(bk, 100, pipelines...)
srv.AddMetric(platformSignificance, minutes(24*60), defaultPublisher)
platformUsage := metrics.CreatePlatformUsage(bk, 100, settings.BuildkiteOrgs...)
srv.AddMetric(platformUsage, minutes(60), defaultPublisher)
releaseDownloads := metrics.CreateReleaseDownloads(settings.GitHubOrg,
settings.GitHubRepo,
settings.GitHubApiToken, megaByte)
srv.AddMetric(releaseDownloads, minutes(12*60), defaultPublisher)
workerAvailability := metrics.CreateWorkerAvailability(bk, settings.BuildkiteOrgs...)
srv.AddMetric(workerAvailability, minutes(5), defaultPublisher)
// TODO(fweikert): Read gracePeriod from Datastore
zombieInstances := metrics.CreateZombieInstances(computeClient, settings.CloudProjects, bk, settings.BuildkiteOrgs, minutes(3))
srv.AddMetric(zombieInstances, minutes(5), defaultPublisher)
if *testMode {
logInTestMode("Running all jobs exactly once...")
srv.RunJobsOnce()
os.Exit(0)
}
srv.Start()
http.HandleFunc("/", handleRequest)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}