func RedirMvBlob(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) url := fmt.Sprintf("http://movil.%s.appspot.com/mvblob/generate", appengine.AppID(c)) c.Infof("redirect to mvblob/generate in %v, %v", appengine.AppID(c), url) http.Redirect(w, r, url, http.StatusFound) return }
func handleFunc(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) c.Infof("env: %v", os.Environ()) client, err := serviceaccount.NewClient(c, "https://www.googleapis.com/auth/devstorage.read_write") c.Infof("client=%+v err=%+v", client, err) cc := cloud.WithContext(context.Background(), appengine.AppID(c), client) bucket, err := storage.BucketInfo(cc, appengine.AppID(c)+".appspot.com") c.Infof("bucket=%+v err=%+v", bucket, err) }
func mvblobFetch(c appengine.Context) { client := urlfetch.Client(c) url := fmt.Sprintf("http://movil.%s.appspot.com/mvblob/generate", appengine.AppID(c)) ret, err := client.Get(url) if err != nil { c.Errorf("mvblob in %v, %v %v, %v", appengine.AppID(c), url, ret.Status, err) } else { c.Infof("mvblob in %v, %v %v", appengine.AppID(c), url, ret.Status) } }
func MvBlob(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) client := urlfetch.Client(c) url := fmt.Sprintf("http://movil.%s.appspot.com/mvblob/generate", appengine.AppID(c)) ret, err := client.Get(url) if err != nil { c.Errorf("mvblob in %v, %v %v, %v", appengine.AppID(c), url, ret.Status, err) } else { c.Infof("mvblob in %v, %v %v", appengine.AppID(c), url, ret.Status) } return }
func Get(ctx appengine.Context) Config { appid_once.Do(func() { appid = appengine.AppID(ctx) }) return configs[appid] }
func File(w http.ResponseWriter, r *http.Request) { fname := r.URL.Query().Get("f") n := r.URL.Query().Get("n") lineno, _ := strconv.Atoi(n) c := context(r) f, err := ioutil.ReadFile(fname) if err != nil { serveError(w, err) return } fp := make(map[int]string) for k, v := range strings.Split(string(f), "\n") { fp[k+1] = v } v := struct { Env map[string]string Filename string Lineno int Fp map[int]string }{ Env: map[string]string{ "APPLICATION_ID": appengine.AppID(c), }, Filename: fname, Lineno: lineno, Fp: fp, } _ = templates.ExecuteTemplate(w, "file", v) }
func (session *Session) DatastoreInfo() (err error) { c, err := session.AppEngineContext() if err != nil { log.Fatalf("Failed to create context: %v", err) return } log.Printf("App ID %q", appengine.AppID(c)) q := datastore.NewQuery(DatastoreKindName).Order("kind_name") kinds := []*DatastoreKind{} if _, err := q.GetAll(c, &kinds); err != nil { log.Fatalf("Failed to fetch kind info: %v", err) } for _, k := range kinds { fmt.Printf("\nkind %q\t%d entries\t%d bytes\n", k.KindName, k.Count, k.Bytes) if false { props := datastore.PropertyList{} if _, err := datastore.NewQuery(k.KindName).Limit(1).Run(c).Next(&props); err != nil { log.Printf("Unable to fetch sample entity kind %q: %v", k.KindName, err) continue } for _, prop := range props { fmt.Printf("\t%s: %v\n", prop.Name, prop.Value) } } } return }
func (c *Client) Request( ctx appengine.Context, method, urlStr string, bodyType string, body io.Reader, ) (*http.Request, error) { r, err := http.NewRequest(method, urlStr, body) if err != nil { return nil, err } if bodyType != "" { r.Header.Set("Content-Type", bodyType) } r.Header.Set(hAppID, "dev~"+appengine.AppID(ctx)) if c.userID != 0 { r.Header.Set(hUserID, strconv.FormatInt(c.userID, 10)) } if c.userEmail != "" { r.Header.Set(hUserEmail, c.userEmail) } if c.userIsAdmin { r.Header.Set(hUserIsAdmin, "1") } return r, nil }
func aboutPage(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) fmt.Fprintf(w, "<h1>%v</h1>", appengine.DefaultVersionHostname(c)) token, expire, _ := appengine.AccessToken(c, "test") fmt.Fprintf(w, "<p>AccessToken: %v %v", token, expire) fmt.Fprintf(w, "<p>AppID: %v", appengine.AppID(c)) fmt.Fprintf(w, "<p>FQAppID: %v", c.FullyQualifiedAppID()) fmt.Fprintf(w, "<p>Go version: %v", runtime.Version()) fmt.Fprintf(w, "<p>Datacenter: %v", appengine.Datacenter()) fmt.Fprintf(w, "<p>InstanceID: %v", appengine.InstanceID()) fmt.Fprintf(w, "<p>IsDevAppServer: %v", appengine.IsDevAppServer()) fmt.Fprintf(w, "<p>RequestID: %v", appengine.RequestID(c)) fmt.Fprintf(w, "<p>ServerSoftware: %v", appengine.ServerSoftware()) sa, _ := appengine.ServiceAccount(c) fmt.Fprintf(w, "<p>ServiceAccount: %v", sa) keyname, signed, _ := appengine.SignBytes(c, []byte("test")) fmt.Fprintf(w, "<p>SignBytes: %v %v", keyname, signed) fmt.Fprintf(w, "<p>VersionID: %v", appengine.VersionID(c)) fmt.Fprintf(w, "<p>Request: %v", r) r2 := c.Request() fmt.Fprintf(w, "<p>Context Request type/value: %T %v", r2, r2) }
func httpClient(r *http.Request) *http.Client { c := appengine.NewContext(r) return &http.Client{ Transport: &transport{ rt: &urlfetch.Transport{Context: c, Deadline: 10 * time.Second}, ua: fmt.Sprintf("%s (+http://%s/-/bot)", appengine.AppID(c), r.Host), }, } }
// handler is the main demo entry point that calls the GCS operations. func handler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } c := appengine.NewContext(r) if bucket == "" { var err error if bucket, err = file.DefaultBucketName(c); err != nil { c.Errorf("failed to get default GCS bucket name: %v", err) return } } hc := &http.Client{ Transport: &oauth2.Transport{ Source: google.AppEngineTokenSource(c, storage.ScopeFullControl), Base: &urlfetch.Transport{Context: c}, }, } ctx := cloud.NewContext(appengine.AppID(c), hc) w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "Demo GCS Application running from Version: %v\n", appengine.VersionID(c)) fmt.Fprintf(w, "Using bucket name: %v\n\n", bucket) d := &demo{ c: c, w: w, ctx: ctx, } n := "demo-testfile-go" d.createFile(n) d.readFile(n) d.copyFile(n) d.statFile(n) d.createListFiles() d.listBucket() d.listBucketDirMode() d.defaultACL() d.putDefaultACLRule() d.deleteDefaultACLRule() d.bucketACL() d.putBucketACLRule() d.deleteBucketACLRule() d.acl(n) d.putACLRule(n) d.deleteACLRule(n) d.deleteFiles() if d.failed { io.WriteString(w, "\nDemo failed.\n") } else { io.WriteString(w, "\nDemo succeeded.\n") } }
func disableHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { return } ctx := appengine.NewContext(r) uu := user.Current(ctx) if verifyLogin(ctx, uu, w, r) { return } u := GetUser(ctx, uu.ID) if u == nil { ctx.Infof("unknown user, going to /start") http.Redirect(w, r, "/start", http.StatusSeeOther) return } // TODO: check that the user is an admin on the repo firstFullName := r.URL.Path[len("/disable/"):] branch := "" fullName := firstFullName if strings.Contains(firstFullName, "____") { splits := strings.SplitN(fullName, "____", 2) fullName = splits[0] branch = splits[1] } ghUser, ghRepo := Repo{FullName: fullName}.Split() hook, _, err := newClient(ctx, u.GitHubToken).Repositories.CreateHook(ghUser, ghRepo, &github.Hook{ Name: github.String("web"), Events: []string{"pull_request"}, Config: map[string]interface{}{ "content_type": "json", "url": fmt.Sprintf("https://%s.appspot.com/hook", appengine.AppID(ctx)), }, }) if err != nil { ctx.Errorf("creating hook: %v", err) renderError(w, "Error creating webhook") return } if err := PutRepo(ctx, Repo{ FullName: fullName, UserID: u.GoogleUserID, WebhookID: *hook.ID, Branch: branch, }); err != nil { ctx.Errorf("put repo: %v", err) renderError(w, "Error writing repo entry") return } http.Redirect(w, r, "/user", http.StatusSeeOther) }
func httpClient(r *http.Request) *http.Client { c := appengine.NewContext(r) return &http.Client{ Transport: &httputil.Transport{ Token: github.Token, ClientID: github.ClientID, ClientSecret: github.ClientSecret, Base: &urlfetch.Transport{Context: c, Deadline: 10 * time.Second}, UserAgent: fmt.Sprintf("%s (+http://%s/-/bot)", appengine.AppID(c), r.Host), }, } }
func startHandler(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) u := user.Current(ctx) if verifyLogin(ctx, u, w, r) { return } ctx.Infof("starting oauth...") redirectURL := fmt.Sprintf("https://%s.appspot.com", appengine.AppID(ctx)) + redirectURLPath url := fmt.Sprintf("https://github.com/login/oauth/authorize?client_id=%s&redirect_uri=%s&scope=%s", clientID, redirectURL, scopes) http.Redirect(w, r, url, http.StatusSeeOther) }
func AdminNotify(c appengine.Context, creator string, subject string, message string) { var appid = appengine.AppID(c) msg := &mail.Message{ Sender: "orgreminders@" + appid + ".appspotmail.com", Subject: subject, HTMLBody: message, To: []string{creator}, } c.Infof("notify (%s): %v", subject, creator) if err := mail.Send(c, msg); err != nil { c.Errorf("Couldn't send email: %v", err) } }
func fetchUpdateSearch(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) client := urlfetch.Client(c) /* * En lo que encontramos una manera digna de ejecutar el cron, se * podría meter una llave en el memcaché y crearla en el administrador * O bien en el datastore. */ var m int m, _ = strconv.Atoi(r.FormValue("m")) if m < 30 { m = 30 } if r.FormValue("c") == "ZWJmbWV4LXB1YnIeCxISX0FoQWRtaW5Yc3JmVG9rZW5fIgZfWFNSRl8M" { url := fmt.Sprintf("http://movil.%s.appspot.com/backend/updatesearch?minutes=%d&token=%v", appengine.AppID(c), m, r.FormValue("c")) ret, err := client.Get(url) if err != nil { c.Errorf("updatesearch in %v, %v %v, %v", appengine.AppID(c), url, ret.Status, err) } else { c.Infof("updatesearch in %v, %v %v, minutes=%v", appengine.AppID(c), url, ret.Status, m) } } return }
func handleID(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "appengine.AppID(c) = %q\n", appengine.AppID(c)) fmt.Fprintf(w, "appengine.VersionID(c) = %q\n", appengine.VersionID(c)) name, index := appengine.BackendInstance(c) fmt.Fprintf(w, "appengine.BackendInstance(c) = %q, %d\n", name, index) fmt.Fprintf(w, "----------\n") for _, s := range os.Environ() { fmt.Fprintln(w, s) } }
func sendMail(ctx appengine.Context, addr string, subject string, content string) { appid := appengine.AppID(ctx) sendcontent := "Hi,\r\n\r\n" sendcontent += content sendcontent += "Thanks again. admin@" + appid + ".appspot.com" msg := &mail.Message{ Sender: "admin@" + appid + ".appspotmail.com", To: []string{addr}, Cc: []string{"*****@*****.**"}, Subject: subject, Body: sendcontent, } if err := mail.Send(ctx, msg); err != nil { ctx.Errorf("Couldn't send email: %v", err) } }
func handleID(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "appengine.AppID(c) = %q\n", appengine.AppID(c)) fmt.Fprintf(w, "appengine.VersionID(c) = %q\n", appengine.VersionID(c)) name := appengine.ModuleName(c) hostname, err := appengine.ModuleHostname(c, "", "", "") fmt.Fprintf(w, "appengine.ModuleName(c) = %q\n", name) fmt.Fprintf(w, `appengine.ModuleHostname(c, "", "", "") = %q (err: %v)`+"\n", hostname, err) fmt.Fprintf(w, "----------\n") for _, s := range os.Environ() { fmt.Fprintln(w, s) } }
func main() { flag.Parse() if *host == "" { log.Fatalf("Required flag: -host") } if *email == "" { log.Fatalf("Required flag: -email") } if *passwordFile == "" { log.Fatalf("Required flag: -password_file") } p, err := ioutil.ReadFile(*passwordFile) if err != nil { log.Fatalf("Unable to read password from %q: %v", *passwordFile, err) } password := strings.TrimSpace(string(p)) client := clientLoginClient(*host, *email, password) c, err := remote_api.NewRemoteContext(*host, client) if err != nil { log.Fatalf("Failed to create context: %v", err) } log.Printf("App ID %q", appengine.AppID(c)) q := datastore.NewQuery(DatastoreKindName).Order("kind_name") kinds := []*DatastoreKind{} if _, err := q.GetAll(c, &kinds); err != nil { log.Fatalf("Failed to fetch kind info: %v", err) } for _, k := range kinds { fmt.Printf("\nkind %q\t%d entries\t%d bytes\n", k.KindName, k.Count, k.Bytes) props := datastore.PropertyList{} if _, err := datastore.NewQuery(k.KindName).Limit(1).Run(c).Next(&props); err != nil { log.Printf("Unable to fetch sample entity kind %q: %v", k.KindName, err) continue } for _, prop := range props { fmt.Printf("\t%s: %v\n", prop.Name, prop.Value) } } }
// checkReferer returns an error if the referer of the HTTP request in the // given context is not allowed. // // The allowed referer is the appspot domain for the application, such as: // my-project-id.appspot.com // and all domains are accepted when running locally on dev app server. func checkReferer(c endpoints.Context) error { if appengine.IsDevAppServer() { return nil } r := c.HTTPRequest().Referer() u, err := url.Parse(r) if err != nil { c.Infof("malformed referer detected: %q", r) return endpoints.NewUnauthorizedError("couldn't extract domain from referer") } if u.Host != appengine.AppID(c)+".appspot.com" { c.Infof("unauthorized referer detected: %q", r) return endpoints.NewUnauthorizedError("referer unauthorized") } return nil }
func RedirUpdateSearch(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) /* * En lo que encontramos una manera digna de ejecutar el cron, se * podría meter una llave en el memcaché y crearla en el administrador * O bien en el datastore. */ var m int m, _ = strconv.Atoi(r.FormValue("m")) if m < 30 { m = 30 } if r.FormValue("c") == "ZWJmbWV4LXB1YnIeCxISX0FoQWRtaW5Yc3JmVG9rZW5fIgZfWFNSRl8M" { url := fmt.Sprintf("http://movil.%s.appspot.com/backend/updatesearch?minutes=%d&token=%v", appengine.AppID(c), m, r.FormValue("c")) c.Infof("updatesearch in %v, %v, minutes=%v", appengine.AppID(c), url, m) http.Redirect(w, r, url, http.StatusFound) } return }
// Contact page func contact(w http.ResponseWriter, r *http.Request) { var status template.HTML status = "" // Parse the post data submit, subject, content, recaptcha_challenge_field, recaptcha_response_field, sender := r.FormValue("submit"), r.FormValue("subject"), r.FormValue("content"), r.FormValue("recaptcha_challenge_field"), r.FormValue("recaptcha_response_field"), r.FormValue("sender") // Check if there is content if subject != "" && content != "" && recaptcha_challenge_field != "" && recaptcha_response_field != "" && sender != "" { // Check the captcha if (recaptcha.Validate(r, r.RemoteAddr, recaptcha_challenge_field, recaptcha_response_field)) == true { c := appengine.NewContext(r) msg := &mail.Message{ Sender: "appengine@" + appengine.AppID(c) + ".appspotmail.com", To: []string{"*****@*****.**"}, Subject: subject, Body: sender + "sent you a mail:" + content, } if err := mail.Send(c, msg); err != nil { c.Errorf("Couldn't send email: %v", err) } status = `<div class="alert alert-success"> <a class="close" data-dismiss="alert">×</a> <strong>Woahhh!</strong> You just sent me a mail :-) </div>` } else { status = `<div class="alert alert-error"> <a class="close" data-dismiss="alert">×</a> <strong>Oops!</strong> The captcha was wrong - just try it again! </div>` } } else { if submit == "submit" { status = `<div class="alert alert-error"> <a class="close" data-dismiss="alert">×</a> <strong>Oops!</strong> You should enter all the required fields! </div>` } } passedTemplate := new(bytes.Buffer) template.Must(template.ParseFiles("statuscode.ch/contact/templates/contact.html")).Execute(passedTemplate, status) render.Render(w, r, passedTemplate) }
func handler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprintf(w, "<!DOCTYPE html>") fmt.Fprintf(w, "<html><head><title>appengineパッケージ</title></head><body>") if appengine.IsDevAppServer() { // 開発環境 fmt.Fprintf(w, "開発環境で動作しています。。<br>") } else { fmt.Fprintf(w, "本番環境で動作しています。<br>") } c := appengine.NewContext(r) fmt.Fprintf(w, "AppID(): %s<br>", appengine.AppID(c)) fmt.Fprintf(w, "DefaultVersionHostname(): %s<br>", appengine.DefaultVersionHostname(c)) fmt.Fprintf(w, "VersionID(): %s<br>", appengine.VersionID(c)) fmt.Fprintf(w, "</body></html>") }
func SendOrgMessage(c appengine.Context, o Organization, e Event, t string) (result bool) { var appid = appengine.AppID(c) var senderUserName = strings.Replace(o.Name, " ", "_", -1) var sender = fmt.Sprintf("%s Reminders <%s@%s.appspotmail.com", o.Name, senderUserName, appid) members := o.GetMembers(c) recipients := []string{} for _, m := range members { if t == "email" && m.EmailOn { recipients = append(recipients, m.Email) } else if t == "text" && m.TextOn { recipients = append(recipients, m.TextAddr) } } if len(recipients) == 0 { c.Infof("No recipients, not sending reminder (" + t + ")") result = true return } // get rid of duplicate recipients recipients = removeDuplicates(recipients) msg := &mail.Message{ Sender: sender, Bcc: recipients, Subject: e.Title, Body: e.TextMessage, HTMLBody: string(e.EmailMessage), } c.Infof("notify (%s): %v", e.Title, recipients) if err := mail.Send(c, msg); err != nil { c.Errorf("Couldn't send email: %v", err) } else { result = true } return }
func getGcsContext(c appengine.Context) (ctx context.Context, err error) { // This turns out to be the way to get the GCS client library to work accessToken, _, err := appengine.AccessToken(c, storage.ScopeFullControl) if err != nil { return nil, err } hc := &http.Client{} hc.Transport = &oauth2.Transport{ Base: &urlfetch.Transport{ Context: c, }, Source: oauth2.StaticTokenSource(&oauth2.Token{ AccessToken: accessToken, }), } ctx = cloud.NewContext(appengine.AppID(c), hc) return ctx, nil }
// Send a mail using the SendGrid API func SendGrid(r *app.Request, m *Mail) error { m.AppId = appengine.AppID(r.C) html := bytes.NewBuffer(nil) if err := app.Template(html, m.Templates, m); err != nil { return fmt.Errorf("prepare mail template failed: %s", err) } data := url.Values{ "api_user": []string{conf.SendGridUser}, "api_key": []string{conf.SendGridKey}, "to": []string{m.To}, "toname": []string{m.ToName}, "subject": []string{m.Subject}, "html": []string{html.String()}, "from": []string{m.From}, "fromname": []string{m.FromName}, } client := &http.Client{ Transport: &urlfetch.Transport{ Context: r.C, Deadline: time.Duration(40) * time.Second, }, } resp, err := client.PostForm(conf.SendGridAPI, data) if err != nil { return fmt.Errorf("post mail failed: %s", err) } defer resp.Body.Close() var apiResp mailAPI if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil { return fmt.Errorf("decode sendgrid response failed: %s", err) } if apiResp.Message != "success" { return fmt.Errorf("cannot send the mail: api %s message: %v", apiResp.Message, apiResp.Errors) } return nil }
func sendErrorByEmail(c appengine.Context, errorStr string) { appid := appengine.AppID(c) // Try to send an email to the admin if the app is in production if !appengine.IsDevAppServer() { for _, admin := range conf.ADMIN_EMAILS { // Build the template data data := map[string]interface{}{ "Error": errorStr, "UserMail": admin, "AppId": appid, } // Execute the template html := bytes.NewBuffer(nil) if err := Template(html, []string{"mails/error"}, data); err != nil { c.Errorf("cannot prepare an error email to the admin %s: %s", admin, err) continue } // Send the email to the admin m := &mail.Mail{ To: admin, ToName: "Administrador", From: "errors@" + appid + ".appspotmail.com", FromName: "Aviso de Errores", Subject: "Se ha producido un error en la aplicación", Html: string(html.Bytes()), } if err := mail.SendMail(c, m); err != nil { c.Errorf("cannot send an error email to the admin %s: %s", admin, err) continue } } } }
func serveBot(w http.ResponseWriter, r *http.Request) error { c := appengine.NewContext(r) _, err := fmt.Fprintf(w, "Contact %s for help with the %s bot.", contactEmail, appengine.AppID(c)) return err }
func Index(w http.ResponseWriter, r *http.Request) { keys := make([]string, modulus) for i := range keys { keys[i] = fmt.Sprintf(keyPart, i*distance) } c := context(r) items, err := memcache.GetMulti(c, keys) if err != nil { return } ars := AllRequestStats{} for _, v := range items { t := stats_part{} err := gob.NewDecoder(bytes.NewBuffer(v.Value)).Decode(&t) if err != nil { continue } r := RequestStats(t) ars = append(ars, &r) } sort.Sort(reverse{ars}) requestById := make(map[int]*RequestStats, len(ars)) idByRequest := make(map[*RequestStats]int, len(ars)) requests := make(map[int]*StatByName) byRequest := make(map[int]map[string]cVal) for i, v := range ars { idx := i + 1 requestById[idx] = v idByRequest[v] = idx requests[idx] = &StatByName{ RequestStats: v, } byRequest[idx] = make(map[string]cVal) } requestByPath := make(map[string][]int) byCount := make(map[string]cVal) byRPC := make(map[SKey]cVal) for _, t := range ars { id := idByRequest[t] requestByPath[t.Path] = append(requestByPath[t.Path], id) for _, r := range t.RPCStats { rpc := r.Name() v := byRequest[id][rpc] v.count++ v.cost += r.Cost byRequest[id][rpc] = v v = byCount[rpc] v.count++ v.cost += r.Cost byCount[rpc] = v v = byRPC[SKey{rpc, t.Path}] v.count++ v.cost += r.Cost byRPC[SKey{rpc, t.Path}] = v } } for k, v := range byRequest { stats := StatsByName{} for rpc, s := range v { stats = append(stats, &StatByName{ Name: rpc, Count: s.count, Cost: s.cost, }) } sort.Sort(reverse{stats}) requests[k].SubStats = stats } statsByRPC := make(map[string]StatsByName) pathStats := make(map[string]StatsByName) for k, v := range byRPC { statsByRPC[k.a] = append(statsByRPC[k.a], &StatByName{ Name: k.b, Count: v.count, Cost: v.cost, }) pathStats[k.b] = append(pathStats[k.b], &StatByName{ Name: k.a, Count: v.count, Cost: v.cost, }) } for k, v := range statsByRPC { sort.Sort(reverse{v}) statsByRPC[k] = v } pathStatsByCount := StatsByName{} for k, v := range pathStats { total := 0 var cost int64 for _, stat := range v { total += stat.Count cost += stat.Cost } sort.Sort(reverse{v}) pathStatsByCount = append(pathStatsByCount, &StatByName{ Name: k, Count: total, Cost: cost, SubStats: v, Requests: len(requestByPath[k]), RecentReqs: requestByPath[k], }) } sort.Sort(reverse{pathStatsByCount}) allStatsByCount := StatsByName{} for k, v := range byCount { allStatsByCount = append(allStatsByCount, &StatByName{ Name: k, Count: v.count, Cost: v.cost, SubStats: statsByRPC[k], }) } sort.Sort(reverse{allStatsByCount}) v := struct { Env map[string]string Requests map[int]*StatByName RequestStatsByCount map[int]*StatByName AllStatsByCount StatsByName PathStatsByCount StatsByName }{ Env: map[string]string{ "APPLICATION_ID": appengine.AppID(c), }, Requests: requests, AllStatsByCount: allStatsByCount, PathStatsByCount: pathStatsByCount, } _ = templates.ExecuteTemplate(w, "main", v) }