add test api to send channel message
This commit is contained in:
parent
5f2569d999
commit
d6d1013e0a
|
@ -33,6 +33,7 @@ func (alert *AlertAPI) Init() {
|
|||
api.HandleAPIMethod(api.DELETE, "/alerting/channel", alert.RequirePermission(alert.deleteChannel, enum.PermissionAlertChannelWrite))
|
||||
api.HandleAPIMethod(api.PUT, "/alerting/channel/:channel_id", alert.RequirePermission(alert.updateChannel, enum.PermissionAlertChannelWrite))
|
||||
api.HandleAPIMethod(api.GET, "/alerting/channel/_search", alert.RequirePermission(alert.searchChannel, enum.PermissionAlertChannelRead))
|
||||
api.HandleAPIMethod(api.POST, "/alerting/channel/test", alert.RequirePermission(alert.testChannel, enum.PermissionAlertChannelWrite))
|
||||
|
||||
api.HandleAPIMethod(api.GET, "/alerting/alert/_search", alert.RequirePermission(alert.searchAlert, enum.PermissionAlertHistoryRead))
|
||||
api.HandleAPIMethod(api.GET, "/alerting/alert/:alert_id", alert.RequirePermission(alert.getAlert, enum.PermissionAlertHistoryRead))
|
||||
|
|
|
@ -6,9 +6,11 @@ package alerting
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"infini.sh/console/service/alerting/common"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/cihub/seelog"
|
||||
"infini.sh/console/model/alerting"
|
||||
|
@ -33,10 +35,7 @@ func (h *AlertAPI) createChannel(w http.ResponseWriter, req *http.Request, ps ht
|
|||
return
|
||||
}
|
||||
|
||||
h.WriteJSON(w, util.MapStr{
|
||||
"_id": obj.ID,
|
||||
"result": "created",
|
||||
}, 200)
|
||||
h.WriteCreatedOKJSON(w, obj.ID)
|
||||
|
||||
}
|
||||
|
||||
|
@ -60,11 +59,7 @@ func (h *AlertAPI) getChannel(w http.ResponseWriter, req *http.Request, ps httpr
|
|||
return
|
||||
}
|
||||
|
||||
h.WriteJSON(w, util.MapStr{
|
||||
"found": true,
|
||||
"_id": id,
|
||||
"_source": obj,
|
||||
}, 200)
|
||||
h.WriteGetOKJSON(w, id, obj)
|
||||
}
|
||||
|
||||
func (h *AlertAPI) updateChannel(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
|
@ -101,10 +96,7 @@ func (h *AlertAPI) updateChannel(w http.ResponseWriter, req *http.Request, ps ht
|
|||
return
|
||||
}
|
||||
|
||||
h.WriteJSON(w, util.MapStr{
|
||||
"_id": obj.ID,
|
||||
"result": "updated",
|
||||
}, 200)
|
||||
h.WriteUpdatedOKJSON(w, id)
|
||||
}
|
||||
|
||||
func (h *AlertAPI) deleteChannel(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
|
@ -179,3 +171,43 @@ func (h *AlertAPI) searchChannel(w http.ResponseWriter, req *http.Request, ps ht
|
|||
}
|
||||
h.Write(w, res.Raw)
|
||||
}
|
||||
|
||||
func (h *AlertAPI) testChannel(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
obj := alerting.Channel{}
|
||||
err := h.DecodeJSON(req, &obj)
|
||||
if err != nil {
|
||||
h.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
ctx := map[string]interface{}{
|
||||
"title": "test title",
|
||||
"message": "test message",
|
||||
"rule_id": util.GetUUID(),
|
||||
"rule_name": "test rule",
|
||||
"resource_id": util.GetUUID(),
|
||||
"resource_name": "test resource",
|
||||
"event_id": util.GetUUID(),
|
||||
"timestamp": time.Now().UnixMilli(),
|
||||
"first_group_value": "first group value",
|
||||
"first_threshold": "90",
|
||||
"priority": "critical",
|
||||
"results": []util.MapStr{
|
||||
{"threshold": "90",
|
||||
"priority": "critical",
|
||||
"group_values": []string{"first group value", "second group value"},
|
||||
"issue_timestamp": time.Now().UnixMilli()-500,
|
||||
"result_value": 90,
|
||||
"relation_values": util.MapStr{"a": 100, "b": 90},
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
_, err, _ = common.PerformChannel(&obj, ctx)
|
||||
if err != nil {
|
||||
h.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
h.WriteAckOKJSON(w)
|
||||
}
|
|
@ -80,10 +80,7 @@ func (h *EmailAPI) createEmailServer(w http.ResponseWriter, req *http.Request, p
|
|||
}
|
||||
}
|
||||
|
||||
h.WriteJSON(w, util.MapStr{
|
||||
"_id": obj.ID,
|
||||
"result": "created",
|
||||
}, 200)
|
||||
h.WriteCreatedOKJSON(w, obj.ID)
|
||||
|
||||
}
|
||||
|
||||
|
@ -107,11 +104,7 @@ func (h *EmailAPI) getEmailServer(w http.ResponseWriter, req *http.Request, ps h
|
|||
return
|
||||
}
|
||||
|
||||
h.WriteJSON(w, util.MapStr{
|
||||
"found": true,
|
||||
"_id": id,
|
||||
"_source": obj,
|
||||
}, 200)
|
||||
h.WriteGetOKJSON(w, id, obj)
|
||||
}
|
||||
|
||||
func (h *EmailAPI) updateEmailServer(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
|
@ -161,10 +154,7 @@ func (h *EmailAPI) updateEmailServer(w http.ResponseWriter, req *http.Request, p
|
|||
log.Error(err)
|
||||
}
|
||||
|
||||
h.WriteJSON(w, util.MapStr{
|
||||
"_id": obj.ID,
|
||||
"result": "updated",
|
||||
}, 200)
|
||||
h.WriteUpdatedOKJSON(w, obj.ID)
|
||||
}
|
||||
|
||||
func (h *EmailAPI) deleteEmailServer(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
|
@ -202,10 +192,7 @@ func (h *EmailAPI) deleteEmailServer(w http.ResponseWriter, req *http.Request, p
|
|||
}
|
||||
}
|
||||
|
||||
h.WriteJSON(w, util.MapStr{
|
||||
"_id": obj.ID,
|
||||
"result": "deleted",
|
||||
}, 200)
|
||||
h.WriteDeletedOKJSON(w, obj.ID)
|
||||
}
|
||||
|
||||
func checkEmailServerReferenced(srv *model.EmailServer) error {
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* Copyright © INFINI Ltd. All rights reserved.
|
||||
* Web: https://infinilabs.com
|
||||
* Email: hello#infini.ltd */
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"infini.sh/console/model/alerting"
|
||||
"infini.sh/console/service/alerting/action"
|
||||
"infini.sh/console/service/alerting/funcs"
|
||||
"infini.sh/framework/core/orm"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func PerformChannel(channel *alerting.Channel, ctx map[string]interface{}) ([]byte, error, []byte) {
|
||||
var (
|
||||
act action.Action
|
||||
message []byte
|
||||
err error
|
||||
)
|
||||
channel, err = RetrieveChannel(channel)
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
}
|
||||
switch channel.Type {
|
||||
|
||||
case alerting.ChannelWebhook:
|
||||
message, err = ResolveMessage(channel.Webhook.Body, ctx)
|
||||
if err != nil {
|
||||
return nil, err, message
|
||||
}
|
||||
wh := *channel.Webhook
|
||||
urlBytes, err := ResolveMessage(wh.URL, ctx)
|
||||
if err != nil {
|
||||
return nil, err, message
|
||||
}
|
||||
wh.URL = string(urlBytes)
|
||||
act = &action.WebhookAction{
|
||||
Data: &wh,
|
||||
Message: string(message),
|
||||
}
|
||||
case alerting.ChannelEmail:
|
||||
message, err = ResolveMessage(channel.Email.Body, ctx)
|
||||
if err != nil {
|
||||
return nil, err, message
|
||||
}
|
||||
subjectBytes, err := ResolveMessage(channel.Email.Subject, ctx)
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
}
|
||||
act = &action.EmailAction{
|
||||
Data: channel.Email,
|
||||
Subject: string(subjectBytes),
|
||||
Body: string(message),
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported action type: %s", channel.Type), message
|
||||
}
|
||||
executeResult, err := act.Execute()
|
||||
return executeResult, err, message
|
||||
}
|
||||
|
||||
func ResolveMessage(messageTemplate string, ctx map[string]interface{}) ([]byte, error){
|
||||
msg := messageTemplate
|
||||
tmpl, err := template.New("alert-message").Funcs(funcs.GenericFuncMap()).Parse(msg)
|
||||
if err !=nil {
|
||||
return nil, fmt.Errorf("parse message temlate error: %w", err)
|
||||
}
|
||||
msgBuffer := &bytes.Buffer{}
|
||||
err = tmpl.Execute(msgBuffer, ctx)
|
||||
return msgBuffer.Bytes(), err
|
||||
}
|
||||
|
||||
func RetrieveChannel(ch *alerting.Channel) (*alerting.Channel, error) {
|
||||
if ch == nil {
|
||||
return nil, fmt.Errorf("empty channel")
|
||||
}
|
||||
if ch.ID != "" {
|
||||
_, err := orm.Get(ch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ch, nil
|
||||
}
|
|
@ -5,7 +5,6 @@
|
|||
package elasticsearch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/Knetic/govaluate"
|
||||
|
@ -13,8 +12,7 @@ import (
|
|||
"infini.sh/console/model"
|
||||
"infini.sh/console/model/alerting"
|
||||
alerting2 "infini.sh/console/service/alerting"
|
||||
"infini.sh/console/service/alerting/action"
|
||||
"infini.sh/console/service/alerting/funcs"
|
||||
"infini.sh/console/service/alerting/common"
|
||||
"infini.sh/framework/core/elastic"
|
||||
"infini.sh/console/model/insight"
|
||||
"infini.sh/framework/core/kv"
|
||||
|
@ -25,7 +23,6 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -857,12 +854,12 @@ func attachTitleMessageToCtx(title, message string, paramsCtx map[string]interfa
|
|||
tplBytes []byte
|
||||
err error
|
||||
)
|
||||
tplBytes, err = resolveMessage(message, paramsCtx)
|
||||
tplBytes, err = common.ResolveMessage(message, paramsCtx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve message template error: %w", err)
|
||||
}
|
||||
paramsCtx[alerting2.ParamMessage] = string(tplBytes)
|
||||
tplBytes, err = resolveMessage(title, paramsCtx)
|
||||
tplBytes, err = common.ResolveMessage(title, paramsCtx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve title template error: %w", err)
|
||||
}
|
||||
|
@ -962,7 +959,7 @@ func performChannels(channels []alerting.Channel, ctx map[string]interface{}) ([
|
|||
var errCount int
|
||||
var actionResults []alerting.ActionExecutionResult
|
||||
for _, channel := range channels {
|
||||
resBytes, err, messageBytes := performChannel(&channel, ctx)
|
||||
resBytes, err, messageBytes := common.PerformChannel(&channel, ctx)
|
||||
var errStr string
|
||||
if err != nil {
|
||||
errCount++
|
||||
|
@ -980,64 +977,8 @@ func performChannels(channels []alerting.Channel, ctx map[string]interface{}) ([
|
|||
return actionResults, errCount
|
||||
}
|
||||
|
||||
func resolveMessage(messageTemplate string, ctx map[string]interface{}) ([]byte, error){
|
||||
msg := messageTemplate
|
||||
tmpl, err := template.New("alert-message").Funcs(funcs.GenericFuncMap()).Parse(msg)
|
||||
if err !=nil {
|
||||
return nil, fmt.Errorf("parse message temlate error: %w", err)
|
||||
}
|
||||
msgBuffer := &bytes.Buffer{}
|
||||
err = tmpl.Execute(msgBuffer, ctx)
|
||||
return msgBuffer.Bytes(), err
|
||||
}
|
||||
|
||||
func performChannel(channel *alerting.Channel, ctx map[string]interface{}) ([]byte, error, []byte) {
|
||||
var (
|
||||
act action.Action
|
||||
message []byte
|
||||
err error
|
||||
)
|
||||
channel, err = RetrieveChannel(channel)
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
}
|
||||
switch channel.Type {
|
||||
|
||||
case alerting.ChannelWebhook:
|
||||
message, err = resolveMessage(channel.Webhook.Body, ctx)
|
||||
if err != nil {
|
||||
return nil, err, message
|
||||
}
|
||||
wh := *channel.Webhook
|
||||
urlBytes, err := resolveMessage(wh.URL, ctx)
|
||||
if err != nil {
|
||||
return nil, err, message
|
||||
}
|
||||
wh.URL = string(urlBytes)
|
||||
act = &action.WebhookAction{
|
||||
Data: &wh,
|
||||
Message: string(message),
|
||||
}
|
||||
case alerting.ChannelEmail:
|
||||
message, err = resolveMessage(channel.Email.Body, ctx)
|
||||
if err != nil {
|
||||
return nil, err, message
|
||||
}
|
||||
subjectBytes, err := resolveMessage(channel.Email.Subject, ctx)
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
}
|
||||
act = &action.EmailAction{
|
||||
Data: channel.Email,
|
||||
Subject: string(subjectBytes),
|
||||
Body: string(message),
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported action type: %s", channel.Type), message
|
||||
}
|
||||
executeResult, err := act.Execute()
|
||||
return executeResult, err, message
|
||||
}
|
||||
func (engine *Engine) GenerateTask(rule alerting.Rule) func(ctx context.Context) {
|
||||
return func(ctx context.Context) {
|
||||
defer func() {
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/* Copyright © INFINI Ltd. All rights reserved.
|
||||
* Web: https://infinilabs.com
|
||||
* Email: hello#infini.ltd */
|
||||
|
||||
package elasticsearch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"infini.sh/console/model/alerting"
|
||||
"infini.sh/framework/core/orm"
|
||||
)
|
||||
|
||||
func RetrieveChannel(ch *alerting.Channel) (*alerting.Channel, error) {
|
||||
if ch == nil {
|
||||
return nil, fmt.Errorf("empty channel")
|
||||
}
|
||||
if ch.ID != "" {
|
||||
_, err := orm.Get(ch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ch, nil
|
||||
}
|
Loading…
Reference in New Issue