Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Side by Side Diff: golden/go/skiacorrectness/main.go

Issue 650253003: Added HTTP endpoints for Correctness counts (Closed) Base URL: https://skia.googlesource.com/buildbot@master
Patch Set: Fixed typos Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 package main 1 package main
2 2
3 import ( 3 import (
4 "encoding/json"
4 "flag" 5 "flag"
6 "fmt"
5 "net/http" 7 "net/http"
6 ) 8 » "time"
7 9
8 import (
9 "github.com/golang/glog" 10 "github.com/golang/glog"
11 "github.com/gorilla/mux"
12
13 // "skia.googlesource.com/buildbot.git/golden/go/analysis"
jcgregorio 2014/10/17 18:07:52 leftover?
stephana 2014/10/17 20:01:45 Yes. Thank you. Removed.
14 "skia.googlesource.com/buildbot.git/go/database"
15 "skia.googlesource.com/buildbot.git/golden/go/analysis"
16 "skia.googlesource.com/buildbot.git/golden/go/db"
17 "skia.googlesource.com/buildbot.git/golden/go/expstorage"
18 "skia.googlesource.com/buildbot.git/golden/go/filediffstore"
19 "skia.googlesource.com/buildbot.git/perf/go/filetilestore"
10 ) 20 )
11 21
12 // flags 22 // flags
13 var ( 23 var (
14 » port = flag.String("port", ":9000", "HTTP service address (e.g., ': 9000')") 24 » port = flag.String("port", ":9000", "HTTP service address (e.g., ':9000')")
15 » staticDir = flag.String("static", "./app", "Directory with static conten t to serve") 25 » local = flag.Bool("local", false, "Running locally if true. As op posed to in production.")
26 » staticDir = flag.String("static_dir", "./app", "Directory with static content to serve")
27 » tileStoreDir = flag.String("tile_store_dir", "/tmp/tileStore", "What dir ectory to look for tiles in.")
28 » imageDiffDir = flag.String("image_diff_dir", "/tmp/imagediffdir", "What directory to store diff images in.")
29 » gsBucketName = flag.String("gs_bucket", "chromium-skia-gm", "Name of the google storage bucket that holds uploaded images.")
30 » mysqlConnStr = flag.String("mysql_conn", "", "MySQL connection string fo r backend database. If 'local' is false the password in this string will be subs tituted via the metadata server.")
31 » sqlitePath = flag.String("sqlite_path", "./golden.db", "Filepath of th e embedded SQLite database. Requires 'local' to be set to true and 'mysql_conn' to be empty to take effect.")
32 )
16 33
17 // TODO (stephana): Just ideas to be sorted out later 34 // Response envelope. All responses follow this format. Some fields might
18 // tempDir = flag.String("temp", "./.cache", 35 // be empty depending on context.
19 // "Directory to store temporary file and application cache") 36 type ResponseEnvelope struct {
20 ) 37 » Data *interface{} `json:"data"`
38 » Err *string `json:"err"`
39 » Status int `json:"status"`
40 }
41
42 type RestResources struct {
43 » analizer *analysis.Analyzer
44 }
45
46 func NewRestResources(a *analysis.Analyzer) *RestResources {
47 » return &RestResources{
48 » » analizer: a,
49 » }
50 }
51
52 // Get the aggregated counts
53 func (rr *RestResources) GetTileCountsHandler(w http.ResponseWriter, r *http.Req uest) {
jcgregorio 2014/10/17 18:07:52 sendResponse looks useful, but I'm not sure about
stephana 2014/10/17 20:01:45 I added RestResources as a container for the varia
jcgregorio 2014/10/17 20:12:16 As for global, that's not too much of a concern si
54 » result, err := rr.analizer.GetTileCounts()
55 » if err != nil {
56 » » sendErrorResponse(w, err.Error(), http.StatusInternalServerError )
57 » » return
58 » }
59
60 » sendResponse(w, result, http.StatusOK)
61 }
62
63 // Process a diff request send via HTTP.
64 func (rr *RestResources) GetTestCountsHandler(w http.ResponseWriter, r *http.Req uest) {
65 » testName := mux.Vars(r)["testname"]
66 » result, err := rr.analizer.GetTestCounts(testName)
67 » if err != nil {
68 » » sendErrorResponse(w, err.Error(), http.StatusInternalServerError )
69 » » return
70 » }
71
72 » sendResponse(w, result, http.StatusOK)
73 }
74
75 // Send an error response with the given error message.
76 func sendErrorResponse(w http.ResponseWriter, errorMsg string, status int) {
77 » resp := ResponseEnvelope{nil, &errorMsg, status}
78 » sendJson(w, &resp)
79 }
80
81 // Send a non-error response with the given data.
82 func sendResponse(w http.ResponseWriter, data interface{}, status int) {
83 » resp := ResponseEnvelope{&data, nil, status}
84 » sendJson(w, &resp)
85 }
86
87 // Parse JSON input and validate it.
88 // TODO (stephana): Validation is still missing. It's not sufficient
89 // to just parse the JSON. Could be done with Json schemas.
90 func parseJson(r *http.Request, v interface{}) error {
jcgregorio 2014/10/17 18:07:52 Doesn't appear to be used?
stephana 2014/10/17 20:01:45 Agreed that's a remainder from another version. Re
91 » // TODO: validate the JSON against a schema. Might not be necessary !
92 » decoder := json.NewDecoder(r.Body)
93 » return decoder.Decode(v)
94 }
95
96 // Sends the response envelope rendered as JSON.
97 func sendJson(w http.ResponseWriter, resp *ResponseEnvelope) {
98 » jsonBytes, err := json.Marshal(resp)
99 » if err != nil {
100 » » http.Error(w, err.Error(), http.StatusInternalServerError)
101 » » return
102 » }
103
104 » w.Header().Set("Content-Type", "application/json")
105 » w.Header().Set("Content-Length", fmt.Sprintf("%d", len(jsonBytes)))
jcgregorio 2014/10/17 18:07:52 Content-Length isn't necessary.
stephana 2014/10/17 20:01:45 Removed.
106 » w.Write(jsonBytes)
107 }
21 108
22 func main() { 109 func main() {
23 // parse the arguments 110 // parse the arguments
24 flag.Parse() 111 flag.Parse()
25 112
113 // Get the expecations storage, the filediff storage and the tilestore.
114 diffStore := filediffstore.NewFileDiffStore(nil, *imageDiffDir, *gsBucke tName)
115 vdb := database.NewVersionedDB(db.GetDatabaseConfig(*mysqlConnStr, *sqli tePath, *local))
116 expStore := expstorage.NewSQLExpectationStore(vdb)
117 tileStore := filetilestore.NewFileTileStore(*tileStoreDir, "golden", -1)
118
119 // Create the analyer and plug it into the rest resources.
120 analyzer := analysis.NewAnalyzer(expStore, tileStore, diffStore, 5*time. Minute)
121 resources := NewRestResources(analyzer)
122
123 router := mux.NewRouter()
124
125 // Wire up the resources. We use the 'rest' prefix to avoid any name
126 // clashes witht the static files being served.
127 router.HandleFunc("/rest/tilecounts", resources.GetTileCountsHandler)
jcgregorio 2014/10/17 18:07:52 Consider adding autogzip for JSON responses: htt
stephana 2014/10/17 20:01:45 I actually had that and removed it. I think we sho
128 router.HandleFunc("/rest/tilecounts/{testname}", resources.GetTestCounts Handler)
129
26 // // Static file handling 130 // // Static file handling
27 » http.Handle("/", http.FileServer(http.Dir(*staticDir))) 131 » router.Handle("/", http.FileServer(http.Dir(*staticDir)))
28 132
29 » // Wire up the resources 133 » // Send all requests to the router
134 » http.Handle("/", router)
30 135
31 // Start the server 136 // Start the server
32 glog.Infoln("Serving on http://127.0.0.1" + *port) 137 glog.Infoln("Serving on http://127.0.0.1" + *port)
33 glog.Fatal(http.ListenAndServe(*port, nil)) 138 glog.Fatal(http.ListenAndServe(*port, nil))
34 } 139 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698