Exemple #1
0
// clHandler serves the HTML for the /cl/<id> page.
//
// These are shortcuts to individual clusters.
//
// See alertingHandler for the JSON it uses.
//
func clHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	if *local {
		loadTemplates()
	}

	match := clHandlerPath.FindStringSubmatch(r.URL.Path)
	if r.Method != "GET" || match == nil || len(match) != 2 {
		http.NotFound(w, r)
		return
	}
	id, err := strconv.ParseInt(match[1], 10, 0)
	if err != nil {
		util.ReportError(w, r, err, "Failed parsing ID.")
		return
	}
	cl, err := alerting.Get(id)
	if err != nil {
		util.ReportError(w, r, err, "Failed to find cluster with that ID.")
		return
	}
	if err := templates.ExecuteTemplate(w, "cl.html", cl); err != nil {
		glog.Errorln("Failed to expand template:", err)
	}
}
// Handler serves the /annotate/ endpoint for changing the status of an
// alert cluster. It also writes a new types.Activity log record to the database.
//
// Expects a POST of JSON of the following form:
//
//   {
//     Id: 20                - The id of the alerting cluster.
//     Status: "Ignore"      - The new Status value.
//     Message: "SKP Update" - The new Messge value.
//   }
//
// Returns JSON of the form:
//
//  {
//    "Bug": "http://"
//  }
//
// Where bug, if set, is the URL the user should be directed to to log a bug report.
func Handler(w http.ResponseWriter, r *http.Request) {
	glog.Infof("Annotate Handler: %q\n", r.URL.Path)

	if login.LoggedInAs(r) == "" {
		util.ReportError(w, r, fmt.Errorf("Not logged in."), "You must be logged in to change an alert status.")
		return
	}
	if r.Method != "POST" {
		http.NotFound(w, r)
		return
	}
	if r.Body == nil {
		util.ReportError(w, r, fmt.Errorf("Missing POST Body."), "POST with no request body.")
		return
	}

	req := struct {
		Id      int64
		Status  string
		Message string
	}{}
	dec := json.NewDecoder(r.Body)
	if err := dec.Decode(&req); err != nil {
		util.ReportError(w, r, err, "Unable to decode posted JSON.")
		return
	}

	if !util.In(req.Status, types.ValidStatusValues) {
		util.ReportError(w, r, fmt.Errorf("Invalid status value: %s", req.Status), "Unknown value.")
		return
	}

	// Store the updated values in the ClusterSummary.
	c, err := alerting.Get(req.Id)
	if err != nil {
		util.ReportError(w, r, err, "Failed to load cluster summary.")
		return
	}
	c.Status = req.Status
	c.Message = req.Message
	if err := alerting.Write(c); err != nil {
		util.ReportError(w, r, err, "Failed to save cluster summary.")
		return
	}

	// Write a new Activity record.
	// TODO(jcgregorio) Move into alerting.Write().
	a := &types.Activity{
		UserID: login.LoggedInAs(r),
		Action: "Perf Alert: " + req.Status,
		URL:    fmt.Sprintf("https://perf.skia.org/cl/%d", req.Id),
	}
	if err := activitylog.Write(a); err != nil {
		util.ReportError(w, r, err, "Failed to save activity.")
		return
	}

	retval := map[string]string{}

	if req.Status == "Bug" {
		q := url.Values{
			"labels":  []string{"FromSkiaPerf,Type-Defect,Priority-Medium"},
			"comment": []string{fmt.Sprintf(ISSUE_COMMENT_TEMPLATE, req.Id)},
		}
		retval["Bug"] = "https://bugs.chromium.org/p/skia/issues/entry?" + q.Encode()
	}
	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)
	if err := enc.Encode(retval); err != nil {
		glog.Errorf("Failed to write or encode output: %s", err)
	}
}