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