blob: bdfcfb40566d94ceb4fa1d6c93b6ee604d8d9b33 [file] [log] [blame]
fweikertebe8b8e2019-03-27 16:51:43 +01001package main
2
3import (
Florian Weikerta880c3d2019-09-17 12:16:53 +02004 "context"
fweikertebe8b8e2019-03-27 16:51:43 +01005 "flag"
6 "fmt"
7 "log"
fweikert58286bb2019-05-15 16:01:46 +02008 "net/http"
fweikert0154b442019-03-29 15:41:05 +01009 "os"
Florian Weikertad519722019-06-25 14:26:10 +020010 "time"
fweikertebe8b8e2019-03-27 16:51:43 +010011
fweikerta2366cf2019-07-22 16:36:29 +020012 "github.com/bazelbuild/continuous-integration/metrics/clients"
13 "github.com/bazelbuild/continuous-integration/metrics/metrics"
14 "github.com/bazelbuild/continuous-integration/metrics/publishers"
15 "github.com/bazelbuild/continuous-integration/metrics/service"
fweikertebe8b8e2019-03-27 16:51:43 +010016)
17
18var (
fweikertd9242ff2019-04-01 15:08:33 +020019 projectID = flag.String("project_id", "bazel-untrusted", "ID of the GCP project.")
20 datastoreSettingsName = flag.String("datastore_settings_name", "MetricSettings", "Name of the settings entity in Datastore.")
21 testMode = flag.Bool("test", false, "If true, the service will collect and publish all metrics immediately and only once.")
fweikertebe8b8e2019-03-27 16:51:43 +010022)
23
Florian Weikerta9bfd172019-03-28 14:30:59 +010024const megaByte = 1024 * 1024
25
fweikertebe8b8e2019-03-27 16:51:43 +010026func handleError(metricName string, err error) {
fweikertba7e27d2019-03-29 16:41:38 +010027 fmt.Printf("[%s] %v\n", metricName, err)
fweikertebe8b8e2019-03-27 16:51:43 +010028}
29
fweikert58286bb2019-05-15 16:01:46 +020030func handleRequest(w http.ResponseWriter, r *http.Request) {
31 fmt.Fprintln(w, "You should try https://bazel.build")
32}
33
Florian Weikertad519722019-06-25 14:26:10 +020034func minutes(value int) time.Duration {
35 return time.Duration(value) * time.Minute
36}
37
fweikert645d4592019-06-27 18:49:56 +020038func logInTestMode(message string) {
39 log.Printf("[Test mode] %s\n", message)
40}
41
fweikertebe8b8e2019-03-27 16:51:43 +010042func main() {
43 flag.Parse()
44
fweikertd9242ff2019-04-01 15:08:33 +020045 settings, err := ReadSettingsFromDatastore(*projectID, *datastoreSettingsName)
46 if err != nil {
47 log.Fatalf("Could not read settings from Datastore: %v", err)
48 }
fweikertacf50c62019-06-11 19:21:58 +020049 pipelines, err := settings.GetPipelineIDs()
50 if err != nil {
51 log.Fatalf("Could not get Buildkite pipeline IDs from Datastore: %v", err)
52 }
53 if len(pipelines) == 0 {
fweikerte1fcf1a2019-03-28 10:00:03 +010054 log.Fatalf("No pipelines were specified.")
55 }
fweikerte1fcf1a2019-03-28 10:00:03 +010056
fweikert2041b2c2019-07-05 18:15:30 +020057 bkAPI, err := clients.CreateBuildkiteAPI(settings.BuildkiteApiToken, settings.BuildkiteDebug)
fweikert4b53c972019-06-14 17:19:50 +020058 if err != nil {
fweikert2041b2c2019-07-05 18:15:30 +020059 log.Fatalf("Cannot create Buildkite API client: %v", err)
fweikert4b53c972019-06-14 17:19:50 +020060 }
fweikert2041b2c2019-07-05 18:15:30 +020061 bk := clients.CreateCachedBuildkiteClient(bkAPI, time.Duration(settings.BuildkiteCacheTimeoutMinutes)*time.Minute)
fweikert6011f922019-05-14 14:54:51 +020062
Florian Weikert9bd3b572019-07-24 14:47:30 +020063 computeClient, err := clients.CreateComputeEngineClient()
64 if err != nil {
65 log.Fatalf("Cannot create Compute Engine client: %v", err)
66 }
67
Florian Weikerte2ca0ce2019-07-23 20:01:26 +020068 storageClient, err := clients.CreateCloudStorageClient()
fweikert5a2b6172019-06-17 14:34:06 +020069 if err != nil {
Florian Weikerte2ca0ce2019-07-23 20:01:26 +020070 log.Fatalf("Cannot create Cloud Storage client: %v", err)
fweikert5a2b6172019-06-17 14:34:06 +020071 }
72
Florian Weikert8cc67482019-09-09 17:58:31 +020073 stackdriverClient, err := clients.CreateStackdriverClient()
74 if err != nil {
75 log.Fatalf("Cannot create Stackdriver client: %v", err)
76 }
fweikert761cebd2019-06-12 15:06:04 +020077
Florian Weikert8cc67482019-09-09 17:58:31 +020078 stackdriver := publishers.CreateStackdriverPublisher(stackdriverClient, *projectID)
fweikert35c412d2019-05-15 15:30:58 +020079
fweikert645d4592019-06-27 18:49:56 +020080 stdout := publishers.CreateStdoutPublisher(publishers.Csv)
fweikert5a2b6172019-06-17 14:34:06 +020081
fweikert645d4592019-06-27 18:49:56 +020082 var defaultPublisher publishers.Publisher
83 if *testMode {
84 logInTestMode("Using stdout publisher for all metrics.")
85 defaultPublisher = stdout
86 } else {
87 defaultPublisher, err = publishers.CreateCloudSqlPublisher(settings.CloudSqlUser, settings.CloudSqlPassword, settings.CloudSqlInstance, settings.CloudSqlDatabase, settings.CloudSqlLocalPort)
88 if err != nil {
89 log.Fatalf("Failed to set up Cloud SQL publisher: %v", err)
90 }
91 }
fweikert6964d3a2019-03-29 13:03:48 +010092
fweikertebe8b8e2019-03-27 16:51:43 +010093 srv := service.CreateService(handleError)
fweikertba7e27d2019-03-29 16:41:38 +010094
Florian Weikert802c7952020-02-20 17:13:17 +010095 aggPipelinePerformance := metrics.CreateAggregatedPipelinePerformance(bk, 20, pipelines...)
96 srv.AddMetric(aggPipelinePerformance, minutes(10), defaultPublisher)
97
fweikert5a2b6172019-06-17 14:34:06 +020098 buildsPerChange := metrics.CreateBuildsPerChange(bk, 500, pipelines...)
fweikert645d4592019-06-27 18:49:56 +020099 srv.AddMetric(buildsPerChange, minutes(60), defaultPublisher)
fweikert6e3d5d52019-06-17 14:31:53 +0200100
fweikert5a2b6172019-06-17 14:34:06 +0200101 buildSuccess := metrics.CreateBuildSuccess(bk, 200, pipelines...)
fweikert645d4592019-06-27 18:49:56 +0200102 srv.AddMetric(buildSuccess, minutes(60), defaultPublisher)
fweikert6e3d5d52019-06-17 14:31:53 +0200103
Florian Weikerta5f6fc52019-09-17 12:42:52 +0200104 ctx := context.Background()
105 cloudBuildStatus, err := metrics.CreateCloudBuildStatus(ctx, settings.CloudBuildProject, settings.CloudBuildSubscription)
106 if err != nil {
107 log.Fatalf("Failed to set up CloudBuildStatus metric: %v", err)
108 }
109 srv.AddMetric(cloudBuildStatus, minutes(5), defaultPublisher, stackdriver)
110
fweikert592af0e2019-06-24 19:22:11 +0200111 criticalPath := metrics.CreateCriticalPath(bk, 20, pipelines...)
fweikert645d4592019-06-27 18:49:56 +0200112 srv.AddMetric(criticalPath, minutes(60), defaultPublisher)
fweikert592af0e2019-06-24 19:22:11 +0200113
Florian Weikert85b2f192020-02-21 12:28:27 +0100114 dailyPerformance := metrics.CreateDailyPerformance(bk, 100, pipelines...)
115 srv.AddMetric(dailyPerformance, minutes(60), defaultPublisher)
116
Florian Weikerte2ca0ce2019-07-23 20:01:26 +0200117 flakiness := metrics.CreateFlakiness(storageClient, "bazel-buildkite-stats", "flaky-tests-bep", pipelines...)
fweikert645d4592019-06-27 18:49:56 +0200118 srv.AddMetric(flakiness, minutes(60), defaultPublisher)
fweikert6e3d5d52019-06-17 14:31:53 +0200119
fweikert5a2b6172019-06-17 14:34:06 +0200120 macPerformance := metrics.CreateMacPerformance(bk, 20, pipelines...)
fweikert645d4592019-06-27 18:49:56 +0200121 srv.AddMetric(macPerformance, minutes(60), defaultPublisher)
fweikert6e3d5d52019-06-17 14:31:53 +0200122
fweikerte3c56632019-07-11 17:19:22 +0200123 pipelinePerformance := metrics.CreatePipelinePerformance(bk, 20, pipelines...)
124 srv.AddMetric(pipelinePerformance, minutes(10), defaultPublisher)
fweikert6e3d5d52019-06-17 14:31:53 +0200125
fweikert4b53c972019-06-14 17:19:50 +0200126 platformLoad := metrics.CreatePlatformLoad(bk, 100, settings.BuildkiteOrgs...)
Florian Weikert3a1f8612019-09-10 15:40:10 +0200127 srv.AddMetric(platformLoad, minutes(1), defaultPublisher, stackdriver)
fweikertd230ce22019-05-08 18:08:51 +0200128
fweikert5a2b6172019-06-17 14:34:06 +0200129 platformSignificance := metrics.CreatePlatformSignificance(bk, 100, pipelines...)
fweikert645d4592019-06-27 18:49:56 +0200130 srv.AddMetric(platformSignificance, minutes(24*60), defaultPublisher)
Florian Weikertfee4ed92019-04-08 15:18:02 +0200131
fweikert5a2b6172019-06-17 14:34:06 +0200132 platformUsage := metrics.CreatePlatformUsage(bk, 100, settings.BuildkiteOrgs...)
fweikert645d4592019-06-27 18:49:56 +0200133 srv.AddMetric(platformUsage, minutes(60), defaultPublisher)
fweikert6011f922019-05-14 14:54:51 +0200134
fweikert5a2b6172019-06-17 14:34:06 +0200135 releaseDownloads := metrics.CreateReleaseDownloads(settings.GitHubOrg,
136 settings.GitHubRepo,
137 settings.GitHubApiToken, megaByte)
fweikert645d4592019-06-27 18:49:56 +0200138 srv.AddMetric(releaseDownloads, minutes(12*60), defaultPublisher)
fweikert1c63b362019-05-10 18:02:37 +0200139
fweikert5a2b6172019-06-17 14:34:06 +0200140 workerAvailability := metrics.CreateWorkerAvailability(bk, settings.BuildkiteOrgs...)
fweikert645d4592019-06-27 18:49:56 +0200141 srv.AddMetric(workerAvailability, minutes(5), defaultPublisher)
fweikertba7e27d2019-03-29 16:41:38 +0100142
Florian Weikert9bd3b572019-07-24 14:47:30 +0200143 // TODO(fweikert): Read gracePeriod from Datastore
144 zombieInstances := metrics.CreateZombieInstances(computeClient, settings.CloudProjects, bk, settings.BuildkiteOrgs, minutes(3))
145 srv.AddMetric(zombieInstances, minutes(5), defaultPublisher)
146
fweikertd9242ff2019-04-01 15:08:33 +0200147 if *testMode {
fweikert645d4592019-06-27 18:49:56 +0200148 logInTestMode("Running all jobs exactly once...")
fweikertd9242ff2019-04-01 15:08:33 +0200149 srv.RunJobsOnce()
fweikert58286bb2019-05-15 16:01:46 +0200150 os.Exit(0)
fweikertd9242ff2019-04-01 15:08:33 +0200151 }
fweikert58286bb2019-05-15 16:01:46 +0200152
153 srv.Start()
154 http.HandleFunc("/", handleRequest)
fweikertc94528e2019-06-14 12:57:20 +0200155
156 port := os.Getenv("PORT")
157 if port == "" {
158 port = "8080"
159 }
160 log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
fweikertebe8b8e2019-03-27 16:51:43 +0100161}