OLD | NEW |
---|---|
(Empty) | |
1 // run_chromium_analysis_on_workers is an application that runs the specified | |
2 // telemetry benchmark on swarming bots and uploads the results to Google | |
3 // Storage. The requester is emailed when the task is done. | |
4 package main | |
5 | |
6 import ( | |
7 "flag" | |
8 "fmt" | |
9 "os" | |
10 "path/filepath" | |
11 "strings" | |
12 "time" | |
13 | |
14 "github.com/skia-dev/glog" | |
15 "go.skia.org/infra/ct/go/frontend" | |
16 "go.skia.org/infra/ct/go/master_scripts/master_common" | |
17 "go.skia.org/infra/ct/go/util" | |
18 "go.skia.org/infra/go/common" | |
19 "go.skia.org/infra/go/email" | |
20 skutil "go.skia.org/infra/go/util" | |
21 ) | |
22 | |
23 const ( | |
24 MAX_PAGES_PER_SWARMING_BOT = 100 | |
25 ) | |
26 | |
27 var ( | |
28 emails = flag.String("emails", "", "The comma separated emai l addresses to notify when the task is picked up and completes.") | |
29 description = flag.String("description", "", "The description of the run as entered by the requester.") | |
30 gaeTaskID = flag.Int64("gae_task_id", -1, "The key of the App E ngine task. This task will be updated when the task is completed.") | |
dogben
2016/05/19 21:06:41
Should probably update the doc string, if not the
rmistry
2016/05/20 11:07:16
Ah looks like all master scripts have this. Will m
| |
31 pagesetType = flag.String("pageset_type", "", "The type of pagese ts to use. Eg: 10k, Mobile10k, All.") | |
32 benchmarkName = flag.String("benchmark_name", "", "The telemetry be nchmark to run on the workers.") | |
33 benchmarkExtraArgs = flag.String("benchmark_extra_args", "", "The extra arguments that are passed to the specified benchmark.") | |
34 browserExtraArgs = flag.String("browser_extra_args", "", "The extra ar guments that are passed to the browser while running the benchmark.") | |
35 runID = flag.String("run_id", "", "The unique run id (typic ally requester + timestamp).") | |
36 | |
37 taskCompletedSuccessfully = false | |
38 | |
39 chromiumPatchLink = util.MASTER_LOGSERVER_LINK | |
40 benchmarkPatchLink = util.MASTER_LOGSERVER_LINK | |
41 outputLink = util.MASTER_LOGSERVER_LINK | |
42 ) | |
43 | |
44 func sendEmail(recipients []string) { | |
45 // Send completion email. | |
46 emailSubject := fmt.Sprintf("Cluster telemetry chromium analysis task ha s completed (%s)", *runID) | |
47 failureHtml := "" | |
48 viewActionMarkup := "" | |
49 var err error | |
50 | |
51 if taskCompletedSuccessfully { | |
52 if viewActionMarkup, err = email.GetViewActionMarkup(outputLink, "View Results", "Direct link to the CSV results"); err != nil { | |
53 glog.Errorf("Failed to get view action markup: %s", err) | |
54 return | |
55 } | |
56 } else { | |
57 emailSubject += " with failures" | |
58 failureHtml = util.GetFailureEmailHtml(*runID) | |
59 if viewActionMarkup, err = email.GetViewActionMarkup(util.GetMas terLogLink(*runID), "View Failure", "Direct link to the master log"); err != nil { | |
60 glog.Errorf("Failed to get view action markup: %s", err) | |
61 return | |
62 } | |
63 } | |
64 bodyTemplate := ` | |
65 The chromium perf %s benchmark task on %s pageset has completed.<br/> | |
dogben
2016/05/19 21:06:40
s/perf/analysis/
rmistry
2016/05/20 11:07:16
Done.
| |
66 Run description: %s<br/> | |
67 %s | |
68 The CSV output is <a href='%s'>here</a>.<br/> | |
69 The patch(es) you specified are here: | |
70 <a href='%s'>chromium</a>/<a href='%s'>telemetry</a> | |
71 <br/><br/> | |
72 You can schedule more runs <a href='%s'>here</a>. | |
73 <br/><br/> | |
74 Thanks! | |
75 ` | |
76 emailBody := fmt.Sprintf(bodyTemplate, *benchmarkName, *pagesetType, *de scription, failureHtml, outputLink, chromiumPatchLink, benchmarkPatchLink, front end.ChromiumAnalysisTasksWebapp) | |
77 if err := util.SendEmailWithMarkup(recipients, emailSubject, emailBody, viewActionMarkup); err != nil { | |
78 glog.Errorf("Error while sending email: %s", err) | |
79 return | |
80 } | |
81 } | |
82 | |
83 func updateWebappTask() { | |
84 // TODO(rmistry): Update this section when the analysis page is created. | |
85 //vars := chromium_perf.UpdateVars{} | |
86 //vars.Id = *gaeTaskID | |
87 //vars.SetCompleted(taskCompletedSuccessfully) | |
88 //vars.Results = sql.NullString{String: htmlOutputLink, Valid: true} | |
89 //vars.NoPatchRawOutput = sql.NullString{String: noPatchOutputLink, Vali d: true} | |
90 //vars.WithPatchRawOutput = sql.NullString{String: withPatchOutputLink, Valid: true} | |
91 //skutil.LogErr(frontend.UpdateWebappTaskV2(&vars)) | |
92 } | |
93 | |
94 func main() { | |
95 defer common.LogPanic() | |
96 master_common.Init() | |
97 | |
98 // Send start email. | |
99 emailsArr := util.ParseEmails(*emails) | |
100 emailsArr = append(emailsArr, util.CtAdmins...) | |
101 if len(emailsArr) == 0 { | |
102 glog.Error("At least one email address must be specified") | |
103 return | |
104 } | |
105 // TODO(rmistry): Update the below when the analysis page is created. | |
106 // skutil.LogErr(frontend.UpdateWebappTaskSetStarted(&chromium_perf.Upda teVars{}, *gaeTaskID)) | |
107 skutil.LogErr(util.SendTaskStartEmail(emailsArr, "Chromium analysis", *r unID, *description)) | |
108 // Ensure webapp is updated and email is sent even if task fails. | |
109 defer updateWebappTask() | |
110 defer sendEmail(emailsArr) | |
111 // Cleanup dirs after run completes. | |
112 defer skutil.RemoveAll(filepath.Join(util.StorageDir, util.ChromiumPerfR unsDir)) | |
dogben
2016/05/19 21:06:41
ChromiumPerfRunsDir is correct?
rmistry
2016/05/20 11:07:16
Changed. Done.
dogben
2016/05/20 12:45:34
Actually, is there anything that gets written here
rmistry
2016/05/20 13:00:31
Looks like the local dir is not used. Removed this
| |
113 defer skutil.RemoveAll(filepath.Join(util.StorageDir, util.BenchmarkRuns Dir)) | |
114 // Finish with glog flush and how long the task took. | |
115 defer util.TimeTrack(time.Now(), "Running chromium analysis task on work ers") | |
116 defer glog.Flush() | |
117 | |
118 if *pagesetType == "" { | |
119 glog.Error("Must specify --pageset_type") | |
120 return | |
121 } | |
122 if *benchmarkName == "" { | |
123 glog.Error("Must specify --benchmark_name") | |
124 return | |
125 } | |
126 if *runID == "" { | |
127 glog.Error("Must specify --run_id") | |
128 return | |
129 } | |
130 | |
131 // Instantiate GsUtil object. | |
132 gs, err := util.NewGsUtil(nil) | |
133 if err != nil { | |
134 glog.Errorf("Could not instantiate gsutil object: %s", err) | |
135 return | |
136 } | |
137 remoteOutputDir := filepath.Join(util.ChromiumPerfRunsDir, *runID) | |
138 | |
139 // Copy the patches to Google Storage. | |
140 chromiumPatchName := *runID + ".chromium.patch" | |
141 benchmarkPatchName := *runID + ".benchmark.patch" | |
142 for _, patchName := range []string{chromiumPatchName, benchmarkPatchName } { | |
143 if err := gs.UploadFile(patchName, os.TempDir(), remoteOutputDir ); err != nil { | |
144 glog.Errorf("Could not upload %s to %s: %s", patchName, remoteOutputDir, err) | |
145 return | |
146 } | |
147 } | |
148 chromiumPatchLink = util.GS_HTTP_LINK + filepath.Join(util.GSBucketName, remoteOutputDir, chromiumPatchName) | |
149 benchmarkPatchLink = util.GS_HTTP_LINK + filepath.Join(util.GSBucketName , remoteOutputDir, benchmarkPatchName) | |
150 | |
151 // Create the required chromium build. | |
152 chromiumHash, skiaHash, err := util.CreateChromiumBuild(*runID, "Linux", "", "", true, true) | |
153 if err != nil { | |
154 glog.Errorf("Could not create chromium build: %s", err) | |
155 return | |
156 } | |
157 chromiumBuild := fmt.Sprintf("try-%s-%s-%s-withpatch", chromiumHash, ski aHash, *runID) | |
158 | |
159 // Archive, trigger and collect swarming tasks. | |
160 isolateExtraArgs := map[string]string{ | |
161 "CHROMIUM_BUILD": chromiumBuild, | |
162 "RUN_ID": *runID, | |
163 "BENCHMARK": *benchmarkName, | |
164 "BENCHMARK_ARGS": *benchmarkExtraArgs, | |
165 "BROWSER_EXTRA_ARGS": *browserExtraArgs, | |
166 } | |
167 if err := util.TriggerSwarmingTask(*pagesetType, "chromium_analysis", ut il.CHROMIUM_ANALYSIS_ISOLATE, 2*time.Hour, 1*time.Hour, MAX_PAGES_PER_SWARMING_B OT, isolateExtraArgs); err != nil { | |
168 glog.Errorf("Error encountered when swarming tasks: %s", err) | |
169 return | |
170 } | |
171 | |
172 // If "--output-format=csv-pivot-table" was specified then merge all CSV files and upload. | |
173 noOutputSlaves := []string{} | |
174 pathToPyFiles := util.GetPathToPyFiles(false) | |
175 if strings.Contains(*benchmarkExtraArgs, "--output-format=csv-pivot-tabl e") { | |
176 if noOutputSlaves, err = util.MergeUploadCSVFiles(*runID, pathTo PyFiles, gs, util.PagesetTypeToInfo[*pagesetType].NumPages, MAX_PAGES_PER_SWARMI NG_BOT); err != nil { | |
177 glog.Errorf("Unable to merge and upload CSV files for %s : %s", *runID, err) | |
178 } | |
179 } | |
180 | |
181 // Construct the output link. | |
182 outputLink = util.GS_HTTP_LINK + filepath.Join(util.GSBucketName, util.B enchmarkRunsDir, *runID, "consolidated_outputs", *runID+".output") | |
183 | |
184 // Display the no output slaves. | |
185 for _, noOutputSlave := range noOutputSlaves { | |
186 fmt.Printf("Missing output from %s\n", noOutputSlave) | |
187 } | |
188 | |
189 taskCompletedSuccessfully = true | |
190 } | |
OLD | NEW |