| OLD | NEW |
| 1 package main | 1 package main |
| 2 | 2 |
| 3 import ( | 3 import ( |
| 4 "encoding/json" | 4 "encoding/json" |
| 5 "flag" | 5 "flag" |
| 6 "fmt" | 6 "fmt" |
| 7 ehtml "html" | 7 ehtml "html" |
| 8 "html/template" | 8 "html/template" |
| 9 "math/rand" | 9 "math/rand" |
| 10 "net/http" | 10 "net/http" |
| 11 "net/url" | 11 "net/url" |
| 12 "path/filepath" | 12 "path/filepath" |
| 13 "regexp" | 13 "regexp" |
| 14 "runtime" | 14 "runtime" |
| 15 "strconv" | 15 "strconv" |
| 16 "strings" | 16 "strings" |
| 17 "time" | 17 "time" |
| 18 | 18 |
| 19 "github.com/gorilla/mux" | 19 "github.com/gorilla/mux" |
| 20 "github.com/skia-dev/glog" | 20 "github.com/skia-dev/glog" |
| 21 "go.skia.org/infra/go/common" | 21 "go.skia.org/infra/go/common" |
| 22 "go.skia.org/infra/go/filetilestore" | |
| 23 "go.skia.org/infra/go/gitinfo" | 22 "go.skia.org/infra/go/gitinfo" |
| 24 "go.skia.org/infra/go/human" | 23 "go.skia.org/infra/go/human" |
| 25 "go.skia.org/infra/go/ingester" | 24 "go.skia.org/infra/go/ingester" |
| 26 "go.skia.org/infra/go/login" | 25 "go.skia.org/infra/go/login" |
| 27 "go.skia.org/infra/go/tiling" | 26 "go.skia.org/infra/go/tiling" |
| 27 "go.skia.org/infra/go/trace/db" |
| 28 "go.skia.org/infra/go/util" | 28 "go.skia.org/infra/go/util" |
| 29 "go.skia.org/infra/perf/go/activitylog" | 29 "go.skia.org/infra/perf/go/activitylog" |
| 30 "go.skia.org/infra/perf/go/alerting" | 30 "go.skia.org/infra/perf/go/alerting" |
| 31 "go.skia.org/infra/perf/go/annotate" | 31 "go.skia.org/infra/perf/go/annotate" |
| 32 "go.skia.org/infra/perf/go/clustering" | 32 "go.skia.org/infra/perf/go/clustering" |
| 33 "go.skia.org/infra/perf/go/config" | 33 "go.skia.org/infra/perf/go/config" |
| 34 » "go.skia.org/infra/perf/go/db" | 34 » idb "go.skia.org/infra/perf/go/db" |
| 35 "go.skia.org/infra/perf/go/parser" | 35 "go.skia.org/infra/perf/go/parser" |
| 36 "go.skia.org/infra/perf/go/shortcut" | 36 "go.skia.org/infra/perf/go/shortcut" |
| 37 "go.skia.org/infra/perf/go/stats" | 37 "go.skia.org/infra/perf/go/stats" |
| 38 "go.skia.org/infra/perf/go/trybot" | 38 "go.skia.org/infra/perf/go/trybot" |
| 39 "go.skia.org/infra/perf/go/types" | 39 "go.skia.org/infra/perf/go/types" |
| 40 "go.skia.org/infra/perf/go/vec" | 40 "go.skia.org/infra/perf/go/vec" |
| 41 ) | 41 ) |
| 42 | 42 |
| 43 var ( | 43 var ( |
| 44 // indexTemplate is the main index.html page we serve. | 44 // indexTemplate is the main index.html page we serve. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 git *gitinfo.GitInfo = nil | 78 git *gitinfo.GitInfo = nil |
| 79 | 79 |
| 80 commitLinkifyRe = regexp.MustCompile("(?m)^commit (.*)$") | 80 commitLinkifyRe = regexp.MustCompile("(?m)^commit (.*)$") |
| 81 ) | 81 ) |
| 82 | 82 |
| 83 // flags | 83 // flags |
| 84 var ( | 84 var ( |
| 85 port = flag.String("port", ":8000", "HTTP service address (e.g
., ':8000')") | 85 port = flag.String("port", ":8000", "HTTP service address (e.g
., ':8000')") |
| 86 local = flag.Bool("local", false, "Running locally if true. As
opposed to in production.") | 86 local = flag.Bool("local", false, "Running locally if true. As
opposed to in production.") |
| 87 gitRepoDir = flag.String("git_repo_dir", "../../../skia", "Directory
location for the Skia repo.") | 87 gitRepoDir = flag.String("git_repo_dir", "../../../skia", "Directory
location for the Skia repo.") |
| 88 tileStoreDir = flag.String("tile_store_dir", "/tmp/tileStore", "What d
irectory to look for tiles in.") | |
| 89 graphiteServer = flag.String("graphite_server", "skia-monitoring:2003",
"Where is Graphite metrics ingestion server running.") | 88 graphiteServer = flag.String("graphite_server", "skia-monitoring:2003",
"Where is Graphite metrics ingestion server running.") |
| 90 apikey = flag.String("apikey", "", "The API Key used to make iss
ue tracker requests. Only for local testing.") | 89 apikey = flag.String("apikey", "", "The API Key used to make iss
ue tracker requests. Only for local testing.") |
| 91 gitRepoURL = flag.String("git_repo_url", "https://skia.googlesource.
com/skia", "The URL to pass to git clone for the source repository.") | 90 gitRepoURL = flag.String("git_repo_url", "https://skia.googlesource.
com/skia", "The URL to pass to git clone for the source repository.") |
| 92 resourcesDir = flag.String("resources_dir", "", "The directory to find
templates, JS, and CSS files. If blank the current directory will be used.") | 91 resourcesDir = flag.String("resources_dir", "", "The directory to find
templates, JS, and CSS files. If blank the current directory will be used.") |
| 92 traceservice = flag.String("trace_service", "localhost:9090", "The add
ress of the traceservice endpoint.") |
| 93 ) | 93 ) |
| 94 | 94 |
| 95 var ( | 95 var ( |
| 96 » nanoTileStore tiling.TileStore | 96 » nanoTileStore *db.Builder |
| 97 | 97 |
| 98 templates *template.Template | 98 templates *template.Template |
| 99 ) | 99 ) |
| 100 | 100 |
| 101 func loadTemplates() { | 101 func loadTemplates() { |
| 102 templates = template.Must(template.New("").ParseFiles( | 102 templates = template.Must(template.New("").ParseFiles( |
| 103 filepath.Join(*resourcesDir, "templates/index.html"), | 103 filepath.Join(*resourcesDir, "templates/index.html"), |
| 104 filepath.Join(*resourcesDir, "templates/clusters.html"), | 104 filepath.Join(*resourcesDir, "templates/clusters.html"), |
| 105 filepath.Join(*resourcesDir, "templates/alerting.html"), | 105 filepath.Join(*resourcesDir, "templates/alerting.html"), |
| 106 filepath.Join(*resourcesDir, "templates/cl.html"), | 106 filepath.Join(*resourcesDir, "templates/cl.html"), |
| (...skipping 21 matching lines...) Expand all Loading... |
| 128 | 128 |
| 129 func Init() { | 129 func Init() { |
| 130 rand.Seed(time.Now().UnixNano()) | 130 rand.Seed(time.Now().UnixNano()) |
| 131 if *resourcesDir == "" { | 131 if *resourcesDir == "" { |
| 132 _, filename, _, _ := runtime.Caller(0) | 132 _, filename, _, _ := runtime.Caller(0) |
| 133 *resourcesDir = filepath.Join(filepath.Dir(filename), "../..") | 133 *resourcesDir = filepath.Join(filepath.Dir(filename), "../..") |
| 134 } | 134 } |
| 135 | 135 |
| 136 loadTemplates() | 136 loadTemplates() |
| 137 | 137 |
| 138 nanoTileStore = filetilestore.NewFileTileStore(*tileStoreDir, config.DAT
ASET_NANO, 2*time.Minute) | |
| 139 | |
| 140 var err error | 138 var err error |
| 141 git, err = gitinfo.CloneOrUpdate(*gitRepoURL, *gitRepoDir, false) | 139 git, err = gitinfo.CloneOrUpdate(*gitRepoURL, *gitRepoDir, false) |
| 142 if err != nil { | 140 if err != nil { |
| 143 glog.Fatal(err) | 141 glog.Fatal(err) |
| 144 } | 142 } |
| 143 nanoTileStore, err = db.NewBuilder(git, *traceservice, config.INITIAL_TI
LE_SIZE, types.PerfTraceBuilder) |
| 144 if err != nil { |
| 145 glog.Fatalf("Failed to build trace/db.DB: %s", err) |
| 146 } |
| 145 } | 147 } |
| 146 | 148 |
| 147 // showcutHandler handles the POST requests of the shortcut page. | 149 // showcutHandler handles the POST requests of the shortcut page. |
| 148 // | 150 // |
| 149 // Shortcuts are of the form: | 151 // Shortcuts are of the form: |
| 150 // | 152 // |
| 151 // { | 153 // { |
| 152 // "scale": 0, | 154 // "scale": 0, |
| 153 // "tiles": [-1], | 155 // "tiles": [-1], |
| 154 // "hash": "a1092123890...", | 156 // "hash": "a1092123890...", |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 glog.Errorf("Failed to write or encode output: %s", err) | 206 glog.Errorf("Failed to write or encode output: %s", err) |
| 205 } | 207 } |
| 206 } | 208 } |
| 207 | 209 |
| 208 // alertingHandler returns the currently untriaged clusters. | 210 // alertingHandler returns the currently untriaged clusters. |
| 209 // | 211 // |
| 210 // The return format is the same as clusteringHandler. | 212 // The return format is the same as clusteringHandler. |
| 211 func alertingHandler(w http.ResponseWriter, r *http.Request) { | 213 func alertingHandler(w http.ResponseWriter, r *http.Request) { |
| 212 glog.Infof("Alerting Handler: %q\n", r.URL.Path) | 214 glog.Infof("Alerting Handler: %q\n", r.URL.Path) |
| 213 w.Header().Set("Content-Type", "application/json") | 215 w.Header().Set("Content-Type", "application/json") |
| 214 » tile, err := nanoTileStore.Get(0, -1) | 216 » tile := nanoTileStore.GetTile() |
| 215 » if err != nil { | |
| 216 » » util.ReportError(w, r, err, fmt.Sprintf("Failed to load tile.")) | |
| 217 » » return | |
| 218 » } | |
| 219 | |
| 220 alerts, err := alerting.ListFrom(tile.Commits[0].CommitTime) | 217 alerts, err := alerting.ListFrom(tile.Commits[0].CommitTime) |
| 221 if err != nil { | 218 if err != nil { |
| 222 util.ReportError(w, r, err, "Error retrieving cluster summaries.
") | 219 util.ReportError(w, r, err, "Error retrieving cluster summaries.
") |
| 223 return | 220 return |
| 224 } | 221 } |
| 225 enc := json.NewEncoder(w) | 222 enc := json.NewEncoder(w) |
| 226 if err = enc.Encode(map[string][]*types.ClusterSummary{"Clusters": alert
s}); err != nil { | 223 if err = enc.Encode(map[string][]*types.ClusterSummary{"Clusters": alert
s}); err != nil { |
| 227 glog.Errorf("Failed to write or encode output: %s", err) | 224 glog.Errorf("Failed to write or encode output: %s", err) |
| 228 } | 225 } |
| 229 } | 226 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // | 342 // |
| 346 // Takes the following query parameters: | 343 // Takes the following query parameters: |
| 347 // | 344 // |
| 348 // commit1 - The hash for the first commit. | 345 // commit1 - The hash for the first commit. |
| 349 // commit2 - The hash for the second commit. | 346 // commit2 - The hash for the second commit. |
| 350 // query - A paramset in URI query format used to filter the results at each
commit. | 347 // query - A paramset in URI query format used to filter the results at each
commit. |
| 351 // | 348 // |
| 352 func kernelJSONHandler(w http.ResponseWriter, r *http.Request) { | 349 func kernelJSONHandler(w http.ResponseWriter, r *http.Request) { |
| 353 // TODO(jcgregorio) Determine the tile(s) to load based on the commit ha
shes, | 350 // TODO(jcgregorio) Determine the tile(s) to load based on the commit ha
shes, |
| 354 // possibly loading two different tiles, one for each hash. | 351 // possibly loading two different tiles, one for each hash. |
| 355 » tile, err := nanoTileStore.Get(0, -1) | 352 » tile := nanoTileStore.GetTile() |
| 356 » if err != nil { | |
| 357 » » util.ReportError(w, r, err, fmt.Sprintf("Failed to load tile.")) | |
| 358 » » return | |
| 359 » } | |
| 360 commit1 := r.FormValue("commit1") | 353 commit1 := r.FormValue("commit1") |
| 361 commit2 := r.FormValue("commit2") | 354 commit2 := r.FormValue("commit2") |
| 362 | 355 |
| 363 // Calulate the indices where the commit falls in the tile. | 356 // Calulate the indices where the commit falls in the tile. |
| 364 commit1Index := -1 | 357 commit1Index := -1 |
| 365 commit2Index := -1 | 358 commit2Index := -1 |
| 366 | 359 |
| 367 // Confirm that the two commits appear in the tile. | 360 // Confirm that the two commits appear in the tile. |
| 368 for i, c := range tile.Commits { | 361 for i, c := range tile.Commits { |
| 369 if c.Hash == commit1 { | 362 if c.Hash == commit1 { |
| 370 commit1Index = i | 363 commit1Index = i |
| 371 } | 364 } |
| 372 if c.Hash == commit2 { | 365 if c.Hash == commit2 { |
| 373 commit2Index = i | 366 commit2Index = i |
| 374 } | 367 } |
| 375 } | 368 } |
| 376 if commit1Index == -1 || commit2Index == -1 { | 369 if commit1Index == -1 || commit2Index == -1 { |
| 377 glog.Warningf("Commits %s[%d] %s[%d]", commit1, commit1Index, co
mmit2, commit2Index) | 370 glog.Warningf("Commits %s[%d] %s[%d]", commit1, commit1Index, co
mmit2, commit2Index) |
| 378 » » util.ReportError(w, r, err, fmt.Sprintf("Failed to find commits
in tile.")) | 371 » » util.ReportError(w, r, fmt.Errorf("Failed to find commits in til
e."), fmt.Sprintf("Failed to find commits in tile.")) |
| 379 return | 372 return |
| 380 } | 373 } |
| 381 w.Header().Set("Content-Type", "application/json") | 374 w.Header().Set("Content-Type", "application/json") |
| 382 query := r.FormValue("query") | 375 query := r.FormValue("query") |
| 383 q, err := url.ParseQuery(query) | 376 q, err := url.ParseQuery(query) |
| 384 if err != nil { | 377 if err != nil { |
| 385 util.ReportError(w, r, err, fmt.Sprintf("Failed to parse query p
arameters.")) | 378 util.ReportError(w, r, err, fmt.Sprintf("Failed to parse query p
arameters.")) |
| 386 return | 379 return |
| 387 } | 380 } |
| 388 ret := struct { | 381 ret := struct { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // | 436 // |
| 444 // _k - The K to use for k-means clustering. | 437 // _k - The K to use for k-means clustering. |
| 445 // _stddev - The standard deviation to use when normalize traces | 438 // _stddev - The standard deviation to use when normalize traces |
| 446 // during k-means clustering. | 439 // during k-means clustering. |
| 447 // _issue - The Rietveld issue ID with trybot results to include. | 440 // _issue - The Rietveld issue ID with trybot results to include. |
| 448 // | 441 // |
| 449 // Additionally the rest of the query parameters as returned from | 442 // Additionally the rest of the query parameters as returned from |
| 450 // sk.Query.selectionsAsQuery(). | 443 // sk.Query.selectionsAsQuery(). |
| 451 func clusteringHandler(w http.ResponseWriter, r *http.Request) { | 444 func clusteringHandler(w http.ResponseWriter, r *http.Request) { |
| 452 glog.Infof("Clustering Handler: %q\n", r.URL.Path) | 445 glog.Infof("Clustering Handler: %q\n", r.URL.Path) |
| 453 » tile, err := nanoTileStore.Get(0, -1) | 446 » tile := nanoTileStore.GetTile() |
| 454 » if err != nil { | |
| 455 » » util.ReportError(w, r, err, fmt.Sprintf("Failed to load tile.")) | |
| 456 » » return | |
| 457 » } | |
| 458 w.Header().Set("Content-Type", "application/json") | 447 w.Header().Set("Content-Type", "application/json") |
| 459 // If there are no query parameters just return with an empty set of Clu
sterSummaries. | 448 // If there are no query parameters just return with an empty set of Clu
sterSummaries. |
| 460 if r.FormValue("_k") == "" || r.FormValue("_stddev") == "" { | 449 if r.FormValue("_k") == "" || r.FormValue("_stddev") == "" { |
| 461 writeClusterSummaries(clustering.NewClusterSummaries(), w, r) | 450 writeClusterSummaries(clustering.NewClusterSummaries(), w, r) |
| 462 return | 451 return |
| 463 } | 452 } |
| 464 | 453 |
| 465 k, err := strconv.ParseInt(r.FormValue("_k"), 10, 32) | 454 k, err := strconv.ParseInt(r.FormValue("_k"), 10, 32) |
| 466 if err != nil { | 455 if err != nil { |
| 467 util.ReportError(w, r, err, fmt.Sprintf("_k parameter must be an
integer %s.", r.FormValue("_k"))) | 456 util.ReportError(w, r, err, fmt.Sprintf("_k parameter must be an
integer %s.", r.FormValue("_k"))) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 } | 495 } |
| 507 } | 496 } |
| 508 summary, err := clustering.CalculateClusterSummaries(tile, int(k), stdde
v, filter) | 497 summary, err := clustering.CalculateClusterSummaries(tile, int(k), stdde
v, filter) |
| 509 if err != nil { | 498 if err != nil { |
| 510 util.ReportError(w, r, err, "Failed to calculate clusters.") | 499 util.ReportError(w, r, err, "Failed to calculate clusters.") |
| 511 return | 500 return |
| 512 } | 501 } |
| 513 writeClusterSummaries(summary, w, r) | 502 writeClusterSummaries(summary, w, r) |
| 514 } | 503 } |
| 515 | 504 |
| 516 // getTile retrieves a tile from the disk | |
| 517 func getTile(tileScale, tileNumber int) (*tiling.Tile, error) { | |
| 518 start := time.Now() | |
| 519 tile, err := nanoTileStore.Get(int(tileScale), int(tileNumber)) | |
| 520 glog.Infoln("Time for tile load: ", time.Since(start).Nanoseconds()) | |
| 521 if err != nil || tile == nil { | |
| 522 return nil, fmt.Errorf("Unable to get tile from tilestore: %s",
err) | |
| 523 } | |
| 524 return tile, nil | |
| 525 } | |
| 526 | |
| 527 // tileHandler accepts URIs like /tiles/0/1 | 505 // tileHandler accepts URIs like /tiles/0/1 |
| 528 // where the URI format is /tiles/<tile-scale>/<tile-number> | 506 // where the URI format is /tiles/<tile-scale>/<tile-number> |
| 529 // | 507 // |
| 530 // It returns JSON of the form: | 508 // It returns JSON of the form: |
| 531 // | 509 // |
| 532 // { | 510 // { |
| 533 // tiles: [20], | 511 // tiles: [20], |
| 534 // scale: 0, | 512 // scale: 0, |
| 535 // paramset: { | 513 // paramset: { |
| 536 // "os": ["Android", "ChromeOS", ..], | 514 // "os": ["Android", "ChromeOS", ..], |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 if err != nil { | 546 if err != nil { |
| 569 util.ReportError(w, r, err, "Failed parsing tile scale.") | 547 util.ReportError(w, r, err, "Failed parsing tile scale.") |
| 570 return | 548 return |
| 571 } | 549 } |
| 572 tileNumber, err := strconv.ParseInt(match[2], 10, 0) | 550 tileNumber, err := strconv.ParseInt(match[2], 10, 0) |
| 573 if err != nil { | 551 if err != nil { |
| 574 util.ReportError(w, r, err, "Failed parsing tile number.") | 552 util.ReportError(w, r, err, "Failed parsing tile number.") |
| 575 return | 553 return |
| 576 } | 554 } |
| 577 glog.Infof("tile: %d %d", tileScale, tileNumber) | 555 glog.Infof("tile: %d %d", tileScale, tileNumber) |
| 578 » tile, err := getTile(int(tileScale), int(tileNumber)) | 556 » tile := nanoTileStore.GetTile() |
| 579 » if err != nil { | |
| 580 » » util.ReportError(w, r, err, "Failed retrieving tile.") | |
| 581 » » return | |
| 582 » } | |
| 583 | |
| 584 guiTile := tiling.NewTileGUI(tile.Scale, tile.TileIndex) | 557 guiTile := tiling.NewTileGUI(tile.Scale, tile.TileIndex) |
| 585 guiTile.Commits = tile.Commits | 558 guiTile.Commits = tile.Commits |
| 586 guiTile.ParamSet = tile.ParamSet | 559 guiTile.ParamSet = tile.ParamSet |
| 587 // SkpCommits goes out to the git repo, add caching if this turns out to
be | 560 // SkpCommits goes out to the git repo, add caching if this turns out to
be |
| 588 // slow. | 561 // slow. |
| 589 if skps, err := git.SkpCommits(tile); err != nil { | 562 if skps, err := git.SkpCommits(tile); err != nil { |
| 590 guiTile.Skps = []int{} | 563 guiTile.Skps = []int{} |
| 591 glog.Errorf("Failed to calculate skps: %s", err) | 564 glog.Errorf("Failed to calculate skps: %s", err) |
| 592 } else { | 565 } else { |
| 593 guiTile.Skps = skps | 566 guiTile.Skps = skps |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 if err != nil { | 680 if err != nil { |
| 708 util.ReportError(w, r, err, "Failed parsing tile scale.") | 681 util.ReportError(w, r, err, "Failed parsing tile scale.") |
| 709 return | 682 return |
| 710 } | 683 } |
| 711 tileNumber, err := strconv.ParseInt(match[2], 10, 0) | 684 tileNumber, err := strconv.ParseInt(match[2], 10, 0) |
| 712 if err != nil { | 685 if err != nil { |
| 713 util.ReportError(w, r, err, "Failed parsing tile number.") | 686 util.ReportError(w, r, err, "Failed parsing tile number.") |
| 714 return | 687 return |
| 715 } | 688 } |
| 716 glog.Infof("tile: %d %d", tileScale, tileNumber) | 689 glog.Infof("tile: %d %d", tileScale, tileNumber) |
| 717 » tile, err := getTile(int(tileScale), int(tileNumber)) | 690 » tile := nanoTileStore.GetTile() |
| 718 » if err != nil { | |
| 719 » » util.ReportError(w, r, err, "Failed retrieving tile.") | |
| 720 » » return | |
| 721 » } | |
| 722 w.Header().Set("Content-Type", "application/json") | 691 w.Header().Set("Content-Type", "application/json") |
| 723 ret := &QueryResponse{ | 692 ret := &QueryResponse{ |
| 724 Traces: []*tiling.TraceGUI{}, | 693 Traces: []*tiling.TraceGUI{}, |
| 725 Hash: "", | 694 Hash: "", |
| 726 } | 695 } |
| 727 if match[3] == "" { | 696 if match[3] == "" { |
| 728 // We only want the count. | 697 // We only want the count. |
| 729 total := 0 | 698 total := 0 |
| 730 for _, tr := range tile.Traces { | 699 for _, tr := range tile.Traces { |
| 731 if tiling.Matches(tr, r.Form) { | 700 if tiling.Matches(tr, r.Form) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 } | 799 } |
| 831 hash := match[1] | 800 hash := match[1] |
| 832 | 801 |
| 833 tileNum, idx, err := git.TileAddressFromHash(hash, time.Time(ingester.BE
GINNING_OF_TIME)) | 802 tileNum, idx, err := git.TileAddressFromHash(hash, time.Time(ingester.BE
GINNING_OF_TIME)) |
| 834 if err != nil { | 803 if err != nil { |
| 835 glog.Infof("Did not find hash '%s', use latest: %q.\n", hash, er
r) | 804 glog.Infof("Did not find hash '%s', use latest: %q.\n", hash, er
r) |
| 836 tileNum = -1 | 805 tileNum = -1 |
| 837 idx = -1 | 806 idx = -1 |
| 838 } | 807 } |
| 839 glog.Infof("Hash: %s tileNum: %d, idx: %d\n", hash, tileNum, idx) | 808 glog.Infof("Hash: %s tileNum: %d, idx: %d\n", hash, tileNum, idx) |
| 840 » tile, err := getTile(0, tileNum) | 809 » tile := nanoTileStore.GetTile() |
| 841 » if err != nil { | |
| 842 » » util.ReportError(w, r, err, "Failed retrieving tile.") | |
| 843 » » return | |
| 844 » } | |
| 845 | 810 |
| 846 if idx < 0 { | 811 if idx < 0 { |
| 847 idx = len(tile.Commits) - 1 // Defaults to the last slice elemen
t. | 812 idx = len(tile.Commits) - 1 // Defaults to the last slice elemen
t. |
| 848 } | 813 } |
| 849 glog.Infof("Tile: %d; Idx: %d\n", tileNum, idx) | 814 glog.Infof("Tile: %d; Idx: %d\n", tileNum, idx) |
| 850 | 815 |
| 851 ret := SingleResponse{ | 816 ret := SingleResponse{ |
| 852 Traces: []*SingleTrace{}, | 817 Traces: []*SingleTrace{}, |
| 853 Hash: tile.Commits[idx].Hash, | 818 Hash: tile.Commits[idx].Hash, |
| 854 } | 819 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 // calcHandler handles requests for the form: | 902 // calcHandler handles requests for the form: |
| 938 // | 903 // |
| 939 // /calc/?formula=filter("config=8888") | 904 // /calc/?formula=filter("config=8888") |
| 940 // | 905 // |
| 941 // Where the formula is any formula that parser.Eval() accepts. | 906 // Where the formula is any formula that parser.Eval() accepts. |
| 942 // | 907 // |
| 943 // The response is the same format as queryHandler. | 908 // The response is the same format as queryHandler. |
| 944 func calcHandler(w http.ResponseWriter, r *http.Request) { | 909 func calcHandler(w http.ResponseWriter, r *http.Request) { |
| 945 glog.Infof("Calc Handler: %q\n", r.URL.Path) | 910 glog.Infof("Calc Handler: %q\n", r.URL.Path) |
| 946 w.Header().Set("Content-Type", "application/json") | 911 w.Header().Set("Content-Type", "application/json") |
| 947 » tile, err := nanoTileStore.Get(0, -1) | 912 » tile := nanoTileStore.GetTile() |
| 948 » if err != nil { | |
| 949 » » util.ReportError(w, r, err, fmt.Sprintf("Failed to load tile.")) | |
| 950 » » return | |
| 951 » } | |
| 952 formula := r.FormValue("formula") | 913 formula := r.FormValue("formula") |
| 953 | 914 |
| 954 var data interface{} = nil | 915 var data interface{} = nil |
| 955 if r.FormValue("flat") == "true" { | 916 if r.FormValue("flat") == "true" { |
| 956 resp := &FlatQueryResponse{ | 917 resp := &FlatQueryResponse{ |
| 957 Traces: []*types.PerfTrace{}, | 918 Traces: []*types.PerfTrace{}, |
| 958 } | 919 } |
| 959 if err := addFlatCalculatedTraces(resp, tile, formula); err != n
il { | 920 if err := addFlatCalculatedTraces(resp, tile, formula); err != n
il { |
| 960 util.ReportError(w, r, err, fmt.Sprintf("Failed in /calc
/ to evaluate formula.")) | 921 util.ReportError(w, r, err, fmt.Sprintf("Failed in /calc
/ to evaluate formula.")) |
| 961 return | 922 return |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1099 fileServer := http.FileServer(http.Dir(*resourcesDir)) | 1060 fileServer := http.FileServer(http.Dir(*resourcesDir)) |
| 1100 return func(w http.ResponseWriter, r *http.Request) { | 1061 return func(w http.ResponseWriter, r *http.Request) { |
| 1101 w.Header().Add("Cache-Control", string(300)) | 1062 w.Header().Add("Cache-Control", string(300)) |
| 1102 fileServer.ServeHTTP(w, r) | 1063 fileServer.ServeHTTP(w, r) |
| 1103 } | 1064 } |
| 1104 } | 1065 } |
| 1105 | 1066 |
| 1106 func main() { | 1067 func main() { |
| 1107 defer common.LogPanic() | 1068 defer common.LogPanic() |
| 1108 // Setup DB flags. | 1069 // Setup DB flags. |
| 1109 » dbConf := db.DBConfigFromFlags() | 1070 » dbConf := idb.DBConfigFromFlags() |
| 1110 | 1071 |
| 1111 common.InitWithMetrics("skiaperf", graphiteServer) | 1072 common.InitWithMetrics("skiaperf", graphiteServer) |
| 1112 Init() | 1073 Init() |
| 1113 if !*local { | 1074 if !*local { |
| 1114 if err := dbConf.GetPasswordFromMetadata(); err != nil { | 1075 if err := dbConf.GetPasswordFromMetadata(); err != nil { |
| 1115 glog.Fatal(err) | 1076 glog.Fatal(err) |
| 1116 } | 1077 } |
| 1117 } | 1078 } |
| 1118 if err := dbConf.InitDB(); err != nil { | 1079 if err := dbConf.InitDB(); err != nil { |
| 1119 glog.Fatal(err) | 1080 glog.Fatal(err) |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1159 router.HandleFunc("/help/", helpHandler) | 1120 router.HandleFunc("/help/", helpHandler) |
| 1160 router.HandleFunc("/oauth2callback/", login.OAuth2CallbackHandler) | 1121 router.HandleFunc("/oauth2callback/", login.OAuth2CallbackHandler) |
| 1161 router.HandleFunc("/logout/", login.LogoutHandler) | 1122 router.HandleFunc("/logout/", login.LogoutHandler) |
| 1162 router.HandleFunc("/loginstatus/", login.StatusHandler) | 1123 router.HandleFunc("/loginstatus/", login.StatusHandler) |
| 1163 | 1124 |
| 1164 http.Handle("/", util.LoggingGzipRequestResponse(router)) | 1125 http.Handle("/", util.LoggingGzipRequestResponse(router)) |
| 1165 | 1126 |
| 1166 glog.Infoln("Ready to serve.") | 1127 glog.Infoln("Ready to serve.") |
| 1167 glog.Fatal(http.ListenAndServe(*port, nil)) | 1128 glog.Fatal(http.ListenAndServe(*port, nil)) |
| 1168 } | 1129 } |
| OLD | NEW |