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

Side by Side Diff: appengine/chromium_build_stats/default/ninja_log.go

Issue 561633002: chromium-build-stats: show ninja_log in table format (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: fix typo Created 6 years, 3 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 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package chromiumbuildstats 5 package chromiumbuildstats
6 6
7 // ninja_log.go provides /ninja_log endpoints. 7 // ninja_log.go provides /ninja_log endpoints.
8 8
9 import ( 9 import (
10 "bufio" 10 "bufio"
11 "compress/gzip" 11 "compress/gzip"
12 "encoding/json" 12 "encoding/json"
13 "fmt" 13 "fmt"
14 "html/template" 14 "html/template"
15 "net/http" 15 "net/http"
16 "path" 16 "path"
17 "sort"
17 "strings" 18 "strings"
18 19
19 "appengine" 20 "appengine"
20 21
21 "github.com/golang/oauth2/google" 22 "github.com/golang/oauth2/google"
22 23
23 "chromegomalog" 24 "chromegomalog"
24 "ninjalog" 25 "ninjalog"
25 ) 26 )
26 27
27 type outputFunc func(http.ResponseWriter, string, *ninjalog.NinjaLog) error 28 type outputFunc func(http.ResponseWriter, string, *ninjalog.NinjaLog) error
28 29
29 var ( 30 var (
30 outputs = map[string]outputFunc{ 31 outputs = map[string]outputFunc{
31 "lastbuild": outputFunc(lastBuild), 32 "lastbuild": outputFunc(lastBuild),
33 "table": outputFunc(table),
32 "metadata.json": outputFunc(metadataJSON), 34 "metadata.json": outputFunc(metadataJSON),
33 "trace.json": outputFunc(traceJSON), 35 "trace.json": outputFunc(traceJSON),
34 } 36 }
35 37
36 // chromegomalog.URL(path) won't be accessible by user. 38 // chromegomalog.URL(path) won't be accessible by user.
37 indexTmpl = template.Must(template.New("index").Parse(` 39 indexTmpl = template.Must(template.New("index").Parse(`
38 <html> 40 <html>
39 <head> 41 <head>
40 <title>{{.Path}}</title> 42 <title>{{.Path}}</title>
41 </head> 43 </head>
42 <body> 44 <body>
43 <h1>{{.Path}}</h1> 45 <h1>{{.Path}}</h1>
44 <ul> 46 <ul>
45 <li><a href="/file/{{.Path}}">original file</a> 47 <li><a href="/file/{{.Path}}">original file</a>
46 <li><a href="{{.Filename}}/lastbuild">.ninja_log</a> 48 <li><a href="{{.Filename}}/lastbuild">.ninja_log</a>
49 <li><a href="{{.Filename}}/table">.ninja_log in table format</a>
47 <li><a href="{{.Filename}}/metadata.json">metadata.json</a> 50 <li><a href="{{.Filename}}/metadata.json">metadata.json</a>
48 <li><a href="{{.Filename}}/trace.json">trace.json</a> 51 <li><a href="{{.Filename}}/trace.json">trace.json</a>
49 </ul> 52 </ul>
50 </body> 53 </body>
51 </html> 54 </html>
52 `)) 55 `))
56
57 tableTmpl = template.Must(template.New("table").Parse(`
58 <html>
59 <head>
60 <title>{{.Filename}}</title>
61 </head>
62 <body>
63 <h1>{{.Filename}}</h1>
64 Platform: {{.Metadata.Platform}}
65 Cmdline: {{.Metadata.Cmdline}}
66 Exit:{{.Metadata.Exit}}
67 <hr />
68 <table border=1>
69 <tr>
70 <th>n
71 <th>duration
72 <th>start
73 <th>end
74 <th>restat
75 <th>output
76 </tr>
77 {{range $i, $step := .Steps}}
78 <tr>
79 <td><a name="{{$i}}" href="#{{$i}}">{{$i}}</a>
80 <td>{{$step.Duration}}
81 <td>{{$step.Start}}
82 <td>{{$step.End}}
83 <td>{{if gt $step.Restat 0}}{{$step.Restat}}{{end}}
84 <td>{{$step.Out}}
85 </tr>
86 {{end}}
87 </table>
88 </html>
89 `))
53 ) 90 )
54 91
55 func init() { 92 func init() {
56 http.Handle("/ninja_log/", http.StripPrefix("/ninja_log/", http.HandlerF unc(ninjaLogHandler))) 93 http.Handle("/ninja_log/", http.StripPrefix("/ninja_log/", http.HandlerF unc(ninjaLogHandler)))
57 } 94 }
58 95
59 // ninjaLogHandler handles /<path>/<format> for ninja_log file in gs://chrome-go ma-log/<path> 96 // ninjaLogHandler handles /<path>/<format> for ninja_log file in gs://chrome-go ma-log/<path>
60 func ninjaLogHandler(w http.ResponseWriter, req *http.Request) { 97 func ninjaLogHandler(w http.ResponseWriter, req *http.Request) {
61 ctx := appengine.NewContext(req) 98 ctx := appengine.NewContext(req)
62 99
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 logPath := path.Dir(reqPath) 133 logPath := path.Dir(reqPath)
97 return logPath, f, nil 134 return logPath, f, nil
98 } 135 }
99 } 136 }
100 if !strings.HasPrefix(basename, "ninja_log.") { 137 if !strings.HasPrefix(basename, "ninja_log.") {
101 return "", nil, fmt.Errorf("unexpected path %s", reqPath) 138 return "", nil, fmt.Errorf("unexpected path %s", reqPath)
102 } 139 }
103 return strings.TrimSuffix(reqPath, "/"), outputFunc(indexPage), nil 140 return strings.TrimSuffix(reqPath, "/"), outputFunc(indexPage), nil
104 } 141 }
105 142
106 func ninjalogFetch(client *http.Client, path string) (*ninjalog.NinjaLog, http.H eader, error) { 143 func ninjalogFetch(client *http.Client, logPath string) (*ninjalog.NinjaLog, htt p.Header, error) {
107 » resp, err := chromegomalog.Fetch(client, path) 144 » resp, err := chromegomalog.Fetch(client, logPath)
108 if err != nil { 145 if err != nil {
109 return nil, nil, err 146 return nil, nil, err
110 } 147 }
111 defer resp.Body.Close() 148 defer resp.Body.Close()
112 const bufsize = 512 * 1024 149 const bufsize = 512 * 1024
113 rd, err := gzip.NewReader(bufio.NewReaderSize(resp.Body, bufsize)) 150 rd, err := gzip.NewReader(bufio.NewReaderSize(resp.Body, bufsize))
114 if err != nil { 151 if err != nil {
115 return nil, nil, err 152 return nil, nil, err
116 } 153 }
117 » nl, err := ninjalog.Parse(rd) 154 » nl, err := ninjalog.Parse(logPath, rd)
118 return nl, resp.Header, nil 155 return nl, resp.Header, nil
119 } 156 }
120 157
121 func indexPage(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) er ror { 158 func indexPage(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) er ror {
122 w.Header().Set("Content-Type", "text/html") 159 w.Header().Set("Content-Type", "text/html")
123 w.WriteHeader(http.StatusOK) 160 w.WriteHeader(http.StatusOK)
124 data := struct { 161 data := struct {
125 Path string 162 Path string
126 Filename string 163 Filename string
127 }{ 164 }{
128 Path: logPath, 165 Path: logPath,
129 » » Filename: path.Base(logPath), 166 » » Filename: path.Base(njl.Filename),
130 } 167 }
131 return indexTmpl.Execute(w, data) 168 return indexTmpl.Execute(w, data)
132 } 169 }
133 170
134 func lastBuild(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) er ror { 171 func lastBuild(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) er ror {
135 w.Header().Set("Content-Type", "text/plain") 172 w.Header().Set("Content-Type", "text/plain")
136 w.WriteHeader(http.StatusOK) 173 w.WriteHeader(http.StatusOK)
137 return ninjalog.Dump(w, njl.Steps) 174 return ninjalog.Dump(w, njl.Steps)
138 } 175 }
139 176
177 func table(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) error {
178 w.Header().Set("Content-Type", "text/html")
179 w.WriteHeader(http.StatusOK)
180 sort.Sort(sort.Reverse(ninjalog.ByDuration{Steps: njl.Steps}))
181 return tableTmpl.Execute(w, njl)
182 }
183
140 func metadataJSON(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) error { 184 func metadataJSON(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) error {
141 js, err := json.Marshal(njl.Metadata) 185 js, err := json.Marshal(njl.Metadata)
142 if err != nil { 186 if err != nil {
143 return err 187 return err
144 } 188 }
145 w.Header().Set("Content-Type", "application/json") 189 w.Header().Set("Content-Type", "application/json")
146 w.WriteHeader(http.StatusOK) 190 w.WriteHeader(http.StatusOK)
147 _, err = w.Write(js) 191 _, err = w.Write(js)
148 return err 192 return err
149 } 193 }
150 194
151 func traceJSON(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) er ror { 195 func traceJSON(w http.ResponseWriter, logPath string, njl *ninjalog.NinjaLog) er ror {
152 steps := ninjalog.Dedup(njl.Steps) 196 steps := ninjalog.Dedup(njl.Steps)
153 flow := ninjalog.Flow(steps) 197 flow := ninjalog.Flow(steps)
154 traces := ninjalog.ToTraces(flow, 1) 198 traces := ninjalog.ToTraces(flow, 1)
155 js, err := json.Marshal(traces) 199 js, err := json.Marshal(traces)
156 if err != nil { 200 if err != nil {
157 return err 201 return err
158 } 202 }
159 w.Header().Set("Content-Type", "application/json") 203 w.Header().Set("Content-Type", "application/json")
160 w.WriteHeader(http.StatusOK) 204 w.WriteHeader(http.StatusOK)
161 _, err = w.Write(js) 205 _, err = w.Write(js)
162 return err 206 return err
163 } 207 }
OLDNEW
« no previous file with comments | « appengine/chromium_build_stats/default/app.go ('k') | appengine/chromium_build_stats/gopath/src/ninjalog/ninjalog.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698