golang.org/x/build@v0.0.0-20240506185731-218518f32b70/perf/app/app.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package app implements the performance data analysis server. 6 package app 7 8 import ( 9 "embed" 10 "net/http" 11 12 "github.com/google/safehtml/template" 13 "golang.org/x/build/perfdata" 14 ) 15 16 var ( 17 //go:embed template/* 18 tmplEmbedFS embed.FS 19 tmplFS = template.TrustedFSFromEmbed(tmplEmbedFS) 20 ) 21 22 // App manages the analysis server logic. 23 // Construct an App instance and call RegisterOnMux to connect it with an HTTP server. 24 type App struct { 25 // StorageClient is used to talk to the perfdata server. 26 StorageClient *perfdata.Client 27 28 // BaseDir is the directory containing the "template" directory. 29 // If empty, the current directory will be used. 30 BaseDir string 31 32 // InfluxHost is the host URL of the perf InfluxDB server. 33 InfluxHost string 34 35 // InfluxToken is the Influx auth token for connecting to InfluxHost. 36 // 37 // If empty, we attempt to fetch the token from Secret Manager using 38 // InfluxProject. 39 InfluxToken string 40 41 // InfluxProject is the GCP project ID containing the InfluxDB secrets. 42 // 43 // If empty, this defaults to the project this service is running as. 44 // 45 // Only used if InfluxToken is empty. 46 InfluxProject string 47 48 // AuthCronEmail is the service account email which requests to 49 // /cron/syncinflux must contain an OICD authentication token for, with 50 // audience "/cron/syncinflux". 51 // 52 // If empty, no authentication is required. 53 AuthCronEmail string 54 } 55 56 // RegisterOnMux registers the app's URLs on mux. 57 func (a *App) RegisterOnMux(mux *http.ServeMux) { 58 mux.HandleFunc("/", a.index) 59 mux.HandleFunc("/search", a.search) 60 mux.HandleFunc("/compare", a.compare) 61 mux.HandleFunc("/cron/syncinflux", a.syncInflux) 62 a.dashboardRegisterOnMux(mux) 63 } 64 65 // search handles /search. 66 // This currently just runs the compare handler, until more analysis methods are implemented. 67 func (a *App) search(w http.ResponseWriter, r *http.Request) { 68 if err := r.ParseForm(); err != nil { 69 http.Error(w, err.Error(), 500) 70 return 71 } 72 if r.Header.Get("Accept") == "text/plain" || r.Header.Get("X-Benchsave") == "1" { 73 // TODO(quentin): Switch to real Accept negotiation when golang/go#19307 is resolved. 74 // Benchsave sends both of these headers. 75 a.textCompare(w, r) 76 return 77 } 78 // TODO(quentin): Intelligently choose an analysis method 79 // based on the results from the query, once there is more 80 // than one analysis method. 81 //q := r.Form.Get("q") 82 a.compare(w, r) 83 }