Add RBE metrics dump in Soong UI.
From aosp/1329396, the RBE metrics protobuf file is part of the
metrics uploading process. The RBE metrics protobuf file is
generated by running the bootstrap shutdown command. A new function
named DumpRBEMetrics was written in order to generate the RBE metrics
protobuf file before sending to the uploading process.
Bug: b/140638454
Test: * Unit test cases
* Ran RBE build on my local host and verified the
metrics protobuf file is created.
* Ran non-RBE build after RBE build and verified that
the previous metrics protobuf file was deleted.
Change-Id: I4b8068905cb67c4b8c2d94793917b98974fed707
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index ceea4bf..fcdab3b 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -15,14 +15,39 @@
package build
import (
+ "os"
"path/filepath"
"android/soong/ui/metrics"
)
-const bootstrapCmd = "bootstrap"
-const rbeLeastNProcs = 2500
-const rbeLeastNFiles = 16000
+const (
+ rbeLeastNProcs = 2500
+ rbeLeastNFiles = 16000
+
+ // prebuilt RBE binaries
+ bootstrapCmd = "bootstrap"
+
+ // RBE metrics proto buffer file
+ rbeMetricsPBFilename = "rbe_metrics.pb"
+)
+
+func rbeCommand(ctx Context, config Config, rbeCmd string) string {
+ var cmdPath string
+ if rbeDir, ok := config.Environment().Get("RBE_DIR"); ok {
+ cmdPath = filepath.Join(rbeDir, rbeCmd)
+ } else if home, ok := config.Environment().Get("HOME"); ok {
+ cmdPath = filepath.Join(home, "rbe", rbeCmd)
+ } else {
+ ctx.Fatalf("rbe command path not found")
+ }
+
+ if _, err := os.Stat(cmdPath); err != nil && os.IsNotExist(err) {
+ ctx.Fatalf("rbe command %q not found", rbeCmd)
+ }
+
+ return cmdPath
+}
func startRBE(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap")
@@ -35,18 +60,50 @@
ctx.Fatalf("max open files is insufficient: %d; want >= %d.\n", n, rbeLeastNFiles)
}
- var rbeBootstrap string
- if rbeDir, ok := config.Environment().Get("RBE_DIR"); ok {
- rbeBootstrap = filepath.Join(rbeDir, bootstrapCmd)
- } else if home, ok := config.Environment().Get("HOME"); ok {
- rbeBootstrap = filepath.Join(home, "rbe", bootstrapCmd)
- } else {
- ctx.Fatalln("rbe bootstrap not found")
- }
-
- cmd := Command(ctx, config, "boostrap", rbeBootstrap)
+ cmd := Command(ctx, config, "startRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd))
if output, err := cmd.CombinedOutput(); err != nil {
ctx.Fatalf("rbe bootstrap failed with: %v\n%s\n", err, output)
}
}
+
+func stopRBE(ctx Context, config Config) {
+ cmd := Command(ctx, config, "stopRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd), "-shutdown")
+ if output, err := cmd.CombinedOutput(); err != nil {
+ ctx.Fatalf("rbe bootstrap with shutdown failed with: %v\n%s\n", err, output)
+ }
+}
+
+// DumpRBEMetrics creates a metrics protobuf file containing RBE related metrics.
+// The protobuf file is created if RBE is enabled and the proxy service has
+// started. The proxy service is shutdown in order to dump the RBE metrics to the
+// protobuf file.
+func DumpRBEMetrics(ctx Context, config Config, filename string) {
+ ctx.BeginTrace(metrics.RunShutdownTool, "dump_rbe_metrics")
+ defer ctx.EndTrace()
+
+ // Remove the previous metrics file in case there is a failure or RBE has been
+ // disable for this run.
+ os.Remove(filename)
+
+ // If RBE is not enabled then there are no metrics to generate.
+ // If RBE does not require to start, the RBE proxy maybe started
+ // manually for debugging purpose and can generate the metrics
+ // afterwards.
+ if !config.StartRBE() {
+ return
+ }
+
+ outputDir := config.RBEStatsOutputDir()
+ if outputDir == "" {
+ ctx.Fatal("RBE output dir variable not defined. Aborting metrics dumping.")
+ }
+ metricsFile := filepath.Join(outputDir, rbeMetricsPBFilename)
+
+ // Stop the proxy first in order to generate the RBE metrics protobuf file.
+ stopRBE(ctx, config)
+
+ if _, err := copyFile(metricsFile, filename); err != nil {
+ ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err)
+ }
+}