blob: 1f2f4704da6117933cc4782c58d2a11315a1467a [file] [log] [blame]
package api
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"time"
"github.com/go-chi/chi/v5"
"go.skia.org/infra/go/alogin"
"go.skia.org/infra/go/httputils"
"go.skia.org/infra/go/sklog"
"go.skia.org/infra/perf/go/chromeperf"
"go.skia.org/infra/perf/go/config"
)
const (
defaultAnomaliesRequestTimeout = time.Second * 30
)
type anomaliesApi struct {
chromeperfClient chromeperf.ChromePerfClient
loginProvider alogin.Login
}
// Response object for the request from sheriff list UI.
type GetSheriffListResponse struct {
SheriffList []string `json:"sheriff_list"`
Error string `json:"error"`
}
// Request object for the request from the anomaly table UI.
type GetAnomaliesRequest struct {
Sheriff string `json:"sheriff"`
IncludeTriaged bool `json:"triaged"`
IncludeImprovements bool `json:"improvements"`
QueryCursor string `json:"anomaly_cursor"`
Host string `json:"host"`
}
// Request object for the request from the anomaly table UI.
type GetAnomaliesResponse struct {
// The list of anomalies.
Anomalies []chromeperf.Anomaly `json:"anomaly_list"`
// The cursor of the current query. It will be used to 'Load More' for the next query.
QueryCursor string `json:"anomaly_cursor"`
// Error message if any.
Error string `json:"error"`
}
func (api anomaliesApi) RegisterHandlers(router *chi.Mux) {
router.Get("/_/anomalies/sheriff_list", api.GetSheriffList)
router.Get("/_/anomalies/anomaly_list", api.GetAnomalyList)
}
func NewAnomaliesApi(loginProvider alogin.Login, chromeperfClient chromeperf.ChromePerfClient) anomaliesApi {
return anomaliesApi{
loginProvider: loginProvider,
chromeperfClient: chromeperfClient,
}
}
func (api anomaliesApi) GetSheriffList(w http.ResponseWriter, r *http.Request) {
if api.loginProvider.LoggedInAs(r) == "" {
httputils.ReportError(w, errors.New("Not logged in"), fmt.Sprintf("You must be logged in to complete this action."), http.StatusUnauthorized)
return
}
sklog.Debug("[SkiaTriage] Get sheriff config list request received from frontend.")
w.Header().Set("Content-Type", "application/json")
ctx, cancel := context.WithTimeout(r.Context(), defaultAnomaliesRequestTimeout)
defer cancel()
getSheriffListResponse := &GetSheriffListResponse{}
err := api.chromeperfClient.SendGetRequest(ctx, "sheriff_configs_skia", "", url.Values{}, getSheriffListResponse)
if err != nil {
httputils.ReportError(w, err, "Failed to finish get sheriff list request.", http.StatusInternalServerError)
return
}
if getSheriffListResponse.Error != "" {
httputils.ReportError(w, errors.New(getSheriffListResponse.Error), "Load sheriff list request returned error.", http.StatusInternalServerError)
return
}
if err := json.NewEncoder(w).Encode(getSheriffListResponse); err != nil {
httputils.ReportError(w, err, "Failed to write sheriff list to UI response.", http.StatusInternalServerError)
return
}
sklog.Debugf("[SkiaTriage] sheriff config list is loaded: %s", getSheriffListResponse.SheriffList)
return
}
func (api anomaliesApi) GetAnomalyList(w http.ResponseWriter, r *http.Request) {
if api.loginProvider.LoggedInAs(r) == "" {
httputils.ReportError(w, errors.New("Not logged in"), fmt.Sprintf("You must be logged in to complete this action."), http.StatusUnauthorized)
return
}
query_values := r.URL.Query()
sklog.Debugf("[SkiaTriage] Get anomalies request received from frontend: %s", query_values)
if query_values.Get("host") == "" {
query_values["host"] = []string{config.Config.URL}
}
w.Header().Set("Content-Type", "application/json")
ctx, cancel := context.WithTimeout(r.Context(), defaultAnomaliesRequestTimeout)
defer cancel()
getAnoamliesResponse := &GetAnomaliesResponse{}
err := api.chromeperfClient.SendGetRequest(ctx, "alerts_skia", "", query_values, getAnoamliesResponse)
if err != nil {
httputils.ReportError(w, err, "Get anomalies request failed due to an internal server error. Please try again.", http.StatusInternalServerError)
return
}
if getAnoamliesResponse.Error != "" {
httputils.ReportError(w, errors.New(getAnoamliesResponse.Error), fmt.Sprintf("Error when getting the anomaly list. Please double check each request parameter, and try again: %v", getAnoamliesResponse.Error), http.StatusBadRequest)
return
}
if err := json.NewEncoder(w).Encode(getAnoamliesResponse); err != nil {
httputils.ReportError(w, err, "Failed to write get anoamlies response.", http.StatusInternalServerError)
return
}
sklog.Debugf("[SkiaTriage] %d anomalies are received.", len(getAnoamliesResponse.Anomalies))
return
}