fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 1 | package main |
| 2 | |
| 3 | import ( |
Florian Weikert | a880c3d | 2019-09-17 12:16:53 +0200 | [diff] [blame] | 4 | "context" |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 5 | "flag" |
| 6 | "fmt" |
| 7 | "log" |
fweikert | 58286bb | 2019-05-15 16:01:46 +0200 | [diff] [blame] | 8 | "net/http" |
fweikert | 0154b44 | 2019-03-29 15:41:05 +0100 | [diff] [blame] | 9 | "os" |
Florian Weikert | ad51972 | 2019-06-25 14:26:10 +0200 | [diff] [blame] | 10 | "time" |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 11 | |
fweikert | a2366cf | 2019-07-22 16:36:29 +0200 | [diff] [blame] | 12 | "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" |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 16 | ) |
| 17 | |
| 18 | var ( |
fweikert | d9242ff | 2019-04-01 15:08:33 +0200 | [diff] [blame] | 19 | 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.") |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 22 | ) |
| 23 | |
Florian Weikert | a9bfd17 | 2019-03-28 14:30:59 +0100 | [diff] [blame] | 24 | const megaByte = 1024 * 1024 |
| 25 | |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 26 | func handleError(metricName string, err error) { |
fweikert | ba7e27d | 2019-03-29 16:41:38 +0100 | [diff] [blame] | 27 | fmt.Printf("[%s] %v\n", metricName, err) |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 28 | } |
| 29 | |
fweikert | 58286bb | 2019-05-15 16:01:46 +0200 | [diff] [blame] | 30 | func handleRequest(w http.ResponseWriter, r *http.Request) { |
| 31 | fmt.Fprintln(w, "You should try https://bazel.build") |
| 32 | } |
| 33 | |
Florian Weikert | ad51972 | 2019-06-25 14:26:10 +0200 | [diff] [blame] | 34 | func minutes(value int) time.Duration { |
| 35 | return time.Duration(value) * time.Minute |
| 36 | } |
| 37 | |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 38 | func logInTestMode(message string) { |
| 39 | log.Printf("[Test mode] %s\n", message) |
| 40 | } |
| 41 | |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 42 | func main() { |
| 43 | flag.Parse() |
| 44 | |
fweikert | d9242ff | 2019-04-01 15:08:33 +0200 | [diff] [blame] | 45 | settings, err := ReadSettingsFromDatastore(*projectID, *datastoreSettingsName) |
| 46 | if err != nil { |
| 47 | log.Fatalf("Could not read settings from Datastore: %v", err) |
| 48 | } |
fweikert | acf50c6 | 2019-06-11 19:21:58 +0200 | [diff] [blame] | 49 | 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 { |
fweikert | e1fcf1a | 2019-03-28 10:00:03 +0100 | [diff] [blame] | 54 | log.Fatalf("No pipelines were specified.") |
| 55 | } |
fweikert | e1fcf1a | 2019-03-28 10:00:03 +0100 | [diff] [blame] | 56 | |
fweikert | 2041b2c | 2019-07-05 18:15:30 +0200 | [diff] [blame] | 57 | bkAPI, err := clients.CreateBuildkiteAPI(settings.BuildkiteApiToken, settings.BuildkiteDebug) |
fweikert | 4b53c97 | 2019-06-14 17:19:50 +0200 | [diff] [blame] | 58 | if err != nil { |
fweikert | 2041b2c | 2019-07-05 18:15:30 +0200 | [diff] [blame] | 59 | log.Fatalf("Cannot create Buildkite API client: %v", err) |
fweikert | 4b53c97 | 2019-06-14 17:19:50 +0200 | [diff] [blame] | 60 | } |
fweikert | 2041b2c | 2019-07-05 18:15:30 +0200 | [diff] [blame] | 61 | bk := clients.CreateCachedBuildkiteClient(bkAPI, time.Duration(settings.BuildkiteCacheTimeoutMinutes)*time.Minute) |
fweikert | 6011f92 | 2019-05-14 14:54:51 +0200 | [diff] [blame] | 62 | |
Florian Weikert | 9bd3b57 | 2019-07-24 14:47:30 +0200 | [diff] [blame] | 63 | computeClient, err := clients.CreateComputeEngineClient() |
| 64 | if err != nil { |
| 65 | log.Fatalf("Cannot create Compute Engine client: %v", err) |
| 66 | } |
| 67 | |
Florian Weikert | e2ca0ce | 2019-07-23 20:01:26 +0200 | [diff] [blame] | 68 | storageClient, err := clients.CreateCloudStorageClient() |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 69 | if err != nil { |
Florian Weikert | e2ca0ce | 2019-07-23 20:01:26 +0200 | [diff] [blame] | 70 | log.Fatalf("Cannot create Cloud Storage client: %v", err) |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 71 | } |
| 72 | |
Florian Weikert | 8cc6748 | 2019-09-09 17:58:31 +0200 | [diff] [blame] | 73 | stackdriverClient, err := clients.CreateStackdriverClient() |
| 74 | if err != nil { |
| 75 | log.Fatalf("Cannot create Stackdriver client: %v", err) |
| 76 | } |
fweikert | 761cebd | 2019-06-12 15:06:04 +0200 | [diff] [blame] | 77 | |
Florian Weikert | 8cc6748 | 2019-09-09 17:58:31 +0200 | [diff] [blame] | 78 | stackdriver := publishers.CreateStackdriverPublisher(stackdriverClient, *projectID) |
fweikert | 35c412d | 2019-05-15 15:30:58 +0200 | [diff] [blame] | 79 | |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 80 | stdout := publishers.CreateStdoutPublisher(publishers.Csv) |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 81 | |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 82 | 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 | } |
fweikert | 6964d3a | 2019-03-29 13:03:48 +0100 | [diff] [blame] | 92 | |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 93 | srv := service.CreateService(handleError) |
fweikert | ba7e27d | 2019-03-29 16:41:38 +0100 | [diff] [blame] | 94 | |
Florian Weikert | 802c795 | 2020-02-20 17:13:17 +0100 | [diff] [blame] | 95 | aggPipelinePerformance := metrics.CreateAggregatedPipelinePerformance(bk, 20, pipelines...) |
| 96 | srv.AddMetric(aggPipelinePerformance, minutes(10), defaultPublisher) |
| 97 | |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 98 | buildsPerChange := metrics.CreateBuildsPerChange(bk, 500, pipelines...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 99 | srv.AddMetric(buildsPerChange, minutes(60), defaultPublisher) |
fweikert | 6e3d5d5 | 2019-06-17 14:31:53 +0200 | [diff] [blame] | 100 | |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 101 | buildSuccess := metrics.CreateBuildSuccess(bk, 200, pipelines...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 102 | srv.AddMetric(buildSuccess, minutes(60), defaultPublisher) |
fweikert | 6e3d5d5 | 2019-06-17 14:31:53 +0200 | [diff] [blame] | 103 | |
Florian Weikert | a5f6fc5 | 2019-09-17 12:42:52 +0200 | [diff] [blame] | 104 | 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 | |
fweikert | 592af0e | 2019-06-24 19:22:11 +0200 | [diff] [blame] | 111 | criticalPath := metrics.CreateCriticalPath(bk, 20, pipelines...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 112 | srv.AddMetric(criticalPath, minutes(60), defaultPublisher) |
fweikert | 592af0e | 2019-06-24 19:22:11 +0200 | [diff] [blame] | 113 | |
Florian Weikert | 85b2f19 | 2020-02-21 12:28:27 +0100 | [diff] [blame] | 114 | dailyPerformance := metrics.CreateDailyPerformance(bk, 100, pipelines...) |
| 115 | srv.AddMetric(dailyPerformance, minutes(60), defaultPublisher) |
| 116 | |
Florian Weikert | e2ca0ce | 2019-07-23 20:01:26 +0200 | [diff] [blame] | 117 | flakiness := metrics.CreateFlakiness(storageClient, "bazel-buildkite-stats", "flaky-tests-bep", pipelines...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 118 | srv.AddMetric(flakiness, minutes(60), defaultPublisher) |
fweikert | 6e3d5d5 | 2019-06-17 14:31:53 +0200 | [diff] [blame] | 119 | |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 120 | macPerformance := metrics.CreateMacPerformance(bk, 20, pipelines...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 121 | srv.AddMetric(macPerformance, minutes(60), defaultPublisher) |
fweikert | 6e3d5d5 | 2019-06-17 14:31:53 +0200 | [diff] [blame] | 122 | |
fweikert | e3c5663 | 2019-07-11 17:19:22 +0200 | [diff] [blame] | 123 | pipelinePerformance := metrics.CreatePipelinePerformance(bk, 20, pipelines...) |
| 124 | srv.AddMetric(pipelinePerformance, minutes(10), defaultPublisher) |
fweikert | 6e3d5d5 | 2019-06-17 14:31:53 +0200 | [diff] [blame] | 125 | |
fweikert | 4b53c97 | 2019-06-14 17:19:50 +0200 | [diff] [blame] | 126 | platformLoad := metrics.CreatePlatformLoad(bk, 100, settings.BuildkiteOrgs...) |
Florian Weikert | 3a1f861 | 2019-09-10 15:40:10 +0200 | [diff] [blame] | 127 | srv.AddMetric(platformLoad, minutes(1), defaultPublisher, stackdriver) |
fweikert | d230ce2 | 2019-05-08 18:08:51 +0200 | [diff] [blame] | 128 | |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 129 | platformSignificance := metrics.CreatePlatformSignificance(bk, 100, pipelines...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 130 | srv.AddMetric(platformSignificance, minutes(24*60), defaultPublisher) |
Florian Weikert | fee4ed9 | 2019-04-08 15:18:02 +0200 | [diff] [blame] | 131 | |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 132 | platformUsage := metrics.CreatePlatformUsage(bk, 100, settings.BuildkiteOrgs...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 133 | srv.AddMetric(platformUsage, minutes(60), defaultPublisher) |
fweikert | 6011f92 | 2019-05-14 14:54:51 +0200 | [diff] [blame] | 134 | |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 135 | releaseDownloads := metrics.CreateReleaseDownloads(settings.GitHubOrg, |
| 136 | settings.GitHubRepo, |
| 137 | settings.GitHubApiToken, megaByte) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 138 | srv.AddMetric(releaseDownloads, minutes(12*60), defaultPublisher) |
fweikert | 1c63b36 | 2019-05-10 18:02:37 +0200 | [diff] [blame] | 139 | |
fweikert | 5a2b617 | 2019-06-17 14:34:06 +0200 | [diff] [blame] | 140 | workerAvailability := metrics.CreateWorkerAvailability(bk, settings.BuildkiteOrgs...) |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 141 | srv.AddMetric(workerAvailability, minutes(5), defaultPublisher) |
fweikert | ba7e27d | 2019-03-29 16:41:38 +0100 | [diff] [blame] | 142 | |
Florian Weikert | 9bd3b57 | 2019-07-24 14:47:30 +0200 | [diff] [blame] | 143 | // 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 | |
fweikert | d9242ff | 2019-04-01 15:08:33 +0200 | [diff] [blame] | 147 | if *testMode { |
fweikert | 645d459 | 2019-06-27 18:49:56 +0200 | [diff] [blame] | 148 | logInTestMode("Running all jobs exactly once...") |
fweikert | d9242ff | 2019-04-01 15:08:33 +0200 | [diff] [blame] | 149 | srv.RunJobsOnce() |
fweikert | 58286bb | 2019-05-15 16:01:46 +0200 | [diff] [blame] | 150 | os.Exit(0) |
fweikert | d9242ff | 2019-04-01 15:08:33 +0200 | [diff] [blame] | 151 | } |
fweikert | 58286bb | 2019-05-15 16:01:46 +0200 | [diff] [blame] | 152 | |
| 153 | srv.Start() |
| 154 | http.HandleFunc("/", handleRequest) |
fweikert | c94528e | 2019-06-14 12:57:20 +0200 | [diff] [blame] | 155 | |
| 156 | port := os.Getenv("PORT") |
| 157 | if port == "" { |
| 158 | port = "8080" |
| 159 | } |
| 160 | log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) |
fweikert | ebe8b8e | 2019-03-27 16:51:43 +0100 | [diff] [blame] | 161 | } |