| 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)) | |
| } |