add alerting api and router
This commit is contained in:
parent
b1e1a47cc3
commit
f8d62a1655
21
api/init.go
21
api/init.go
|
@ -43,6 +43,27 @@ func Init(cfg *config.AppConfig) {
|
|||
ui.HandleUIMethod(api.POST, "/elasticsearch/:id/alerting/_aliases", alerting.GetAliases)
|
||||
ui.HandleUIMethod(api.POST, "/elasticsearch/:id/alerting/_mappings", alerting.GetMappings)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/_plugins", alerting.GetPlugins)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/monitors/:monitorID", alerting.GetMonitor)
|
||||
ui.HandleUIMethod(api.PUT, "/elasticsearch/:id/alerting/monitors/:monitorID", alerting.UpdateMonitor)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/monitors", alerting.GetMonitors)
|
||||
ui.HandleUIMethod(api.POST, "/elasticsearch/:id/alerting/monitors", alerting.CreateMonitor)
|
||||
ui.HandleUIMethod(api.POST, "/elasticsearch/:id/alerting/monitors/_execute", alerting.ExecuteMonitor)
|
||||
ui.HandleUIMethod(api.DELETE, "/elasticsearch/:id/alerting/monitors/:monitorID", alerting.DeleteMonitor)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/_settings", alerting.GetSettings)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/destinations", alerting.GetDestinations)
|
||||
ui.HandleUIMethod(api.POST, "/elasticsearch/:id/alerting/destinations", alerting.CreateDestination)
|
||||
ui.HandleUIMethod(api.PUT, "/elasticsearch/:id/alerting/destinations/:destinationId", alerting.UpdateDestination)
|
||||
ui.HandleUIMethod(api.DELETE, "/elasticsearch/:id/alerting/destinations/:destinationId", alerting.DeleteDestination)
|
||||
ui.HandleUIMethod(api.POST, "/elasticsearch/:id/alerting/destinations/email_accounts", alerting.CreateEmailAccount)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/destinations/email_accounts", alerting.GetEmailAccounts)
|
||||
ui.HandleUIMethod(api.DELETE, "/elasticsearch/:id/alerting/email_accounts/:emailAccountId", alerting.DeleteEmailAccount)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/email_accounts/:emailAccountId", alerting.GetEmailAccount)
|
||||
ui.HandleUIMethod(api.PUT, "/elasticsearch/:id/alerting/email_accounts/:emailAccountId", alerting.UpdateEmailAccount)
|
||||
ui.HandleUIMethod(api.POST, "/elasticsearch/:id/alerting/destinations/email_groups", alerting.CreateEmailGroup)
|
||||
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/destinations/email_groups", alerting.GetEmailGroups)
|
||||
ui.HandleUIMethod(api.DELETE, "/elasticsearch/:id/alerting/email_groups/:emailGroupId", alerting.DeleteEmailGroup)
|
||||
ui.HandleUIMethod(api.PUT, "/elasticsearch/:id/alerting/email_groups/:emailGroupId", alerting.UpdateEmailGroup)
|
||||
|
||||
|
||||
|
||||
task.RegisterScheduleTask(task.ScheduleTask{
|
||||
|
|
|
@ -34,7 +34,7 @@ func GetAlerts (w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
|||
var (
|
||||
from = getQueryParam(req, "from", "0")
|
||||
size = getQueryParam(req, "size", "20")
|
||||
search = getQueryParam(req, "search")
|
||||
search = getQueryParam(req, "search", "")
|
||||
sortDirection = getQueryParam(req, "sortDirection", "desc")
|
||||
sortField = getQueryParam(req, "sortField", "start_time")
|
||||
severityLevel = getQueryParam(req, "severityLevel", "ALL")
|
||||
|
@ -74,57 +74,65 @@ func GetAlerts (w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
|||
clearSearch = strings.Join(searches, "* *")
|
||||
params["searchString"] = fmt.Sprintf("*%s*", clearSearch)
|
||||
}
|
||||
reqUrl := conf.Endpoint + "/_opendistro/_alerting/monitors/alerts"
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors/alerts", conf.Endpoint, API_PREFIX )
|
||||
|
||||
res, err := doRequest(reqUrl, http.MethodGet, params, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
var alertRes = AlertResponse{}
|
||||
var alertRes = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &alertRes)
|
||||
defer res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
alerts := []IfaceMap{}
|
||||
rawAlerts := queryValue(alertRes, "alerts", nil)
|
||||
if ds, ok := rawAlerts.([]interface{}); ok {
|
||||
for _, alert := range ds {
|
||||
if alertItem, ok := alert.(map[string]interface{}); ok {
|
||||
|
||||
var alerts = []IfaceMap{}
|
||||
for _, hit := range alertRes.Alerts {
|
||||
alert := IfaceMap{
|
||||
"id": hit["alert_id"],
|
||||
alertItem["version"] = queryValue(alertItem, "alert_version", "")
|
||||
alertItem["id"] = queryValue(alertItem, "alert_id", "")
|
||||
alerts = append(alerts, alertItem)
|
||||
}
|
||||
}
|
||||
for k, v := range hit {
|
||||
alert[k] = v
|
||||
}
|
||||
alert["version"] = hit["alert_version"]
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"alerts": alerts,
|
||||
"totalAlerts": alertRes.TotalAlerts,
|
||||
"totalAlerts": queryValue(alertRes, "totalAlerts", 0),
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
func writeError(w http.ResponseWriter, err error) {
|
||||
writeJSON(w, map[string]interface{}{
|
||||
"body": map[string]interface{}{
|
||||
"ok": false,
|
||||
"err": err.Error(),
|
||||
},
|
||||
"ok": false,
|
||||
"resp": err.Error(),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
type IfaceMap map[string]interface{}
|
||||
|
||||
type AlertResponse struct {
|
||||
Alerts []IfaceMap `json:"alerts"`
|
||||
TotalAlerts int `json:"totalAlerts"`
|
||||
}
|
||||
|
||||
func decodeJSON(reader io.Reader, obj interface{}) error{
|
||||
dec := json.NewDecoder(reader)
|
||||
return dec.Decode(obj)
|
||||
err := dec.Decode(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if m, ok := obj.(*IfaceMap); ok {
|
||||
if errStr := queryValue(*m,"error", nil); errStr != nil {
|
||||
if str, ok := errStr.(string); ok {
|
||||
errors.New(str)
|
||||
}
|
||||
buf, _ := json.Marshal(errStr)
|
||||
return errors.New(string(buf))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeJSON(w http.ResponseWriter, data interface{}, statusCode int){
|
||||
|
@ -168,5 +176,36 @@ func doRequest(requestUrl string, method string, params map[string]string, body
|
|||
}
|
||||
req, _ = http.NewRequest(method, requestUrl, reader)
|
||||
req.Header.Set("content-type", "application/json")
|
||||
req.Header.Set("User-Agent", "Kibana")
|
||||
return alertClient.Do(req)
|
||||
}
|
||||
|
||||
func queryValue(obj map[string]interface{}, key string, defaultValue interface{}) interface{} {
|
||||
if key == "" {
|
||||
return obj
|
||||
}
|
||||
idx := strings.Index(key, ".")
|
||||
if idx == -1 {
|
||||
if v, ok := obj[key]; ok {
|
||||
return v
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
ckey := key[0:idx]
|
||||
|
||||
if v, ok := obj[ckey]; ok {
|
||||
if vmap, ok := v.(map[string]interface{}); ok {
|
||||
return queryValue(vmap, key[idx+1:], defaultValue)
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func assignTo(dst IfaceMap, src IfaceMap){
|
||||
if dst == nil || src == nil {
|
||||
return
|
||||
}
|
||||
for k, v := range src {
|
||||
dst[k] = v
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package alerting
|
||||
|
||||
const INFINI_PREFIX = "opendistro"
|
||||
|
||||
const PLUGIN_NAME = INFINI_PREFIX + "-alerting"
|
||||
const INDEX_PREFIX = INFINI_PREFIX +"-alerting"
|
||||
|
||||
const INDEX_ALL_ALERTS = "."+INDEX_PREFIX +`-alert*`
|
||||
|
||||
const API_PREFIX = "_opendistro"
|
|
@ -0,0 +1,720 @@
|
|||
package alerting
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
httprouter "infini.sh/framework/core/api/router"
|
||||
"infini.sh/framework/core/elastic"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
dstID := ps.ByName("destID")
|
||||
reqUrl := fmt.Sprintf("%s/_opendistro/_alerting/monitors/%s", conf.Endpoint, dstID)
|
||||
res, err := doRequest(reqUrl, http.MethodGet, nil, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
res.Body.Close()
|
||||
|
||||
if _, ok := resBody["monitor"]; !ok {
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": false,
|
||||
}, http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
queryDSL := ` {
|
||||
"size": 0,
|
||||
"query"": {
|
||||
"bool": {
|
||||
"must": {
|
||||
"term"": {
|
||||
"monitor_id": "%s",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"aggs": {
|
||||
"active_count": {
|
||||
"terms": {
|
||||
"field": "state",
|
||||
}
|
||||
},
|
||||
"24_hour_count": {
|
||||
"date_range": {
|
||||
"field": "start_time",
|
||||
"ranges": [{ "from": "now-24h/h" }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
queryDSL = fmt.Sprintf(queryDSL, id)
|
||||
reqUrl = fmt.Sprintf("%s/_opendistro/_alerting/monitors/_search", conf.Endpoint)
|
||||
res, err = doRequest(reqUrl, http.MethodPost, map[string]string{
|
||||
"index": ".opendistro-alerting-alert*",
|
||||
}, queryDSL)
|
||||
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var searchResBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &searchResBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
dayCount := queryValue(searchResBody, "aggregations.24_hour_count.buckets.0.doc_count", 0)
|
||||
activeBuckets := queryValue(searchResBody, "aggregations.active_count.buckets",[]interface{}{})
|
||||
activeCount := 0
|
||||
if ab, ok := activeBuckets.([]IfaceMap); ok {
|
||||
for _, curr := range ab {
|
||||
if curr["key"].(string) == "ACTIVE" {
|
||||
activeCount = int(curr["doc_count"].(float64))
|
||||
}
|
||||
}
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody["monitor"],
|
||||
"activeCount": activeCount,
|
||||
"dayCount": dayCount,
|
||||
"version": queryValue(resBody, "_version", nil),
|
||||
"ifSeqNo": queryValue(resBody, "_seq_no", nil),
|
||||
"ifPrimaryTerm": queryValue(resBody, "_primary_term", nil),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func GetDestinations(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
var (
|
||||
from = getQueryParam(req, "from", "0")
|
||||
size = getQueryParam(req, "size", "20")
|
||||
search = getQueryParam(req, "search", "")
|
||||
sortDirection = getQueryParam(req, "sortDirection", "desc")
|
||||
sortField = getQueryParam(req, "sortField", "start_time")
|
||||
typ = getQueryParam(req, "type", "ALL")
|
||||
)
|
||||
|
||||
var params = map[string]string{}
|
||||
switch (sortField) {
|
||||
case "name":
|
||||
params = map[string]string{
|
||||
"sortString": "destination.name.keyword",
|
||||
"sortOrder": sortDirection,
|
||||
}
|
||||
case "type":
|
||||
params = map[string]string{
|
||||
"sortString": "destination.type",
|
||||
"sortOrder": sortDirection,
|
||||
}
|
||||
default:
|
||||
}
|
||||
params["startIndex"] = from
|
||||
params["size"] = size
|
||||
params["searchString"] = search
|
||||
params["destinationType"] = typ
|
||||
if clearSearch := strings.TrimSpace(search); clearSearch != "" {
|
||||
clearSearch = strings.ReplaceAll(clearSearch, " ", "* *")
|
||||
params["searchString"] = clearSearch
|
||||
}
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodGet, params, nil)
|
||||
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
rawDests := queryValue(resBody, "destinations", []interface{}{})
|
||||
dests := []IfaceMap{}
|
||||
|
||||
if ds, ok := rawDests.([]interface{}); ok {
|
||||
for _, dest := range ds {
|
||||
if destination, ok := dest.(map[string]interface{}); ok {
|
||||
|
||||
destination["version"] = queryValue(destination, "schema_version", "")
|
||||
destination["ifSeqNo"] = queryValue(destination, "seq_no", 0)
|
||||
destination["ifPrimaryTerm"] = queryValue(destination, "primary_term", 0)
|
||||
dests = append(dests, destination)
|
||||
}
|
||||
}
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"destinations": dests,
|
||||
"totalDestinations": queryValue(resBody, "totalDestinations", 0),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func CreateDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodPost, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func UpdateDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
destinationId := ps.ByName("destinationId")
|
||||
var (
|
||||
ifSeqNo = getQueryParam(req, "ifSeqNo")
|
||||
ifPrimaryTerm = getQueryParam(req, "ifPrimaryTerm")
|
||||
)
|
||||
//PUT /_opendistro/_alerting/destinations/2g3CsHsB3EDgQAwRGzgS?if_seq_no=15&if_primary_term=2&refresh=wait_for
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/%s", conf.Endpoint, API_PREFIX, destinationId)
|
||||
res, err := doRequest(reqUrl, http.MethodPut, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
"if_seq_no": ifSeqNo,
|
||||
"if_primary_term": ifPrimaryTerm,
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"version": queryValue(resBody, "_version", ""),
|
||||
"id": queryValue(resBody, "_id", ""),
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func DeleteDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
destinationId := ps.ByName("destinationId")
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/%s", conf.Endpoint, API_PREFIX, destinationId)
|
||||
res, err := doRequest(reqUrl, http.MethodDelete, nil, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
resultIfce := queryValue(resBody, "result", "")
|
||||
var isOk = false
|
||||
if result, ok := resultIfce.(string); ok && result == "deleted" {
|
||||
isOk = true
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": isOk,
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func CreateEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_accounts", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodPost, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func UpdateEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
emailAccountId := ps.ByName("emailAccountId")
|
||||
var (
|
||||
ifSeqNo = getQueryParam(req, "ifSeqNo")
|
||||
ifPrimaryTerm = getQueryParam(req, "ifPrimaryTerm")
|
||||
)
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_accounts/%s", conf.Endpoint, API_PREFIX, emailAccountId)
|
||||
res, err := doRequest(reqUrl, http.MethodPut, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
"if_seq_no": ifSeqNo,
|
||||
"if_primary_term": ifPrimaryTerm,
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"id": queryValue(resBody, "_id", ""),
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func DeleteEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
emailAccountId := ps.ByName("emailAccountId")
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_accounts/%s", conf.Endpoint, API_PREFIX, emailAccountId)
|
||||
res, err := doRequest(reqUrl, http.MethodDelete, nil, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
resultIfce := queryValue(resBody, "result", "")
|
||||
var isOk = false
|
||||
if result, ok := resultIfce.(string); ok && result == "deleted" {
|
||||
isOk = true
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": isOk,
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func GetEmailAccounts(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
var (
|
||||
from = getQueryParam(req, "from", "0")
|
||||
size = getQueryParam(req, "size", "20")
|
||||
search = getQueryParam(req, "search", "")
|
||||
sortDirection = getQueryParam(req, "sortDirection", "desc")
|
||||
sortField = getQueryParam(req, "sortField", "name")
|
||||
)
|
||||
|
||||
must := IfaceMap{
|
||||
"match_all": IfaceMap{},
|
||||
}
|
||||
|
||||
if clearSearch := strings.TrimSpace(search); clearSearch != "" {
|
||||
clearSearch = strings.ReplaceAll(clearSearch, " ", "* *")
|
||||
must = IfaceMap{
|
||||
"query_string": IfaceMap{
|
||||
"default_field": "email_account.name",
|
||||
"default_operator": "AND",
|
||||
"query": fmt.Sprintf(`*%s*`, clearSearch),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
sortQueryMap := IfaceMap{ "name": IfaceMap{ "email_account.name.keyword": sortDirection } }
|
||||
var sort interface{}
|
||||
if sortQuery, ok := sortQueryMap[sortField]; ok {
|
||||
sort = sortQuery
|
||||
}
|
||||
reqBody := IfaceMap{
|
||||
"from": from,
|
||||
"size": size,
|
||||
"sort": sort,
|
||||
"query": IfaceMap{
|
||||
"bool": IfaceMap{
|
||||
"must": must,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_accounts/_search", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodPost, nil, reqBody)
|
||||
//TODO to handle api error in doRequest function
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
totalEmailAccounts := queryValue(resBody, "hits.total.value", 0)
|
||||
rawHits := queryValue(resBody, "hits.hits", []interface{}{})
|
||||
emailAccounts := []IfaceMap{}
|
||||
|
||||
if rh, ok := rawHits.([]interface{}); ok {
|
||||
for _, hit := range rh {
|
||||
if emailAccount, ok := hit.(map[string]interface{}); ok {
|
||||
newItem := IfaceMap{}
|
||||
newItem["id"] = queryValue(emailAccount, "_id", "")
|
||||
source := queryValue(emailAccount, "_source", nil)
|
||||
if ms, ok := source.(map[string]interface{}); ok {
|
||||
assignTo(newItem, ms)
|
||||
}
|
||||
newItem["ifSeqNo"] = queryValue(emailAccount, "_seq_no", 0)
|
||||
newItem["ifPrimaryTerm"] = queryValue(emailAccount, "_primary_term", 0)
|
||||
emailAccounts = append(emailAccounts, newItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"emailAccounts": emailAccounts,
|
||||
"totalEmailAccounts": totalEmailAccounts,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func GetEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
emailAccountId := ps.ByName("emailAccountId")
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_accounts/%s", conf.Endpoint, API_PREFIX, emailAccountId)
|
||||
res, err := doRequest(reqUrl, http.MethodGet,nil, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": queryValue(resBody, "email_account", nil),
|
||||
"ifSeqNo": queryValue(resBody, "_seq_no", 0),
|
||||
"ifPrimaryTerm": queryValue(resBody, "_primary_term", 0),
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --- email group
|
||||
|
||||
func CreateEmailGroup(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_groups", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodPost, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func UpdateEmailGroup(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
emailGroupId := ps.ByName("emailGroupId")
|
||||
var (
|
||||
ifSeqNo = getQueryParam(req, "ifSeqNo")
|
||||
ifPrimaryTerm = getQueryParam(req, "ifPrimaryTerm")
|
||||
)
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_groups/%s", conf.Endpoint, API_PREFIX, emailGroupId)
|
||||
res, err := doRequest(reqUrl, http.MethodPut, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
"if_seq_no": ifSeqNo,
|
||||
"if_primary_term": ifPrimaryTerm,
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"id": queryValue(resBody, "_id", ""),
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func DeleteEmailGroup(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
emailGroupId := ps.ByName("emailGroupId")
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_groups/%s", conf.Endpoint, API_PREFIX, emailGroupId)
|
||||
res, err := doRequest(reqUrl, http.MethodDelete, nil, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
resultIfce := queryValue(resBody, "result", "")
|
||||
var isOk = false
|
||||
if result, ok := resultIfce.(string); ok && result == "deleted" {
|
||||
isOk = true
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": isOk,
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func GetEmailGroups(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
var (
|
||||
from = getQueryParam(req, "from", "0")
|
||||
size = getQueryParam(req, "size", "20")
|
||||
search = getQueryParam(req, "search", "")
|
||||
sortDirection = getQueryParam(req, "sortDirection", "desc")
|
||||
sortField = getQueryParam(req, "sortField", "name")
|
||||
)
|
||||
|
||||
must := IfaceMap{
|
||||
"match_all": IfaceMap{},
|
||||
}
|
||||
|
||||
if clearSearch := strings.TrimSpace(search); clearSearch != "" {
|
||||
clearSearch = strings.ReplaceAll(clearSearch, " ", "* *")
|
||||
must = IfaceMap{
|
||||
"query_string": IfaceMap{
|
||||
"default_field": "email_group.name",
|
||||
"default_operator": "AND",
|
||||
"query": fmt.Sprintf(`*%s*`, clearSearch),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
sortQueryMap := IfaceMap{ "name": IfaceMap{ "email_group.name.keyword": sortDirection } }
|
||||
var sort interface{}
|
||||
if sortQuery, ok := sortQueryMap[sortField]; ok {
|
||||
sort = sortQuery
|
||||
}
|
||||
reqBody := IfaceMap{
|
||||
"from": from,
|
||||
"size": size,
|
||||
"sort": sort,
|
||||
"query": IfaceMap{
|
||||
"bool": IfaceMap{
|
||||
"must": must,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_groups/_search", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodPost, nil, reqBody)
|
||||
//TODO to handle api error in doRequest function
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
totalEmailGroups := queryValue(resBody, "hits.total.value", 0)
|
||||
rawHits := queryValue(resBody, "hits.hits", []interface{}{})
|
||||
emailGroups := []IfaceMap{}
|
||||
|
||||
if rh, ok := rawHits.([]interface{}); ok {
|
||||
for _, hit := range rh {
|
||||
if emailGroup, ok := hit.(map[string]interface{}); ok {
|
||||
newItem := IfaceMap{}
|
||||
newItem["id"] = queryValue(emailGroup, "_id", "")
|
||||
source := queryValue(emailGroup, "_source", nil)
|
||||
if ms, ok := source.(map[string]interface{}); ok {
|
||||
assignTo(newItem, ms)
|
||||
}
|
||||
newItem["ifSeqNo"] = queryValue(emailGroup, "seq_no", 0)
|
||||
newItem["ifPrimaryTerm"] = queryValue(emailGroup, "primary_term", 0)
|
||||
emailGroups = append(emailGroups, newItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"emailGroups": emailGroups,
|
||||
"totalEmailGroups": totalEmailGroups,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"infini.sh/framework/core/elastic"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SearchBody struct {
|
||||
|
@ -28,7 +29,7 @@ func Search(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
|||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
reqUrl := conf.Endpoint +"/_opendistro/_alerting/monitors/_search"
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors/_search", conf.Endpoint, API_PREFIX)
|
||||
params := map[string]string{
|
||||
"index": body.Index,
|
||||
}
|
||||
|
@ -47,10 +48,8 @@ func Search(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
|||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"body": IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
},
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
@ -90,10 +89,8 @@ func GetIndices(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"body": IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
},
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
|
@ -137,10 +134,8 @@ func GetAliases(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"body": IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
},
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
|
@ -153,14 +148,14 @@ func GetMappings(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
}
|
||||
|
||||
var body = struct{
|
||||
Index string `json:"index"`
|
||||
Index []string `json:"index"`
|
||||
}{}
|
||||
err := decodeJSON(req.Body, &body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
reqUrl := fmt.Sprintf("%s/%s/_mapping", conf.Endpoint, body.Index)
|
||||
reqUrl := fmt.Sprintf("%s/%s/_mapping", conf.Endpoint, strings.Join(body.Index, ","))
|
||||
res, err := doRequest(reqUrl, http.MethodGet, nil, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
|
@ -175,10 +170,8 @@ func GetMappings(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"body": IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
},
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
|
@ -209,9 +202,38 @@ func GetPlugins(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"body": IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
},
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func GetSettings(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
// /_cluster/settings?include_defaults=true
|
||||
reqUrl := fmt.Sprintf("%s/_cluster/settings", conf.Endpoint)
|
||||
res, err := doRequest(reqUrl, http.MethodGet, map[string]string{
|
||||
"include_defaults": "true",
|
||||
}, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
|
@ -6,10 +6,18 @@ import (
|
|||
httprouter "infini.sh/framework/core/api/router"
|
||||
"infini.sh/framework/core/elastic"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
|
@ -19,7 +27,7 @@ func GetMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
|
||||
mid := ps.ByName("monitorID")
|
||||
// /_opendistro/_alerting/monitors/uiSjqXsBHT9Hsiy5Dq6g
|
||||
reqUrl := fmt.Sprintf("%s/_opendistro/_alerting/monitors/%s", conf.Endpoint, mid)
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors/%s", conf.Endpoint, API_PREFIX, mid)
|
||||
res, err := doRequest(reqUrl, http.MethodGet, nil, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
|
@ -35,29 +43,26 @@ func GetMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
|
||||
if _, ok := resBody["monitor"]; !ok {
|
||||
writeJSON(w, IfaceMap{
|
||||
"body": IfaceMap{
|
||||
"ok": false,
|
||||
},
|
||||
}, http.StatusOK)
|
||||
return
|
||||
}
|
||||
///_opendistro/_alerting/monitors/_search?index=.opendistro-alerting-alert*
|
||||
|
||||
queryDSL := ` {
|
||||
"size": 0,
|
||||
"query"": {
|
||||
"query": {
|
||||
"bool": {
|
||||
"must": {
|
||||
"term"": {
|
||||
"monitor_id": "%s",
|
||||
},
|
||||
},
|
||||
},
|
||||
"term": {
|
||||
"monitor_id": "%s"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"aggs": {
|
||||
"active_count": {
|
||||
"terms": {
|
||||
"field": "state",
|
||||
"field": "state"
|
||||
}
|
||||
},
|
||||
"24_hour_count": {
|
||||
|
@ -69,9 +74,9 @@ func GetMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
}
|
||||
}`
|
||||
queryDSL = fmt.Sprintf(queryDSL, id)
|
||||
reqUrl = fmt.Sprintf("%s/_opendistro/_alerting/monitors/_search", conf.Endpoint)
|
||||
reqUrl = fmt.Sprintf("%s/%s/_alerting/monitors/_search", conf.Endpoint, API_PREFIX)
|
||||
res, err = doRequest(reqUrl, http.MethodPost, map[string]string{
|
||||
"index": ".opendistro-alerting-alert*",
|
||||
"index": INDEX_ALL_ALERTS,
|
||||
}, queryDSL)
|
||||
|
||||
if err != nil {
|
||||
|
@ -85,34 +90,400 @@ func GetMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params)
|
|||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//dayCount := queryValue(searchResBody, "aggregations.24_hour_count.buckets.0.doc_count", 0)
|
||||
//activeBuckets := queryValue(searchResBody, "aggregations.active_count.buckets",[]interface{}{})
|
||||
dayCount := queryValue(searchResBody, "aggregations.24_hour_count.buckets.0.doc_count", 0)
|
||||
activeBuckets := queryValue(searchResBody, "aggregations.active_count.buckets",[]interface{}{})
|
||||
activeCount := 0
|
||||
if ab, ok := activeBuckets.([]IfaceMap); ok {
|
||||
for _, curr := range ab {
|
||||
if curr["key"].(string) == "ACTIVE" {
|
||||
activeCount = int(curr["doc_count"].(float64))
|
||||
}
|
||||
}
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"body": IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
},
|
||||
"ok": true,
|
||||
"resp": resBody["monitor"],
|
||||
"activeCount": activeCount,
|
||||
"dayCount": dayCount,
|
||||
"version": queryValue(resBody, "_version", nil),
|
||||
"ifSeqNo": queryValue(resBody, "_seq_no", nil),
|
||||
"ifPrimaryTerm": queryValue(resBody, "_primary_term", nil),
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func queryValue(obj map[string]interface{}, key string, defaultValue interface{}) interface{} {
|
||||
if key == "" {
|
||||
return obj
|
||||
}
|
||||
idx := strings.Index(key, ".")
|
||||
if idx == -1 {
|
||||
if v, ok := obj[key]; ok {
|
||||
return v
|
||||
func GetMonitors(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
debug.PrintStack()
|
||||
}
|
||||
return defaultValue
|
||||
}()
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
var (
|
||||
from = getQueryParam(req, "from")
|
||||
size = getQueryParam(req, "size")
|
||||
search = getQueryParam(req, "search")
|
||||
sortDirection = getQueryParam(req, "sortDirection")
|
||||
sortField = getQueryParam(req, "sortField")
|
||||
state = getQueryParam(req, "state")
|
||||
must = IfaceMap{ "match_all": IfaceMap{} }
|
||||
)
|
||||
if clearSearch := strings.TrimSpace(search); clearSearch != "" {
|
||||
clearSearch = strings.ReplaceAll(clearSearch, " ", "* *")
|
||||
must = IfaceMap{
|
||||
"query_string": IfaceMap{
|
||||
"default_field": "monitor.name",
|
||||
"default_operator": "AND",
|
||||
"query": fmt.Sprintf("*%s*", clearSearch),
|
||||
},
|
||||
}
|
||||
}
|
||||
var filter = []IfaceMap{
|
||||
IfaceMap{ "term": IfaceMap{ "monitor.type": "monitor" }},
|
||||
}
|
||||
if state != "all" {
|
||||
filter = append(filter, IfaceMap{
|
||||
"term": IfaceMap{ "monitor.enabled": state == "enabled" },
|
||||
})
|
||||
}
|
||||
var monitorSorts = IfaceMap{ "name": "monitor.name.keyword" }
|
||||
sortPageData := IfaceMap{
|
||||
"size": 1000,
|
||||
"from": 0,
|
||||
}
|
||||
var (
|
||||
intSize int
|
||||
intFrom int
|
||||
)
|
||||
if msort, ok := monitorSorts[sortField]; ok {
|
||||
sortPageData["sort"] = []IfaceMap{
|
||||
{ msort.(string): sortDirection },
|
||||
}
|
||||
intSize, _ = strconv.Atoi(size)
|
||||
if intSize < 0 {
|
||||
intSize = 1000
|
||||
}
|
||||
sortPageData["size"] = intSize
|
||||
intFrom, _ = strconv.Atoi(from)
|
||||
if intFrom < 0 {
|
||||
intFrom = 0
|
||||
}
|
||||
sortPageData["from"] = intFrom
|
||||
}
|
||||
var params = IfaceMap{
|
||||
"seq_no_primary_term": true,
|
||||
"version": true,
|
||||
"query": IfaceMap{
|
||||
"bool": IfaceMap{
|
||||
"filter": filter,
|
||||
"must": must,
|
||||
},
|
||||
},
|
||||
}
|
||||
assignTo(params, sortPageData)
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors/_search", conf.Endpoint, API_PREFIX )
|
||||
res, err := doRequest(reqUrl, http.MethodPost, nil, params)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
ckey := key[0:idx]
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if v, ok := obj[ckey]; ok {
|
||||
if vmap, ok := v.(map[string]interface{}); ok {
|
||||
return queryValue(vmap, key[idx+1:], defaultValue)
|
||||
totalMonitors := queryValue(resBody, "hits.total.value", 0)
|
||||
monitorMap:= map[string]IfaceMap{}
|
||||
var hits = queryValue(resBody, "hits.hits", []IfaceMap{})
|
||||
monitorIDs := []interface{}{}
|
||||
if hitsArr, ok := hits.([]interface{}); ok {
|
||||
for _, hitIface := range hitsArr {
|
||||
if hit, ok := hitIface.(map[string]interface{}); ok {
|
||||
id := queryValue(hit, "_id", "")
|
||||
monitorIDs = append(monitorIDs, id)
|
||||
monitor := queryValue(hit, "_source", IfaceMap{}).(map[string]interface{})
|
||||
monitorMap[id.(string)] = IfaceMap{
|
||||
"id": id,
|
||||
"version": queryValue(hit, "_version", ""),
|
||||
"ifSeqNo": queryValue(hit, "_seq_no", false),
|
||||
"ifPrimaryTerm": queryValue(hit, "_primary_term", false),
|
||||
"name": queryValue(monitor, "name", ""),
|
||||
"enabled": queryValue(monitor, "enabled", false),
|
||||
"monitor": monitor,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
|
||||
aggsOrderData := IfaceMap{}
|
||||
aggsSorts := IfaceMap{
|
||||
"active": "active",
|
||||
"acknowledged": "acknowledged",
|
||||
"errors": "errors",
|
||||
"ignored": "ignored",
|
||||
"lastNotificationTime": "last_notification_time",
|
||||
}
|
||||
|
||||
if sortF, ok := aggsSorts[sortField]; ok {
|
||||
aggsOrderData["order"] = IfaceMap{ sortF.(string): sortDirection }
|
||||
}
|
||||
var queryParams = map[string]string{
|
||||
"index": INDEX_ALL_ALERTS,
|
||||
}
|
||||
var termsMap = IfaceMap{
|
||||
"field": "monitor_id",
|
||||
"size": intFrom + intSize,
|
||||
}
|
||||
assignTo(termsMap, aggsOrderData)
|
||||
var aggsParams = IfaceMap{
|
||||
"size": 0,
|
||||
"query": IfaceMap{ "terms": IfaceMap{ "monitor_id": monitorIDs } },
|
||||
"aggregations": IfaceMap{
|
||||
"uniq_monitor_ids": IfaceMap{
|
||||
"terms": termsMap,
|
||||
"aggregations": IfaceMap{
|
||||
"active": IfaceMap{ "filter": IfaceMap{ "term": IfaceMap{ "state": "ACTIVE" } } },
|
||||
"acknowledged": IfaceMap{ "filter": IfaceMap{ "term": IfaceMap{ "state": "ACKNOWLEDGED" } } },
|
||||
"errors": IfaceMap{ "filter": IfaceMap{ "term": IfaceMap{ "state": "ERROR" } } },
|
||||
"ignored": IfaceMap{
|
||||
"filter": IfaceMap{
|
||||
"bool": IfaceMap{
|
||||
"filter": IfaceMap{ "term": IfaceMap{ "state": "COMPLETED" } },
|
||||
"must_not": IfaceMap{ "exists": IfaceMap{ "field": "acknowledged_time" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
"last_notification_time": IfaceMap{ "max": IfaceMap{ "field": "last_notification_time" } },
|
||||
"latest_alert": IfaceMap{
|
||||
"top_hits": IfaceMap{
|
||||
"size": 1,
|
||||
"sort": []IfaceMap{ { "start_time": IfaceMap{ "order": "desc" }} },
|
||||
"_source": IfaceMap{
|
||||
"includes": []string{"last_notification_time", "trigger_name"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
reqUrl = fmt.Sprintf("%s/%s/_alerting/monitors/_search", conf.Endpoint, API_PREFIX)
|
||||
searchRes, err := doRequest(reqUrl, http.MethodPost, queryParams, aggsParams)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var searchResBody = IfaceMap{}
|
||||
err = decodeJSON(searchRes.Body, &searchResBody)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
buckets := queryValue(searchResBody, "aggregations.uniq_monitor_ids.buckets",[]IfaceMap{})
|
||||
usedMonitors := []IfaceMap{}
|
||||
if bks, ok := buckets.([]interface{}); ok {
|
||||
for _, bk := range bks {
|
||||
if bk, ok := bk.(map[string]interface{}); ok {
|
||||
id := queryValue(bk, "key", "")
|
||||
monitor := monitorMap[id.(string)]
|
||||
monitor["lastNotificationTime"] = queryValue(bk, "last_notification_time.value", "")
|
||||
monitor["ignored"] = queryValue(bk, "ignored.doc_count", 0)
|
||||
alertHits := queryValue(bk, "latest_alert.hits.hits", nil)
|
||||
var latestAlert interface{}
|
||||
if hits, ok := alertHits.([]interface{}); ok && len(hits) > 0 {
|
||||
if hitMap, ok := hits[0].(map[string]interface{}); ok {
|
||||
latestAlert = queryValue(hitMap, "_source.trigger_name", nil)
|
||||
}
|
||||
}
|
||||
monitor["latestAlert"] = latestAlert
|
||||
monitor["active"] = queryValue(bk, "active.doc_count", 0)
|
||||
monitor["errors"] = queryValue(bk, "errors.doc_count", 0)
|
||||
monitor["currentTime"] = time.Now().UnixNano() / 1e6
|
||||
usedMonitors = append(usedMonitors, monitor)
|
||||
delete(monitorMap, id.(string))
|
||||
}
|
||||
}
|
||||
}
|
||||
unusedMonitors := []IfaceMap{}
|
||||
|
||||
for _, m := range monitorMap {
|
||||
assignTo(m, IfaceMap{
|
||||
"lastNotificationTime": nil,
|
||||
"ignored": 0,
|
||||
"active": 0,
|
||||
"acknowledged": 0,
|
||||
"errors": 0,
|
||||
"latestAlert": "--",
|
||||
"currentTime": time.Now().UnixNano()/1e6,
|
||||
})
|
||||
unusedMonitors = append(unusedMonitors,m)
|
||||
}
|
||||
|
||||
results := append(usedMonitors, unusedMonitors...)
|
||||
|
||||
if _, ok := monitorSorts[sortField]; !ok {
|
||||
results = results[intFrom: intFrom + intSize]
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"monitors": results,
|
||||
"totalMonitors": totalMonitors,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
|
||||
func CreateMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodPost, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func DeleteMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
monitorId := ps.ByName("monitorID")
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors/%s", conf.Endpoint, API_PREFIX, monitorId)
|
||||
res, err := doRequest(reqUrl, http.MethodDelete, nil, nil)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
resultIfce := queryValue(resBody, "result", "")
|
||||
var isOk = false
|
||||
if result, ok := resultIfce.(string); ok && result == "deleted" {
|
||||
isOk = true
|
||||
}
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": isOk,
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func UpdateMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
|
||||
monitorId := ps.ByName("monitorID")
|
||||
var (
|
||||
ifSeqNo = getQueryParam(req, "ifSeqNo")
|
||||
ifPrimaryTerm = getQueryParam(req, "ifPrimaryTerm")
|
||||
)
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors/%s", conf.Endpoint, API_PREFIX, monitorId)
|
||||
res, err := doRequest(reqUrl, http.MethodPut, map[string]string{
|
||||
"refresh": "wait_for",
|
||||
"if_seq_no": ifSeqNo,
|
||||
"if_primary_term": ifPrimaryTerm,
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"version": queryValue(resBody, "_version", ""),
|
||||
"id": queryValue(resBody, "_id", ""),
|
||||
}, http.StatusOK)
|
||||
|
||||
}
|
||||
|
||||
func ExecuteMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
id := ps.ByName("id")
|
||||
conf := elastic.GetConfig(id)
|
||||
if conf == nil {
|
||||
writeError(w, errors.New("cluster not found"))
|
||||
return
|
||||
}
|
||||
var (
|
||||
dryrun = getQueryParam(req, "dryrun", "true")
|
||||
)
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/%s/_alerting/monitors/_execute", conf.Endpoint, API_PREFIX)
|
||||
res, err := doRequest(reqUrl, http.MethodPost, map[string]string{
|
||||
"dryrun": dryrun,
|
||||
}, req.Body)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var resBody = IfaceMap{}
|
||||
err = decodeJSON(res.Body, &resBody)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
//TODO error handle: check whether resBody has contains field error
|
||||
|
||||
writeJSON(w, IfaceMap{
|
||||
"ok": true,
|
||||
"resp": resBody,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
"rxjs": "^7.2.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"use-query-params": "^1.2.3",
|
||||
"uuidv4": "^6.2.12"
|
||||
"uuid-v4": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"antd-pro-merge-less": "^0.1.0",
|
||||
|
|
|
@ -129,7 +129,7 @@ export async function getBreadcrumb(route, routeState, httpClient) {
|
|||
// TODO::Everything else is considered as monitor, we should break this.
|
||||
let monitorName = base;
|
||||
try {
|
||||
const response = await httpClient.get(`../api/alerting/monitors/${base}`);
|
||||
const response = await httpClient.get(`/alerting/monitors/${base}`);
|
||||
if (response.ok) {
|
||||
monitorName = response.resp.name;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ const httpClient = new Fetch({
|
|||
get: () => '',
|
||||
prepend: (url) => url,
|
||||
remove: (url) => url,
|
||||
serverBasePath: '/elasticsearch',
|
||||
serverBasePath: '',
|
||||
}
|
||||
});
|
||||
const notifications = {
|
||||
|
@ -23,6 +23,11 @@ const notifications = {
|
|||
description: text,
|
||||
duration: toastLifeTimeMs/1000,
|
||||
})
|
||||
},
|
||||
addSuccess: (message) => {
|
||||
notification.success({
|
||||
description: message,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +37,8 @@ const AlertingUI = (props)=>{
|
|||
return null;
|
||||
}
|
||||
useMemo(()=>{
|
||||
httpClient.getServerBasePath = ()=>{
|
||||
return '/api/elasticsearch/'+ props.selectedCluster.id;
|
||||
httpClient.params.basePath.prepend = (url)=>{
|
||||
return '/elasticsearch/'+ props.selectedCluster.id + url;
|
||||
}
|
||||
}, [props.selectedCluster]);
|
||||
const isDarkMode = false;
|
||||
|
|
|
@ -56,7 +56,7 @@ class AnomalyDetectorData extends React.Component {
|
|||
preview: this.props.preview,
|
||||
};
|
||||
try {
|
||||
const response = await httpClient.get(`../api/alerting/detectors/${detectorId}/results`, {
|
||||
const response = await httpClient.get(`/alerting/detectors/${detectorId}/results`, {
|
||||
query: requestParams,
|
||||
});
|
||||
if (response.ok) {
|
||||
|
|
|
@ -38,7 +38,7 @@ class AnomalyDetectors extends React.Component {
|
|||
async searchDetectors() {
|
||||
const { http: httpClient, notifications } = this.context;
|
||||
try {
|
||||
const response = await httpClient.post('../api/alerting/detectors/_search');
|
||||
const response = await httpClient.post('/alerting/detectors/_search');
|
||||
if (response.ok) {
|
||||
const detectorOptions = response.detectors
|
||||
.filter((detector) => detector.detectionDateRange === undefined)
|
||||
|
|
|
@ -76,7 +76,7 @@ export default class CreateMonitor extends Component {
|
|||
async onCreate(monitor, { setSubmitting, setErrors }) {
|
||||
const { httpClient, notifications } = this.props;
|
||||
try {
|
||||
const resp = await httpClient.post('../api/alerting/monitors', {
|
||||
const resp = await httpClient.post('/alerting/monitors', {
|
||||
body: JSON.stringify(monitor),
|
||||
});
|
||||
setSubmitting(false);
|
||||
|
|
|
@ -249,7 +249,7 @@ describe('CreateMonitor', () => {
|
|||
);
|
||||
wrapper.instance().onCreate(monitor, formikBag);
|
||||
expect(httpClientMock.post).toHaveBeenCalledTimes(1);
|
||||
expect(httpClientMock.post).toHaveBeenCalledWith('../api/alerting/monitors', {
|
||||
expect(httpClientMock.post).toHaveBeenCalledWith('/alerting/monitors', {
|
||||
body: JSON.stringify(monitor),
|
||||
});
|
||||
});
|
||||
|
|
|
@ -126,7 +126,7 @@ class DefineMonitor extends Component {
|
|||
async getPlugins() {
|
||||
const { httpClient } = this.props;
|
||||
try {
|
||||
const pluginsResponse = await httpClient.get('../api/alerting/_plugins');
|
||||
const pluginsResponse = await httpClient.get('/alerting/_plugins');
|
||||
if (pluginsResponse.ok) {
|
||||
this.setState({ plugins: pluginsResponse.resp.map((plugin) => plugin.component) });
|
||||
} else {
|
||||
|
@ -186,7 +186,7 @@ class DefineMonitor extends Component {
|
|||
_.set(monitor, 'name', 'TEMP_MONITOR');
|
||||
_.set(monitor, 'triggers', []);
|
||||
_.set(monitor, 'inputs[0].search', searchRequest);
|
||||
return httpClient.post('../api/alerting/monitors/_execute', {
|
||||
return httpClient.post('/alerting/monitors/_execute', {
|
||||
body: JSON.stringify(monitor),
|
||||
});
|
||||
});
|
||||
|
@ -231,7 +231,7 @@ class DefineMonitor extends Component {
|
|||
}
|
||||
|
||||
try {
|
||||
const response = await this.props.httpClient.post('../api/alerting/_mappings', {
|
||||
const response = await this.props.httpClient.post('/alerting/_mappings', {
|
||||
body: JSON.stringify({ index }),
|
||||
});
|
||||
if (response.ok) {
|
||||
|
|
|
@ -120,7 +120,7 @@ class MonitorIndex extends React.Component {
|
|||
return [];
|
||||
}
|
||||
try {
|
||||
const response = await this.props.httpClient.post('../api/alerting/_indices', {
|
||||
const response = await this.props.httpClient.post('/alerting/_indices', {
|
||||
body: JSON.stringify({ index }),
|
||||
});
|
||||
if (response.ok) {
|
||||
|
@ -150,7 +150,7 @@ class MonitorIndex extends React.Component {
|
|||
}
|
||||
|
||||
try {
|
||||
const response = await this.props.httpClient.post('../api/alerting/_aliases', {
|
||||
const response = await this.props.httpClient.post('/alerting/_aliases', {
|
||||
body: JSON.stringify({ alias }),
|
||||
});
|
||||
if (response.ok) {
|
||||
|
|
|
@ -62,7 +62,7 @@ class ConfigureActions extends React.Component {
|
|||
return destination.type;
|
||||
};
|
||||
try {
|
||||
const response = await httpClient.get('../api/alerting/destinations', {
|
||||
const response = await httpClient.get('/alerting/destinations', {
|
||||
query: { search: searchText, size: MAX_QUERY_RESULT_SIZE },
|
||||
});
|
||||
if (response.ok) {
|
||||
|
@ -97,7 +97,7 @@ class ConfigureActions extends React.Component {
|
|||
const condition = { script: { lang: 'painless', source: 'return true' } };
|
||||
const testMonitor = { ...monitor, triggers: [{ ...trigger, actions: [action], condition }] };
|
||||
try {
|
||||
const response = await httpClient.post('../api/alerting/monitors/_execute', {
|
||||
const response = await httpClient.post('/alerting/monitors/_execute', {
|
||||
query: { dryrun: false },
|
||||
body: JSON.stringify(testMonitor),
|
||||
});
|
||||
|
|
|
@ -128,7 +128,7 @@ export default class CreateTrigger extends Component {
|
|||
_.set(monitorToExecute, 'inputs[0].search', searchRequest);
|
||||
}
|
||||
httpClient
|
||||
.post('../api/alerting/monitors/_execute', { body: JSON.stringify(monitorToExecute) })
|
||||
.post('/alerting/monitors/_execute', { body: JSON.stringify(monitorToExecute) })
|
||||
.then((resp) => {
|
||||
if (resp.ok) {
|
||||
this.setState({ executeResponse: resp.resp });
|
||||
|
|
|
@ -185,7 +185,7 @@ export default class Dashboard extends Component {
|
|||
location.search;
|
||||
const { httpClient, history, notifications } = this.props;
|
||||
history.replace({ ...this.props.location, search: queryParamsString });
|
||||
httpClient.get(httpClient.getServerBasePath()+'/alerting/alerts', { query: params }).then((resp) => {
|
||||
httpClient.get('/alerting/alerts', { query: params }).then((resp) => {
|
||||
if (resp.ok) {
|
||||
const { alerts, totalAlerts } = resp;
|
||||
this.setState({
|
||||
|
@ -218,7 +218,7 @@ export default class Dashboard extends Component {
|
|||
|
||||
const promises = Object.entries(monitorAlerts).map(([monitorId, alerts]) =>
|
||||
httpClient
|
||||
.post(`../api/alerting/monitors/${monitorId}/_acknowledge/alerts`, {
|
||||
.post(`/alerting/monitors/${monitorId}/_acknowledge/alerts`, {
|
||||
body: JSON.stringify({ alerts }),
|
||||
})
|
||||
.then((resp) => {
|
||||
|
|
|
@ -52,7 +52,7 @@ export const columns = [
|
|||
truncateText: true,
|
||||
textOnly: true,
|
||||
render: (name, alert) => (
|
||||
<EuiLink href={`${PLUGIN_NAME}#/monitors/${alert.monitor_id}`}>{name}</EuiLink>
|
||||
<EuiLink href={`#/${PLUGIN_NAME}/monitors/${alert.monitor_id}`}>{name}</EuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
|
|
|
@ -89,7 +89,7 @@ class CreateDestination extends React.Component {
|
|||
getDestination = async (destinationId) => {
|
||||
const { httpClient, history, notifications } = this.props;
|
||||
try {
|
||||
const resp = await httpClient.get(`../api/alerting/destinations/${destinationId}`);
|
||||
const resp = await httpClient.get(`/alerting/destinations/${destinationId}`);
|
||||
if (resp.ok) {
|
||||
const ifSeqNo = _.get(resp, 'ifSeqNo');
|
||||
const ifPrimaryTerm = _.get(resp, 'ifPrimaryTerm');
|
||||
|
@ -118,7 +118,7 @@ class CreateDestination extends React.Component {
|
|||
} = this.props;
|
||||
const { ifSeqNo, ifPrimaryTerm } = this.state;
|
||||
try {
|
||||
const resp = await httpClient.put(`../api/alerting/destinations/${destinationId}`, {
|
||||
const resp = await httpClient.put(`/alerting/destinations/${destinationId}`, {
|
||||
query: { ifSeqNo, ifPrimaryTerm },
|
||||
body: JSON.stringify(requestData),
|
||||
});
|
||||
|
@ -139,7 +139,7 @@ class CreateDestination extends React.Component {
|
|||
handleCreate = async (requestData, { setSubmitting }) => {
|
||||
const { httpClient, history, notifications } = this.props;
|
||||
try {
|
||||
const resp = await httpClient.post('../api/alerting/destinations', {
|
||||
const resp = await httpClient.post('/alerting/destinations', {
|
||||
body: JSON.stringify(requestData),
|
||||
});
|
||||
setSubmitting(false);
|
||||
|
|
|
@ -17,7 +17,7 @@ import { MAX_QUERY_RESULT_SIZE } from '../../../../../../utils/constants';
|
|||
|
||||
export default async function getEmailGroups(httpClient, searchText = '') {
|
||||
try {
|
||||
const response = await httpClient.get('../api/alerting/destinations/email_groups', {
|
||||
const response = await httpClient.get('/alerting/destinations/email_groups', {
|
||||
query: { search: searchText, size: MAX_QUERY_RESULT_SIZE },
|
||||
});
|
||||
if (response.ok) {
|
||||
|
|
|
@ -17,7 +17,7 @@ import { MAX_QUERY_RESULT_SIZE } from '../../../../../../utils/constants';
|
|||
|
||||
export default async function getSenders(httpClient, searchText = '') {
|
||||
try {
|
||||
const response = await httpClient.get('../api/alerting/destinations/email_accounts', {
|
||||
const response = await httpClient.get('/alerting/destinations/email_accounts', {
|
||||
query: { search: searchText, size: MAX_QUERY_RESULT_SIZE },
|
||||
});
|
||||
if (response.ok) {
|
||||
|
|
|
@ -119,7 +119,7 @@ export default class ManageEmailGroups extends React.Component {
|
|||
emails: emailGroup.emails.map((email) => ({ email: email.label })),
|
||||
};
|
||||
try {
|
||||
const response = await httpClient.post(`../api/alerting/destinations/email_groups`, {
|
||||
const response = await httpClient.post(`/alerting/destinations/email_groups`, {
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (!response.ok) {
|
||||
|
@ -147,7 +147,7 @@ export default class ManageEmailGroups extends React.Component {
|
|||
emails: updatedEmailGroup.emails.map((email) => ({ email: email.label })),
|
||||
};
|
||||
try {
|
||||
const response = await httpClient.put(`../api/alerting/destinations/email_groups/${id}`, {
|
||||
const response = await httpClient.put(`/alerting/email_groups/${id}`, {
|
||||
query: { ifSeqNo, ifPrimaryTerm },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
@ -172,7 +172,7 @@ export default class ManageEmailGroups extends React.Component {
|
|||
const { httpClient, notifications } = this.props;
|
||||
const { id } = emailGroup;
|
||||
try {
|
||||
const response = await httpClient.delete(`../api/alerting/destinations/email_groups/${id}`);
|
||||
const response = await httpClient.delete(`/alerting/email_groups/${id}`);
|
||||
if (!response.ok) {
|
||||
this.setState({ failedEmailGroups: true });
|
||||
notifications.toasts.addDanger({
|
||||
|
|
|
@ -107,7 +107,7 @@ export default class ManageSenders extends React.Component {
|
|||
method: sender.method,
|
||||
};
|
||||
try {
|
||||
const response = await httpClient.post(`../api/alerting/destinations/email_accounts`, {
|
||||
const response = await httpClient.post(`/alerting/destinations/email_accounts`, {
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (!response.ok) {
|
||||
|
@ -138,7 +138,7 @@ export default class ManageSenders extends React.Component {
|
|||
method: updatedSender.method,
|
||||
};
|
||||
try {
|
||||
const response = await httpClient.put(`../api/alerting/destinations/email_accounts/${id}`, {
|
||||
const response = await httpClient.put(`/alerting/email_accounts/${id}`, {
|
||||
query: { ifSeqNo, ifPrimaryTerm },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
@ -163,7 +163,7 @@ export default class ManageSenders extends React.Component {
|
|||
const { httpClient, notifications } = this.props;
|
||||
const { id } = sender;
|
||||
try {
|
||||
const response = await httpClient.delete(`../api/alerting/destinations/email_accounts/${id}`);
|
||||
const response = await httpClient.delete(`/alerting/email_accounts/${id}`);
|
||||
if (!response.ok) {
|
||||
this.setState({ failedSenders: true });
|
||||
notifications.toasts.addDanger({
|
||||
|
|
|
@ -49,7 +49,7 @@ const customWebhookToFormik = ({
|
|||
|
||||
const getSender = async (httpClient, id) => {
|
||||
try {
|
||||
const response = await httpClient.get(`../api/alerting/destinations/email_accounts/${id}`);
|
||||
const response = await httpClient.get(`/alerting/email_accounts/${id}`);
|
||||
if (response.ok) {
|
||||
return response.resp;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ const getSender = async (httpClient, id) => {
|
|||
|
||||
const getEmailGroup = async (httpClient, id) => {
|
||||
try {
|
||||
const response = await httpClient.get(`../api/alerting/destinations/email_groups/${id}`);
|
||||
const response = await httpClient.get(`/alerting/destinations/email_groups/${id}`);
|
||||
if (response.ok) {
|
||||
return response.resp;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ export const validateDestinationName = (httpClient, destinationToEdit) => async
|
|||
index: INDEX.SCHEDULED_JOBS,
|
||||
query: { query: { term: { 'destination.name.keyword': value } } },
|
||||
};
|
||||
const response = await httpClient.post('../api/alerting/monitors/_search', {
|
||||
const response = await httpClient.post('/alerting/monitors/_search', {
|
||||
body: JSON.stringify(options),
|
||||
});
|
||||
if (_.get(response, 'resp.hits.total.value', 0)) {
|
||||
|
|
|
@ -119,7 +119,7 @@ class DestinationsList extends React.Component {
|
|||
query: isDeleteAllowedQuery(type, id),
|
||||
index: INDEX.SCHEDULED_JOBS,
|
||||
};
|
||||
const resp = await httpClient.post('../api/alerting/monitors/_search', {
|
||||
const resp = await httpClient.post('/alerting/monitors/_search', {
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
const total = _.get(resp, 'resp.hits.total.value');
|
||||
|
@ -151,7 +151,7 @@ class DestinationsList extends React.Component {
|
|||
const { id: destinationId } = this.state.destinationToDelete;
|
||||
const { httpClient, notifications } = this.props;
|
||||
try {
|
||||
const resp = await httpClient.delete(`../api/alerting/destinations/${destinationId}`);
|
||||
const resp = await httpClient.delete(`/alerting/destinations/${destinationId}`);
|
||||
if (resp.ok) {
|
||||
await this.getDestinations();
|
||||
} else {
|
||||
|
@ -214,7 +214,7 @@ class DestinationsList extends React.Component {
|
|||
// search: queryParms,
|
||||
// });
|
||||
try {
|
||||
const resp = await httpClient.get('../api/alerting/destinations', {
|
||||
const resp = await httpClient.get('/alerting/destinations', {
|
||||
query: { from, ...params },
|
||||
});
|
||||
if (resp.ok) {
|
||||
|
|
|
@ -19,7 +19,7 @@ import { backendErrorNotification } from '../../../utils/helpers';
|
|||
|
||||
export async function getAllowList(httpClient) {
|
||||
try {
|
||||
const response = await httpClient.get('../api/alerting/_settings');
|
||||
const response = await httpClient.get('/alerting/_settings');
|
||||
if (response.ok) {
|
||||
// Attempt to resolve the value of allow_list in the order of 'persistent, 'transient' and 'defaults' settings
|
||||
const { defaults, transient, persistent } = response.resp;
|
||||
|
|
|
@ -81,7 +81,7 @@ export default class MonitorDetails extends Component {
|
|||
getDetector = (id) => {
|
||||
const { httpClient, notifications } = this.props;
|
||||
httpClient
|
||||
.get(`../api/alerting/detectors/${id}`)
|
||||
.get(`/alerting/detectors/${id}`)
|
||||
.then((resp) => {
|
||||
const { ok, detector, version: detectorVersion, seqNo, primaryTerm } = resp;
|
||||
if (ok) {
|
||||
|
@ -101,7 +101,7 @@ export default class MonitorDetails extends Component {
|
|||
getMonitor = (id) => {
|
||||
const { httpClient } = this.props;
|
||||
httpClient
|
||||
.get(`../api/alerting/monitors/${id}`)
|
||||
.get(`/alerting/monitors/${id}`)
|
||||
.then((resp) => {
|
||||
const {
|
||||
ok,
|
||||
|
@ -148,7 +148,7 @@ export default class MonitorDetails extends Component {
|
|||
const { monitor, ifSeqNo, ifPrimaryTerm } = this.state;
|
||||
this.setState({ updating: true });
|
||||
return httpClient
|
||||
.put(`../api/alerting/monitors/${monitorId}`, {
|
||||
.put(`/alerting/monitors/${monitorId}`, {
|
||||
query: { ifSeqNo, ifPrimaryTerm },
|
||||
body: JSON.stringify({ ...monitor, ...update }),
|
||||
})
|
||||
|
|
|
@ -200,7 +200,7 @@ class MonitorHistory extends PureComponent {
|
|||
),
|
||||
index: INDEX.ALL_ALERTS,
|
||||
};
|
||||
const resp = await httpClient.post('../api/alerting/monitors/_search', {
|
||||
const resp = await httpClient.post('/alerting/monitors/_search', {
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
if (resp.ok) {
|
||||
|
@ -242,7 +242,7 @@ class MonitorHistory extends PureComponent {
|
|||
monitorIds: monitorId,
|
||||
};
|
||||
|
||||
const resp = await httpClient.get('../api/alerting/alerts', { query: params });
|
||||
const resp = await httpClient.get('/alerting/alerts', { query: params });
|
||||
var alerts;
|
||||
if (resp.ok) {
|
||||
alerts = resp.alerts;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import uuidv4 from 'uuidv4';
|
||||
import uuid from 'uuid-v4';
|
||||
import { EuiButton, EuiInMemoryTable } from '@elastic/eui';
|
||||
|
||||
import ContentPanel from '../../../../components/ContentPanel';
|
||||
|
@ -28,7 +28,7 @@ export default class Triggers extends Component {
|
|||
|
||||
this.state = {
|
||||
field: 'name',
|
||||
tableKey: uuidv4(),
|
||||
tableKey: uuid(),
|
||||
direction: 'asc',
|
||||
selectedItems: [],
|
||||
};
|
||||
|
@ -45,7 +45,7 @@ export default class Triggers extends Component {
|
|||
// which EuiInMemoryTable uses which causes items to not be updated correctly.
|
||||
// Whenever the monitor is updated we'll generate a new key for the table
|
||||
// which will cause the table component to remount
|
||||
this.setState({ tableKey: uuidv4() });
|
||||
this.setState({ tableKey: uuid() });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,8 +144,8 @@ export default class Monitors extends Component {
|
|||
const params = { from, size, search, sortField, sortDirection, state };
|
||||
const queryParamsString = queryString.stringify(params);
|
||||
const { httpClient, history } = this.props;
|
||||
history.replace({ ...this.props.location, search: queryParamsString });
|
||||
const response = await httpClient.get('../api/alerting/monitors', { query: params });
|
||||
//history.replace({ ...this.props.location, search: queryParamsString });
|
||||
const response = await httpClient.get('/alerting/monitors', { query: params });
|
||||
if (response.ok) {
|
||||
const { monitors, totalMonitors } = response;
|
||||
this.setState({ monitors, totalMonitors });
|
||||
|
@ -182,7 +182,7 @@ export default class Monitors extends Component {
|
|||
const { httpClient, notifications } = this.props;
|
||||
const { id, ifSeqNo, ifPrimaryTerm, monitor } = item;
|
||||
return httpClient
|
||||
.put(`../api/alerting/monitors/${id}`, {
|
||||
.put(`/alerting/monitors/${id}`, {
|
||||
query: { ifSeqNo, ifPrimaryTerm },
|
||||
body: JSON.stringify({ ...monitor, ...update }),
|
||||
})
|
||||
|
@ -199,7 +199,7 @@ export default class Monitors extends Component {
|
|||
const { httpClient, notifications } = this.props;
|
||||
const { id, version } = item;
|
||||
return httpClient
|
||||
.delete(`../api/alerting/monitors/${id}`, { query: { version } })
|
||||
.delete(`/alerting/monitors/${id}`, { query: { version } })
|
||||
.then((resp) => {
|
||||
if (!resp.ok) {
|
||||
backendErrorNotification(notifications, 'delete', 'monitor', resp.resp);
|
||||
|
@ -249,7 +249,7 @@ export default class Monitors extends Component {
|
|||
|
||||
const promises = Object.entries(monitorAlerts).map(([monitorId, alerts]) =>
|
||||
httpClient
|
||||
.post(`../api/alerting/monitors/${monitorId}/_acknowledge/alerts`, {
|
||||
.post(`/alerting/monitors/${monitorId}/_acknowledge/alerts`, {
|
||||
body: JSON.stringify({ alerts }),
|
||||
})
|
||||
.then((resp) => {
|
||||
|
@ -321,7 +321,7 @@ export default class Monitors extends Component {
|
|||
|
||||
const { httpClient, notifications } = this.props;
|
||||
|
||||
const response = await httpClient.get('../api/alerting/alerts', { query: params });
|
||||
const response = await httpClient.get('/alerting/alerts', { query: params });
|
||||
|
||||
if (response.ok) {
|
||||
const { alerts, totalAlerts } = response;
|
||||
|
|
|
@ -160,7 +160,7 @@ describe('Monitors', () => {
|
|||
|
||||
expect(updateMonitor).toHaveBeenCalled();
|
||||
expect(httpClientMock.put).toHaveBeenCalled();
|
||||
expect(httpClientMock.put).toHaveBeenCalledWith(`../api/alerting/monitors/random_id`, {
|
||||
expect(httpClientMock.put).toHaveBeenCalledWith(`/alerting/monitors/random_id`, {
|
||||
query: { ifSeqNo: 17, ifPrimaryTerm: 20 },
|
||||
body: JSON.stringify({ ...monitor, name: 'UNIQUE_NAME' }),
|
||||
});
|
||||
|
|
|
@ -34,7 +34,7 @@ export const columns = [
|
|||
truncateText: true,
|
||||
textOnly: true,
|
||||
// width: '150px',
|
||||
render: (name, item) => <EuiLink href={`${PLUGIN_NAME}#/monitors/${item.id}`}>{name}</EuiLink>,
|
||||
render: (name, item) => <EuiLink href={`#/${PLUGIN_NAME}/monitors/${item.id}`}>{name}</EuiLink>,
|
||||
},
|
||||
{
|
||||
field: 'user',
|
||||
|
|
|
@ -66,10 +66,10 @@ export const AD_PREVIEW_DAYS = 7;
|
|||
export const MAX_QUERY_RESULT_SIZE = 200;
|
||||
|
||||
|
||||
export const OPEN_DISTRO_PREFIX = '';
|
||||
export const OPEN_DISTRO_PREFIX = 'opendistro';
|
||||
|
||||
export const PLUGIN_NAME = `alerting`;
|
||||
export const INDEX_PREFIX = `alerting`;
|
||||
export const INDEX_PREFIX = `${OPEN_DISTRO_PREFIX}-alerting`;
|
||||
export const INDEX = {
|
||||
SCHEDULED_JOBS: `.${INDEX_PREFIX}-config`,
|
||||
ALERTS: `.${INDEX_PREFIX}-alerts`,
|
||||
|
|
|
@ -56,7 +56,7 @@ export const validateMonitorName = (httpClient, monitorToEdit) => async (value)
|
|||
index: INDEX.SCHEDULED_JOBS,
|
||||
query: { query: { term: { 'monitor.name.keyword': value } } },
|
||||
};
|
||||
const response = await httpClient.post('../api/alerting/monitors/_search', {
|
||||
const response = await httpClient.post('/alerting/monitors/_search', {
|
||||
body: JSON.stringify(options),
|
||||
});
|
||||
if (_.get(response, 'resp.hits.total.value', 0)) {
|
||||
|
|
Loading…
Reference in New Issue