modify alert bug

This commit is contained in:
silenceqi 2021-09-07 09:39:44 +08:00
parent 22c66b01df
commit 13ce75d197
17 changed files with 143 additions and 39 deletions

View File

@ -49,6 +49,7 @@ func Init(cfg *config.AppConfig) {
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.POST, "/elasticsearch/:id/alerting/_monitors/:monitorID/_acknowledge/alerts", alerting.AcknowledgeAlerts)
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)
@ -63,6 +64,7 @@ func Init(cfg *config.AppConfig) {
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)
ui.HandleUIMethod(api.GET, "/elasticsearch/:id/alerting/email_groups/:emailGroupId", alerting.GetEmailGroup)

View File

@ -39,7 +39,7 @@ func GetAlerts (w http.ResponseWriter, req *http.Request, ps httprouter.Params){
sortField = getQueryParam(req, "sortField", "start_time")
severityLevel = getQueryParam(req, "severityLevel", "ALL")
alertState = getQueryParam(req, "alertState", "ALL")
//monitorIds = getQueryParam(req, "monitorIds")
monitorIds = req.URL.Query()["monitorIds"]
params = map[string]string{
"startIndex": from,
"size": size,
@ -68,6 +68,9 @@ func GetAlerts (w http.ResponseWriter, req *http.Request, ps httprouter.Params){
params["sortOrder"] = sortDirection
params["missing"] = "_last"
}
if len(monitorIds) > 0{
params["monitorId"] = monitorIds[0]
}
if clearSearch := strings.TrimSpace(search); clearSearch != ""{
searches := strings.Split(clearSearch, " ")
@ -93,9 +96,10 @@ func GetAlerts (w http.ResponseWriter, req *http.Request, ps httprouter.Params){
if ds, ok := rawAlerts.([]interface{}); ok {
for _, alert := range ds {
if alertItem, ok := alert.(map[string]interface{}); ok {
alertItem["version"] = queryValue(alertItem, "alert_version", "")
alertItem["id"] = queryValue(alertItem, "alert_id", "")
if queryValue(alertItem, "id", nil) == nil {
alertItem["id"] = queryValue(alertItem, "alert_id", nil)
}
alerts = append(alerts, alertItem)
}
}

View File

@ -445,7 +445,6 @@ func GetEmailAccounts(w http.ResponseWriter, req *http.Request, ps httprouter.Pa
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
@ -507,7 +506,6 @@ func GetEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Par
writeError(w, err)
return
}
//TODO error handle: check whether resBody has contains field error
writeJSON(w, IfaceMap{
"ok": true,
@ -703,8 +701,8 @@ func GetEmailGroups(w http.ResponseWriter, req *http.Request, ps httprouter.Para
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)
newItem["ifSeqNo"] = queryValue(emailGroup, "_seq_no", 0)
newItem["ifPrimaryTerm"] = queryValue(emailGroup, "_primary_term", 0)
emailGroups = append(emailGroups, newItem)
}
}
@ -716,5 +714,44 @@ func GetEmailGroups(w http.ResponseWriter, req *http.Request, ps httprouter.Para
}, http.StatusOK)
}
func GetEmailGroup(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("emailGroupId")
reqUrl := fmt.Sprintf("%s/%s/_alerting/destinations/email_groups/%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
}
emailGroup := queryValue(resBody, "email_group", nil)
if emailGroup == nil {
writeJSON(w, IfaceMap{
"ok": false,
}, http.StatusOK)
return
}
writeJSON(w, IfaceMap{
"ok": true,
"resp": emailGroup,
"ifSeqNo": queryValue(resBody, "_seq_no", 0),
"ifPrimaryTerm": queryValue(resBody, "_primary_term", 0),
}, http.StatusOK)
}

View File

@ -443,7 +443,6 @@ func UpdateMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Param
writeError(w, err)
return
}
//TODO error handle: check whether resBody has contains field error
writeJSON(w, IfaceMap{
"ok": true,
@ -453,6 +452,43 @@ func UpdateMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Param
}
func AcknowledgeAlerts(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/_acknowledge/alerts", conf.Endpoint, API_PREFIX, monitorId)
res, err := doRequest(reqUrl, http.MethodPost,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
}
var isOk = false
if failed, ok := resBody["failed"].([]interface{}); ok && len(failed) == 0 {
isOk = true
}
writeJSON(w, IfaceMap{
"ok": isOk,
"resp": resBody,
}, http.StatusOK)
}
func ExecuteMonitor(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
id := ps.ByName("id")
conf := elastic.GetConfig(id)

View File

@ -125,6 +125,7 @@ export class ScopedHistory<HistoryLocationState = unknown>
if (typeof pathOrLocation === 'string') {
this.parentHistory.push(this.prependBasePath(pathOrLocation), state);
} else {
!pathOrLocation.key && (pathOrLocation.key = pathOrLocation.pathname+(pathOrLocation.search||''))
this.parentHistory.push(this.prependBasePath(pathOrLocation));
}
};

View File

@ -14,9 +14,9 @@ export default {
'alert.dashboard.alerts': '告警管理',
'alert.dashboard.severity-options.all': '所有告警级别',
'alert.dashboard.state-options.all': '所有状态',
'alert.dashboard.state-options.active': '激活的',
'alert.dashboard.state-options.acknowledged': '已确认',
'alert.dashboard.state-options.completed': '已完成',
'alert.dashboard.state-options.active': '告警中',
'alert.dashboard.state-options.acknowledged': '已知晓',
'alert.dashboard.state-options.completed': '已恢复',
'alert.dashboard.state-options.error': '错误',
'alert.dashboard.state-options.deleted': '已删除',
'alert.dashboard.create-monitor-text': '暂无监控项。 创建监控项以添加触发器和操作。 一旦触发警报,状态将显示在此表中。',

View File

@ -126,15 +126,15 @@ export default {
});
},
*rewriteURL({payload}, {select}){
const {pathname, history} = payload;
const {pathname, history, search} = payload;
const global = yield select(state=>state.global);
if(pathname && global.selectedClusterID){
const newPart = `/elasticsearch/${global.selectedClusterID}/`;
if(!pathname.includes('elasticsearch')){
history.replace(pathname+newPart)
history.replace(pathname+newPart+search)
}else{
const newPath = pathname.replace(/\/elasticsearch\/(\w+)\/?/, newPart);
history.replace(newPath)
history.replace(newPath+search)
}
}
},
@ -230,14 +230,17 @@ export default {
if(pathname.startsWith("/system")){
clusterVisible = false;
}else{
if(!pathname.includes('elasticsearch')){
dispatch({
type: 'rewriteURL',
payload: {
pathname,
history,
}
})
if(!pathname.startsWith("/exception") && pathname != '/alerting'){
if(!pathname.includes('elasticsearch')){
dispatch({
type: 'rewriteURL',
payload: {
pathname,
history,
search,
}
})
}
}
}
dispatch({

View File

@ -32,6 +32,8 @@ const notifications = {
}
}
const AlertingMain = React.memo(Main)
const AlertingUI = (props)=>{
if(!props.selectedCluster.id){
return null;
@ -52,13 +54,14 @@ const AlertingUI = (props)=>{
>
<Router history={history}>
<div style={{background:'#fff'}}>
<Main title="Alerting" {...props} />
<AlertingMain title="Alerting" {...props} />
</div>
</Router>
</CoreContext.Provider>
)
}
export default connect(({
global
})=>({

View File

@ -22,7 +22,7 @@ const actionEmptyText = 'Add an action to perform when this trigger is triggered
const destinationEmptyText =
'There are no existing destinations. Add a destinations to create an action';
const createDestinationButton = (
<EuiButton fill href={`${PLUGIN_NAME}#/create-destination`}>
<EuiButton fill href={`#/${PLUGIN_NAME}/create-destination`}>
Add destination
</EuiButton>
);

View File

@ -184,7 +184,7 @@ export default class Dashboard extends Component {
const queryParamsString = queryString.stringify(params);
location.search;
const { httpClient, history, notifications } = this.props;
history.replace({ ...this.props.location, search: queryParamsString });
// history.replace({ ...this.props.location, search: queryParamsString });
httpClient.get('/alerting/alerts', { query: params }).then((resp) => {
if (resp.ok) {
const { alerts, totalAlerts } = resp;
@ -218,7 +218,7 @@ export default class Dashboard extends Component {
const promises = Object.entries(monitorAlerts).map(([monitorId, alerts]) =>
httpClient
.post(`/alerting/monitors/${monitorId}/_acknowledge/alerts`, {
.post(`/alerting/_monitors/${monitorId}/_acknowledge/alerts`, {
body: JSON.stringify({ alerts }),
})
.then((resp) => {

View File

@ -28,6 +28,15 @@ const renderTime = (time) => {
return DEFAULT_EMPTY_DATA;
};
const stateOptions = {
'ALL': formatMessage({ id: 'alert.dashboard.state-options.all' }),
[ALERT_STATE.ACTIVE]: formatMessage({ id: 'alert.dashboard.state-options.active' }),
[ALERT_STATE.ACKNOWLEDGED]: formatMessage({ id: 'alert.dashboard.state-options.acknowledged' }),
[ALERT_STATE.COMPLETED]: formatMessage({ id: 'alert.dashboard.state-options.completed' }),
[ALERT_STATE.ERROR]: formatMessage({ id: 'alert.dashboard.state-options.error' }),
[ALERT_STATE.DELETED]: formatMessage({ id: 'alert.dashboard.state-options.deleted' }),
};
export const columns = [
{
field: 'start_time',
@ -76,7 +85,7 @@ export const columns = [
render: (state, alert) => {
const stateText =
typeof state !== 'string' ? DEFAULT_EMPTY_DATA : _.capitalize(state.toLowerCase());
return state === ALERT_STATE.ERROR ? `${stateText}: ${alert.error_message}` : stateText;
return state === ALERT_STATE.ERROR ? `${stateText}: ${alert.error_message}` : (stateOptions[state] || stateText);
},
},
{

View File

@ -165,11 +165,11 @@ class CreateDestination extends React.Component {
handleCancel = () => {
const { edit, history } = this.props;
if (edit) {
history.goBack();
} else {
// if (edit) {
// history.goBack();
// } else {
history.push('/destinations');
}
// }
};
render() {

View File

@ -62,7 +62,7 @@ const getSender = async (httpClient, id) => {
const getEmailGroup = async (httpClient, id) => {
try {
const response = await httpClient.get(`/alerting/destinations/email_groups/${id}`);
const response = await httpClient.get(`/alerting/email_groups/${id}`);
if (response.ok) {
return response.resp;
}

View File

@ -97,7 +97,7 @@ export default class Home extends Component {
<div style={{ padding: '25px 25px' }}>
<Switch>
<Route
exact
// exact
path="/dashboard"
render={(props) => (
<Dashboard {...props} httpClient={httpClient} notifications={notifications} />
@ -121,7 +121,15 @@ export default class Home extends Component {
/>
)}
/>
<Redirect to="/dashboard" />
<Route
exact
path="/"
render={() => {
return (
<Redirect to="/dashboard" />
)
}}
/>
</Switch>
</div>
</div>

View File

@ -96,7 +96,7 @@ class TriggersTimeSeries extends Component {
align={{ vertical: 'top', horizontal: 'auto' }}
value={hints[currentTrigger.name]}
format={formatTooltip}
style={{ title: { fontWeight: 'bold' } }}
style={{ title: { fontWeight: 'bold' }, backgroundColor: '#fff'}}
/>
) : null}
</FlexibleWidthXYPlot>

View File

@ -178,7 +178,8 @@ export default class MonitorDetails extends Component {
};
onCloseTrigger = () => {
this.props.history.push({ ...this.props.location, search: '' });
const {pathname} = this.props.location; //important change
this.props.history.push({ pathname, search: '' });
this.setState({ triggerToEdit: null });
};
@ -301,7 +302,7 @@ export default class MonitorDetails extends Component {
</h1>
</EuiTitle>
{detector ? (
{/* {detector ? (
<EuiFlexItem grow={false}>
<EuiText size="s">
Created from detector:{' '}
@ -310,7 +311,7 @@ export default class MonitorDetails extends Component {
</EuiLink>
</EuiText>
</EuiFlexItem>
) : null}
) : null} */}
</EuiFlexItem>
<EuiFlexItem grow={false}>

View File

@ -249,7 +249,7 @@ export default class Monitors extends Component {
const promises = Object.entries(monitorAlerts).map(([monitorId, alerts]) =>
httpClient
.post(`/alerting/monitors/${monitorId}/_acknowledge/alerts`, {
.post(`/alerting/_monitors/${monitorId}/_acknowledge/alerts`, {
body: JSON.stringify({ alerts }),
})
.then((resp) => {