mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
feat(api): add an enpoint that returns all known label values for given label name
This will be used in the silence form, to provide a list of suggestions
This commit is contained in:
@@ -61,3 +61,43 @@ func knownLabelNames(c *gin.Context) {
|
||||
c.Data(http.StatusOK, gin.MIMEJSON, data.([]byte))
|
||||
logAlertsView(c, "MIS", time.Since(start))
|
||||
}
|
||||
|
||||
func knownLabelValues(c *gin.Context) {
|
||||
noCache(c)
|
||||
start := time.Now()
|
||||
|
||||
cacheKey := c.Request.RequestURI
|
||||
if cacheKey == "" {
|
||||
// FIXME c.Request.RequestURI is empty when running tests for some reason
|
||||
// needs checking, below acts as a workaround
|
||||
cacheKey = c.Request.URL.RawQuery
|
||||
}
|
||||
|
||||
data, found := apiCache.Get(cacheKey)
|
||||
if found {
|
||||
c.Data(http.StatusOK, gin.MIMEJSON, data.([]byte))
|
||||
logAlertsView(c, "HIT", time.Since(start))
|
||||
return
|
||||
}
|
||||
|
||||
name, found := c.GetQuery("name")
|
||||
if !found || name == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "missing name=<token> parameter"})
|
||||
log.Infof("[%s] <%d> %s %s took %s", c.ClientIP(), http.StatusBadRequest, c.Request.Method, c.Request.RequestURI, time.Since(start))
|
||||
return
|
||||
}
|
||||
|
||||
values := alertmanager.DedupKnownLabelValues(name)
|
||||
sort.Strings(values)
|
||||
|
||||
data, err := json.Marshal(values)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
panic(err)
|
||||
}
|
||||
|
||||
apiCache.Set(cacheKey, data, time.Second*15)
|
||||
|
||||
c.Data(http.StatusOK, gin.MIMEJSON, data.([]byte))
|
||||
logAlertsView(c, "MIS", time.Since(start))
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ var labelTests = []labelTest{
|
||||
},
|
||||
}
|
||||
|
||||
func TestKnownLabels(t *testing.T) {
|
||||
func TestKnownLabelNames(t *testing.T) {
|
||||
mockConfig()
|
||||
for _, version := range mock.ListAllMocks() {
|
||||
t.Logf("Testing known labels using mock files from Alertmanager %s", version)
|
||||
@@ -68,3 +68,58 @@ func TestKnownLabels(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type valueTest struct {
|
||||
Name string
|
||||
Results []string
|
||||
}
|
||||
|
||||
var valueTests = []valueTest{
|
||||
{
|
||||
Name: "foobar",
|
||||
Results: []string{},
|
||||
},
|
||||
{
|
||||
Name: "alertname",
|
||||
Results: []string{"Free_Disk_Space_Too_Low", "HTTP_Probe_Failed", "Host_Down", "Memory_Usage_Too_High"},
|
||||
},
|
||||
{
|
||||
Name: "cluster",
|
||||
Results: []string{"dev", "prod", "staging"},
|
||||
},
|
||||
}
|
||||
|
||||
func TestKnownLabelValues(t *testing.T) {
|
||||
mockConfig()
|
||||
for _, version := range mock.ListAllMocks() {
|
||||
t.Logf("Testing known label values using mock files from Alertmanager %s", version)
|
||||
mockAlerts(version)
|
||||
r := ginTestEngine()
|
||||
|
||||
req, _ := http.NewRequest("GET", "/labelValues.json", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
r.ServeHTTP(resp, req)
|
||||
if resp.Code != http.StatusBadRequest {
|
||||
t.Errorf("Invalid status code for request without any query: %d", resp.Code)
|
||||
}
|
||||
|
||||
for _, testCase := range valueTests {
|
||||
url := fmt.Sprintf("/labelValues.json?name=%s", testCase.Name)
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
resp := httptest.NewRecorder()
|
||||
r.ServeHTTP(resp, req)
|
||||
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Errorf("GET %s returned status %d", url, resp.Code)
|
||||
}
|
||||
|
||||
ur := []string{}
|
||||
json.Unmarshal(resp.Body.Bytes(), &ur)
|
||||
|
||||
if len(ur) != len(testCase.Results) {
|
||||
t.Errorf("Invalid number of label values for %s, got %d, expected %d", url, len(ur), len(testCase.Results))
|
||||
t.Errorf("Results: %s", ur)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,3 +180,25 @@ func DedupKnownLabels() []string {
|
||||
}
|
||||
return flatLabels
|
||||
}
|
||||
|
||||
// DedupKnownLabelValues returns a list of all known values for label $name
|
||||
func DedupKnownLabelValues(name string) []string {
|
||||
dedupedValues := map[string]bool{}
|
||||
upstreams := GetAlertmanagers()
|
||||
|
||||
for _, am := range upstreams {
|
||||
for _, ag := range am.Alerts() {
|
||||
for _, alert := range ag.Alerts {
|
||||
if val, found := alert.Labels[name]; found {
|
||||
dedupedValues[val] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flatValues := []string{}
|
||||
for key := range dedupedValues {
|
||||
flatValues = append(flatValues, key)
|
||||
}
|
||||
return flatValues
|
||||
}
|
||||
|
||||
1
main.go
1
main.go
@@ -69,6 +69,7 @@ func setupRouter(router *gin.Engine) {
|
||||
router.GET(getViewURL("/alerts.json"), alerts)
|
||||
router.GET(getViewURL("/autocomplete.json"), autocomplete)
|
||||
router.GET(getViewURL("/labelNames.json"), knownLabelNames)
|
||||
router.GET(getViewURL("/labelValues.json"), knownLabelValues)
|
||||
router.NoRoute(notFound)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user