blob: fec4b204836eeb02ad94c0b8dac91cdf5303c622 [file] [log] [blame]
package chromeperf
import (
"context"
"net/url"
"strings"
"go.skia.org/infra/go/metrics2"
"go.skia.org/infra/go/skerr"
"go.skia.org/infra/go/sklog"
"go.skia.org/infra/go/util"
)
const (
AlertGroupAPIName = "alert_group"
DetailsFuncName = "details"
)
// AlertGroupDetails contains data received from the alert group api.
type AlertGroupDetails struct {
GroupId string `json:"group_id"`
Anomalies map[string]string `json:"anomalies"`
StartCommitNumber int32 `json:"start_commit"`
EndCommitNumber int32 `json:"end_commit"`
}
// AlertGroupApiClient provides an interface to interact with the alert_group api in chromeperf.
type AlertGroupApiClient interface {
// GetAlertGroupDetails returns the alert group details for the provided group key.
GetAlertGroupDetails(ctx context.Context, groupKey string) (*AlertGroupDetails, error)
}
// alertGroupApiClientImpl implements AlertGroupApiClient.
type alertGroupApiClientImpl struct {
chromeperfClient chromePerfClient
getAlertGroupDetailsCalled metrics2.Counter
getAlertGroupDetailsFailed metrics2.Counter
}
// GetAlertGroupDetails implements AlertGroupApiClient, returns alert group details for the provided group key.
func (client *alertGroupApiClientImpl) GetAlertGroupDetails(ctx context.Context, groupKey string) (*AlertGroupDetails, error) {
if groupKey == "" {
return nil, skerr.Fmt("Group key cannot be empty")
}
client.getAlertGroupDetailsCalled.Inc(1)
// Call Chrome Perf API to fetch alert group details
alertgroupResponse := AlertGroupDetails{}
err := client.chromeperfClient.sendGetRequest(ctx, AlertGroupAPIName, DetailsFuncName, url.Values{"key": {groupKey}}, &alertgroupResponse)
if err != nil {
client.getAlertGroupDetailsFailed.Inc(1)
return nil, skerr.Wrapf(err, "Failed to call chrome perf endpoint.")
}
return &alertgroupResponse, nil
}
// GetQueryParams returns the query parameters corresponding to the alert group data.
func (alertGroup *AlertGroupDetails) GetQueryParams(ctx context.Context) map[string][]string {
sklog.Infof("Start commit: %d, End commit: %d", alertGroup.StartCommitNumber, alertGroup.EndCommitNumber)
// We do not want duplicate params, hence create maps to use as a set datastructure for each param
masters_map := util.StringSet{}
bots_map := util.StringSet{}
benchmarks_map := util.StringSet{}
tests_map := util.StringSet{}
subtests_1_map := util.StringSet{}
subtests_2_map := util.StringSet{}
const masters_key = "masters"
const bots_key = "bots"
const benchmarks_key = "benchmarks"
const tests_key = "tests"
const subtests_1_key = "subtests_1"
const subtests_2_key = "subtests_2"
parsedInfo := map[string][]string{}
for _, test := range alertGroup.Anomalies {
splits := strings.Split(test, "/")
addToSetIfNotExists(masters_map, splits[0], parsedInfo, masters_key)
addToSetIfNotExists(bots_map, splits[1], parsedInfo, bots_key)
addToSetIfNotExists(benchmarks_map, splits[2], parsedInfo, benchmarks_key)
addToSetIfNotExists(tests_map, splits[3], parsedInfo, tests_key)
addToSetIfNotExists(subtests_1_map, splits[4], parsedInfo, subtests_1_key)
if len(splits) > 5 {
addToSetIfNotExists(subtests_2_map, splits[5], parsedInfo, subtests_2_key)
}
}
paramsMap := map[string][]string{}
paramsMap["stat"] = []string{"value"}
paramsMap["master"] = parsedInfo[masters_key]
paramsMap["bot"] = parsedInfo[bots_key]
paramsMap["benchmark"] = parsedInfo[benchmarks_key]
paramsMap["test"] = parsedInfo[tests_key]
paramsMap["subtest_1"] = parsedInfo[subtests_1_key]
sub_2, ok := parsedInfo[subtests_2_key]
if ok && len(sub_2) > 0 {
paramsMap["subtest_2"] = parsedInfo[subtests_2_key]
}
return paramsMap
}
func addToSetIfNotExists(set util.StringSet, value string, parsedInfo map[string][]string, parsedInfoKey string) {
// Check if the parsedinfo key is present in the parsed data
if _, ok := parsedInfo[parsedInfoKey]; !ok {
parsedInfo[parsedInfoKey] = []string{}
}
// Append to the set if it isn't already present
if _, ok := set[value]; !ok {
set[value] = true
parsedInfo[parsedInfoKey] = append(parsedInfo[parsedInfoKey], value)
}
}
// NewAlertGroupApiClient returns a new instance of AlertGroupApiClient
func NewAlertGroupApiClient(ctx context.Context) (AlertGroupApiClient, error) {
cpClient, err := newChromePerfClient(ctx, "")
if err != nil {
return nil, err
}
return newAlertGroupApiClient(cpClient), nil
}
// newAlertGroupApiClient returns a new instance of AlertGroupApiClient with the given chromeperf client
func newAlertGroupApiClient(cpClient chromePerfClient) AlertGroupApiClient {
return &alertGroupApiClientImpl{
chromeperfClient: cpClient,
getAlertGroupDetailsCalled: metrics2.GetCounter("chrome_perf_get_alertgroup_details_called"),
getAlertGroupDetailsFailed: metrics2.GetCounter("chrome_perf_get_alertgroup_details_failed"),
}
}