blob: 4f30136b9bb0366f5412dd37352260e8501a16fa [file] [log] [blame]
Patrice Arruda219eef32020-06-01 17:29:30 +00001// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package build
16
17// This file contains the functionality to upload data from one location to
18// another.
19
20import (
21 "io/ioutil"
22 "os"
23 "path/filepath"
24 "time"
25
Patrice Arruda7cc20742020-06-10 18:48:01 +000026 "android/soong/ui/metrics"
Patrice Arruda219eef32020-06-01 17:29:30 +000027 "github.com/golang/protobuf/proto"
28
29 upload_proto "android/soong/ui/metrics/upload_proto"
30)
31
32const (
Patrice Arruda92dc64f2020-11-16 16:29:16 -080033 // Used to generate a raw protobuf file that contains information
34 // of the list of metrics files from host to destination storage.
Patrice Arruda219eef32020-06-01 17:29:30 +000035 uploadPbFilename = ".uploader.pb"
36)
37
Patrice Arruda7cc20742020-06-10 18:48:01 +000038var (
Patrice Arruda92dc64f2020-11-16 16:29:16 -080039 // For testing purpose.
40 tmpDir = ioutil.TempDir
Patrice Arruda7cc20742020-06-10 18:48:01 +000041)
42
Patrice Arruda219eef32020-06-01 17:29:30 +000043// UploadMetrics uploads a set of metrics files to a server for analysis. An
Patrice Arruda92dc64f2020-11-16 16:29:16 -080044// uploader full path is specified in ANDROID_ENABLE_METRICS_UPLOAD environment
45// variable in order to upload the set of metrics files. The metrics files are
46// first copied to a temporary directory and the uploader is then executed in
47// the background to allow the user/system to continue working. Soong communicates
48// to the uploader through the upload_proto raw protobuf file.
Patrice Arrudaf445ba12020-07-28 17:49:01 +000049func UploadMetrics(ctx Context, config Config, simpleOutput bool, buildStarted time.Time, files ...string) {
Patrice Arruda7cc20742020-06-10 18:48:01 +000050 ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics")
51 defer ctx.EndTrace()
52
Patrice Arruda219eef32020-06-01 17:29:30 +000053 uploader := config.MetricsUploaderApp()
Patrice Arruda219eef32020-06-01 17:29:30 +000054 if uploader == "" {
Patrice Arruda92dc64f2020-11-16 16:29:16 -080055 // If the uploader path was not specified, no metrics shall be uploaded.
Patrice Arruda219eef32020-06-01 17:29:30 +000056 return
57 }
58
Patrice Arruda92dc64f2020-11-16 16:29:16 -080059 // Some files passed in to this function may not exist. For example,
60 // build errors protobuf file may not exist since the build was successful.
Patrice Arruda219eef32020-06-01 17:29:30 +000061 var metricsFiles []string
62 for _, f := range files {
63 if _, err := os.Stat(f); err == nil {
64 metricsFiles = append(metricsFiles, f)
65 }
66 }
67
68 if len(metricsFiles) == 0 {
69 return
70 }
71
Patrice Arruda7cc20742020-06-10 18:48:01 +000072 // The temporary directory cannot be deleted as the metrics uploader is started
73 // in the background and requires to exist until the operation is done. The
74 // uploader can delete the directory as it is specified in the upload proto.
Patrice Arruda92dc64f2020-11-16 16:29:16 -080075 tmpDir, err := tmpDir("", "upload_metrics")
Patrice Arruda7cc20742020-06-10 18:48:01 +000076 if err != nil {
77 ctx.Fatalf("failed to create a temporary directory to store the list of metrics files: %v\n", err)
78 }
79
80 for i, src := range metricsFiles {
81 dst := filepath.Join(tmpDir, filepath.Base(src))
82 if _, err := copyFile(src, dst); err != nil {
83 ctx.Fatalf("failed to copy %q to %q: %v\n", src, dst, err)
84 }
85 metricsFiles[i] = dst
86 }
87
Patrice Arruda219eef32020-06-01 17:29:30 +000088 // For platform builds, the branch and target name is hardcoded to specific
89 // values for later extraction of the metrics in the data metrics pipeline.
90 data, err := proto.Marshal(&upload_proto.Upload{
Patrice Arruda73c790f2020-07-13 23:01:18 +000091 CreationTimestampMs: proto.Uint64(uint64(buildStarted.UnixNano() / int64(time.Millisecond))),
Patrice Arruda219eef32020-06-01 17:29:30 +000092 CompletionTimestampMs: proto.Uint64(uint64(time.Now().UnixNano() / int64(time.Millisecond))),
93 BranchName: proto.String("developer-metrics"),
94 TargetName: proto.String("platform-build-systems-metrics"),
95 MetricsFiles: metricsFiles,
Patrice Arruda7cc20742020-06-10 18:48:01 +000096 DirectoriesToDelete: []string{tmpDir},
Patrice Arruda219eef32020-06-01 17:29:30 +000097 })
98 if err != nil {
99 ctx.Fatalf("failed to marshal metrics upload proto buffer message: %v\n", err)
100 }
101
Patrice Arruda7cc20742020-06-10 18:48:01 +0000102 pbFile := filepath.Join(tmpDir, uploadPbFilename)
Patrice Arruda219eef32020-06-01 17:29:30 +0000103 if err := ioutil.WriteFile(pbFile, data, 0644); err != nil {
104 ctx.Fatalf("failed to write the marshaled metrics upload protobuf to %q: %v\n", pbFile, err)
105 }
Patrice Arruda219eef32020-06-01 17:29:30 +0000106
Patrice Arruda7cc20742020-06-10 18:48:01 +0000107 // Start the uploader in the background as it takes several milliseconds to start the uploader
Patrice Arruda92dc64f2020-11-16 16:29:16 -0800108 // and prepare the metrics for upload. This affects small shell commands like "lunch".
Patrice Arruda7cc20742020-06-10 18:48:01 +0000109 cmd := Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile)
Patrice Arrudaf445ba12020-07-28 17:49:01 +0000110 if simpleOutput {
Patrice Arruda7cc20742020-06-10 18:48:01 +0000111 cmd.RunOrFatal()
112 } else {
113 cmd.RunAndStreamOrFatal()
114 }
Patrice Arruda219eef32020-06-01 17:29:30 +0000115}