mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #5340 from zexi/feature/monitor-service
alert notification use joint model
This commit is contained in:
@@ -46,6 +46,20 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.AlertUpdateOptions{}, aN("update"), "Update a alert rule",
|
||||
func(s *mcclient.ClientSession, args *options.AlertUpdateOptions) error {
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := monitor.Alerts.Update(s, args.ID, params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.AlertDeleteOptions{}, aN("delete"), "Delete alerts",
|
||||
func(s *mcclient.ClientSession, args *options.AlertDeleteOptions) error {
|
||||
ret := monitor.Alerts.BatchDelete(s, args.ID, nil)
|
||||
|
||||
@@ -28,11 +28,11 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := monitor.AlertNotifications.List(s, params)
|
||||
ret, err := monitor.Notifications.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(ret, monitor.AlertNotifications.GetColumns(s))
|
||||
printList(ret, monitor.Notifications.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -43,7 +43,7 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := monitor.AlertNotifications.Create(s, params.JSON(params))
|
||||
ret, err := monitor.Notifications.Create(s, params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := monitor.AlertNotifications.Create(s, params.JSON(params))
|
||||
ret, err := monitor.Notifications.Create(s, params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func init() {
|
||||
|
||||
R(&options.NotificationShowOptions{}, nN("show"), "Show alert notification",
|
||||
func(s *mcclient.ClientSession, args *options.NotificationShowOptions) error {
|
||||
ret, err := monitor.AlertNotifications.Get(s, args.ID, nil)
|
||||
ret, err := monitor.Notifications.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := monitor.AlertNotifications.Update(s, args.ID, params.JSON(params))
|
||||
ret, err := monitor.Notifications.Update(s, args.ID, params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -90,13 +90,10 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.NotificationShowOptions{}, nN("delete"), "Show delete notification",
|
||||
func(s *mcclient.ClientSession, args *options.NotificationShowOptions) error {
|
||||
ret, err := monitor.AlertNotifications.Delete(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
R(&options.NotificationDeleteOptions{}, nN("delete"), "Show delete notification",
|
||||
func(s *mcclient.ClientSession, args *options.NotificationDeleteOptions) error {
|
||||
ret := monitor.Notifications.BatchDelete(s, args.ID, nil)
|
||||
printBatchResults(ret, monitor.Notifications.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
+20
-17
@@ -78,9 +78,7 @@ func (s ExecutionErrorOption) ToAlertState() AlertStateType {
|
||||
|
||||
// AlertSettings contains alert conditions
|
||||
type AlertSetting struct {
|
||||
Conditions []AlertCondition `json:"conditions"`
|
||||
Notifications []string `json:"notifications"`
|
||||
Level string `json:"level"`
|
||||
Conditions []AlertCondition `json:"conditions"`
|
||||
}
|
||||
|
||||
type AlertCondition struct {
|
||||
@@ -101,31 +99,36 @@ type AlertQuery struct {
|
||||
type AlertCreateInput struct {
|
||||
apis.Meta
|
||||
|
||||
Name string `json:"name"`
|
||||
Frequency int64 `json:"frequency"`
|
||||
Settings AlertSetting `json:"settings"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
// 报警名称
|
||||
Name string `json:"name"`
|
||||
// 报警执行频率
|
||||
Frequency int64 `json:"frequency"`
|
||||
// 报警设置
|
||||
Settings AlertSetting `json:"settings"`
|
||||
// 启用报警
|
||||
Enabled *bool `json:"enabled"`
|
||||
// 报警级别
|
||||
Level string `json:"level"`
|
||||
}
|
||||
|
||||
type AlertUpdateInput struct {
|
||||
apis.Meta
|
||||
|
||||
Name *string `json:"name"`
|
||||
Frequency *int64 `json:"frequency"`
|
||||
Settings *AlertSetting `json:"settings"`
|
||||
ResourceId *string `json:"resource_id"`
|
||||
ResourceType *string `json:"resource_type"`
|
||||
Message *string `json:"message"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
// 报警名称
|
||||
Name *string `json:"name"`
|
||||
// 报警执行频率
|
||||
Frequency *int64 `json:"frequency"`
|
||||
// 报警设置
|
||||
Settings *AlertSetting `json:"settings"`
|
||||
// 启用报警
|
||||
Enabled *bool `json:"enabled"`
|
||||
Message *string `json:"message"`
|
||||
}
|
||||
|
||||
type AlertListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
apis.EnabledResourceBaseListInput
|
||||
|
||||
// 监控指标名称
|
||||
Metric string `json:"metric"`
|
||||
|
||||
// 以报警是否启用/禁用过滤列表
|
||||
// Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ type MeterAlertListInput struct {
|
||||
Provider string `json:"provider"`
|
||||
// 云账号 Id
|
||||
AccountId string `json:"account_id"`
|
||||
// 项目 Id string
|
||||
// 项目 Id
|
||||
ProjectId string `json:"project_id"`
|
||||
}
|
||||
|
||||
@@ -58,3 +58,16 @@ type MeterAlertDetails struct {
|
||||
AccountId string `json:"account_id"`
|
||||
Provider string `json:"provider"`
|
||||
}
|
||||
|
||||
type MeterAlertUpdateInput struct {
|
||||
// 比较运算符, 比如: >, <, >=, <=
|
||||
Comparator *string `json:"comparator"`
|
||||
// 报警阀值
|
||||
Threshold *float64 `json:"threshold"`
|
||||
// 通知接受者
|
||||
Recipients *string `json:"recipients"`
|
||||
// 项目 Id
|
||||
ProjectId *string `json:"project_id"`
|
||||
// 通知方式, 比如: email, mobile
|
||||
Channel *string `json:"channel"`
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ const (
|
||||
)
|
||||
|
||||
type ResourceAlertV1CreateInput struct {
|
||||
*AlertCreateInput
|
||||
AlertCreateInput
|
||||
|
||||
// 查询指标周期
|
||||
Period string `json:"period"`
|
||||
@@ -36,8 +36,6 @@ type ResourceAlertV1CreateInput struct {
|
||||
Comparator string `json:"comparator"`
|
||||
// 报警阀值
|
||||
Threshold float64 `json:"threshold"`
|
||||
// 报警级别
|
||||
Level string `json:"level"`
|
||||
// 通知方式, 比如: email, mobile
|
||||
Channel string `json:"channel"`
|
||||
// 通知接受者
|
||||
@@ -61,15 +59,13 @@ func (input NodeAlertCreateInput) ToAlertCreateInput(
|
||||
name string,
|
||||
field string,
|
||||
measurement string,
|
||||
db string,
|
||||
notifications []string) AlertCreateInput {
|
||||
db string) AlertCreateInput {
|
||||
freq, _ := time.ParseDuration(input.Window)
|
||||
ret := AlertCreateInput{
|
||||
Name: name,
|
||||
Frequency: int64(freq / time.Second),
|
||||
Level: input.Level,
|
||||
Settings: AlertSetting{
|
||||
Level: input.Level,
|
||||
Notifications: notifications,
|
||||
Conditions: []AlertCondition{
|
||||
{
|
||||
Type: "query",
|
||||
@@ -157,7 +153,6 @@ type NodeAlertListInput struct {
|
||||
func (input NodeAlertListInput) ToAlertListInput() AlertListInput {
|
||||
return AlertListInput{
|
||||
VirtualResourceListInput: input.VirtualResourceListInput,
|
||||
Metric: input.Metric,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ const (
|
||||
AlertNotificationTypeFeishu = "feishu"
|
||||
)
|
||||
|
||||
type AlertNotificationCreateInput struct {
|
||||
type NotificationCreateInput struct {
|
||||
apis.Meta
|
||||
|
||||
// 报警通知名称
|
||||
@@ -55,7 +55,7 @@ type AlertNotificationCreateInput struct {
|
||||
Settings jsonutils.JSONObject `json:"settings"`
|
||||
}
|
||||
|
||||
type AlertNotificationUpdateInput struct {
|
||||
type NotificationUpdateInput struct {
|
||||
apis.Meta
|
||||
|
||||
// 报警通知名称
|
||||
@@ -95,12 +95,3 @@ type NotificationSettingFeishu struct {
|
||||
AppId string `json:"app_id"`
|
||||
AppSecret string `json:"app_secret"`
|
||||
}
|
||||
|
||||
type AlertNotificationStateCreateInput struct {
|
||||
apis.Meta
|
||||
|
||||
Name string `json:"name"`
|
||||
AlertId string `json:"alert_id"`
|
||||
NotifierId string `json:"notifier_id"`
|
||||
State AlertNotificationStateType `json:"state"`
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ type NotificationTemplateConfig struct {
|
||||
Matches []EvalMatch `json:"matches"`
|
||||
// PrevAlertState AlertStateType `json:"prev_alert_state"`
|
||||
// State AlertStateType `json:"state"`
|
||||
NoDataFound bool `json:"no_data"`
|
||||
StartTime string `json:"start_time"`
|
||||
EndTime string `json:"end_time"`
|
||||
Description string `json:"description"`
|
||||
|
||||
@@ -20,21 +20,21 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
Alerts modulebase.ResourceManager
|
||||
AlertNotifications modulebase.ResourceManager
|
||||
Alerts modulebase.ResourceManager
|
||||
Notifications modulebase.ResourceManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
Alerts = modules.NewMonitorV2Manager("alert", "alerts",
|
||||
[]string{"id", "name", "settings"},
|
||||
[]string{"id", "name", "state", "frequency", "enabled", "settings"},
|
||||
[]string{})
|
||||
AlertNotifications = modules.NewMonitorV2Manager(
|
||||
Notifications = modules.NewMonitorV2Manager(
|
||||
"alert_notification", "alert_notifications",
|
||||
[]string{"id", "name", "type", "is_default", "disable_resolve_message", "send_reminder", "settings"},
|
||||
[]string{})
|
||||
for _, m := range []modulebase.ResourceManager{
|
||||
Alerts,
|
||||
AlertNotifications,
|
||||
Notifications,
|
||||
} {
|
||||
modules.Register(&m)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/monitor"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type AlertListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
type AlertShowOptions struct {
|
||||
ID string `help:"ID or name of the alert" json:"-"`
|
||||
}
|
||||
|
||||
type AlertDeleteOptions struct {
|
||||
ID []string `help:"ID of alert to delete"`
|
||||
}
|
||||
|
||||
type AlertUpdateOptions struct {
|
||||
ID string `help:"ID or name of the alert"`
|
||||
Name string `help:"Update alert name"`
|
||||
Frequency string `help:"Alert execute frequency, e.g. '5m', '1h'"`
|
||||
}
|
||||
|
||||
func (opt AlertUpdateOptions) Params() (*monitor.AlertUpdateInput, error) {
|
||||
input := new(monitor.AlertUpdateInput)
|
||||
if opt.Name != "" {
|
||||
input.Name = &opt.Name
|
||||
}
|
||||
if opt.Frequency != "" {
|
||||
freq, err := time.ParseDuration(opt.Frequency)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Invalid frequency time format %s: %v", opt.Frequency, err)
|
||||
}
|
||||
f := int64(freq / time.Second)
|
||||
input.Frequency = &f
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
@@ -41,6 +41,10 @@ type NotificationShowOptions struct {
|
||||
ID string `help:"ID or name of the alert notification config" json:"-"`
|
||||
}
|
||||
|
||||
type NotificationDeleteOptions struct {
|
||||
ID []string `help:"ID or name of the alert notification config" json:"-"`
|
||||
}
|
||||
|
||||
type NotificationFields struct {
|
||||
Frequency string `help:"notify frequency, e.g. 5m, 1h"`
|
||||
IsDefault *bool `help:"set as default notification"`
|
||||
@@ -53,8 +57,8 @@ type NotificationCreateOptions struct {
|
||||
NotificationFields
|
||||
}
|
||||
|
||||
func (opt NotificationCreateOptions) Params() (*monitor.AlertNotificationCreateInput, error) {
|
||||
ret := &monitor.AlertNotificationCreateInput{
|
||||
func (opt NotificationCreateOptions) Params() (*monitor.NotificationCreateInput, error) {
|
||||
ret := &monitor.NotificationCreateInput{
|
||||
Name: opt.NAME,
|
||||
SendReminder: opt.SendReminder,
|
||||
DisableResolveMessage: opt.DisableResolveMessage,
|
||||
@@ -71,7 +75,7 @@ type NotificationDingDingCreateOptions struct {
|
||||
MsgType string `help:"message type" choices:"markdown|actionCard" default:"markdown"`
|
||||
}
|
||||
|
||||
func (opt NotificationDingDingCreateOptions) Params() (*monitor.AlertNotificationCreateInput, error) {
|
||||
func (opt NotificationDingDingCreateOptions) Params() (*monitor.NotificationCreateInput, error) {
|
||||
out, err := opt.NotificationCreateOptions.Params()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -90,7 +94,7 @@ type NotificationFeishuCreateOptions struct {
|
||||
APPSECRET string `help:"feishu robt appSecret"`
|
||||
}
|
||||
|
||||
func (opt NotificationFeishuCreateOptions) Params() (*monitor.AlertNotificationCreateInput, error) {
|
||||
func (opt NotificationFeishuCreateOptions) Params() (*monitor.NotificationCreateInput, error) {
|
||||
out, err := opt.NotificationCreateOptions.Params()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -112,7 +116,7 @@ type NotificationUpdateOptions struct {
|
||||
DisableSendReminder *bool `help:"disable send reminder" json:"-"`
|
||||
}
|
||||
|
||||
func (opt NotificationUpdateOptions) Params() (*monitor.AlertNotificationUpdateInput, error) {
|
||||
func (opt NotificationUpdateOptions) Params() (*monitor.NotificationUpdateInput, error) {
|
||||
if opt.DisableDefault != nil && *opt.DisableDefault {
|
||||
tmp := false
|
||||
opt.IsDefault = &tmp
|
||||
@@ -125,22 +129,10 @@ func (opt NotificationUpdateOptions) Params() (*monitor.AlertNotificationUpdateI
|
||||
tmp := false
|
||||
opt.SendReminder = &tmp
|
||||
}
|
||||
ret := &monitor.AlertNotificationUpdateInput{
|
||||
ret := &monitor.NotificationUpdateInput{
|
||||
IsDefault: opt.IsDefault,
|
||||
DisableResolveMessage: opt.DisableResolveMessage,
|
||||
SendReminder: opt.SendReminder,
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type AlertListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
type AlertShowOptions struct {
|
||||
ID string `help:"ID or name of the alert" json:"-"`
|
||||
}
|
||||
|
||||
type AlertDeleteOptions struct {
|
||||
ID []string `help:"ID of alert to delete"`
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package alerting
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
@@ -83,7 +84,7 @@ func (c *EvalContext) GetStateModel() *StateDescription {
|
||||
Text: "Unknown",
|
||||
}
|
||||
default:
|
||||
panic("Unknown rule state for alert " + c.Rule.State)
|
||||
panic(fmt.Sprintf("Unknown rule state %q for alert %s", c.Rule.State, c.Rule.Name))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +178,7 @@ func (c *EvalContext) GetNotificationTemplateConfig() monitor.NotificationTempla
|
||||
EndTime: c.EndTime.Format(time.RFC3339),
|
||||
Description: desc,
|
||||
Level: c.Rule.Level,
|
||||
NoDataFound: c.NoDataFound,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,5 +50,5 @@ type Notifier interface {
|
||||
Notify(evalContext *EvalContext) error
|
||||
|
||||
// ShouldNotify checks this evaluation should send an alert notification
|
||||
ShouldNotify(ctx context.Context, evalContext *EvalContext, notificationState *models.SAlertNotificationState) bool
|
||||
ShouldNotify(ctx context.Context, evalContext *EvalContext, notificationState *models.SAlertnotification) bool
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package alerting
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
@@ -48,7 +49,7 @@ func (n *notificationService) SendIfNeeded(evalCtx *EvalContext) error {
|
||||
|
||||
type notifierState struct {
|
||||
notifier Notifier
|
||||
state *models.SAlertNotificationState
|
||||
state *models.SAlertnotification
|
||||
}
|
||||
|
||||
type notifierStateSlice []*notifierState
|
||||
@@ -92,7 +93,7 @@ func (n *notificationService) sendNotifications(evalCtx *EvalContext, states not
|
||||
}
|
||||
|
||||
func (n *notificationService) getNeededNotifiers(nIds []string, evalCtx *EvalContext) (notifierStateSlice, error) {
|
||||
notis, err := models.AlertNotificationManager.GetNotificationsWithDefault(nIds)
|
||||
notis, err := models.NotificationManager.GetNotificationsWithDefault(nIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -109,13 +110,21 @@ func (n *notificationService) getNeededNotifiers(nIds []string, evalCtx *EvalCon
|
||||
Settings: obj.Settings,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Could not creat enotifier %s, error: %v", obj.GetId(), err)
|
||||
log.Errorf("Could not create notifier %s, error: %v", obj.GetId(), err)
|
||||
continue
|
||||
}
|
||||
state, err := models.AlertNotificationStateManager.GetOrCreateState(evalCtx.Ctx, evalCtx.UserCred, evalCtx.Rule.Id, obj.GetId())
|
||||
state, err := models.AlertNotificationManager.Get(evalCtx.Rule.Id, obj.GetId())
|
||||
if err != nil {
|
||||
log.Errorf("Get alert state: %v, alertId %s, notifierId: %s", err, evalCtx.Rule.Id, obj.GetId())
|
||||
continue
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
state, err = obj.AttachToAlert(evalCtx.Ctx, evalCtx.UserCred, evalCtx.Rule.Id)
|
||||
if err != nil {
|
||||
log.Errorf("Attach notification %s to alert %s error: %v", obj.GetName(), evalCtx.Rule.Id, err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
log.Errorf("Get alert state: %v, alertId %s, notifierId: %s", err, evalCtx.Rule.Id, obj.GetId())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if not.ShouldNotify(evalCtx.Ctx, evalCtx, state) {
|
||||
@@ -132,7 +141,7 @@ func (n *notificationService) getNeededNotifiers(nIds []string, evalCtx *EvalCon
|
||||
type NotifierPlugin struct {
|
||||
Type string
|
||||
Factory NotifierFactory
|
||||
ValidateCreateData func(cred mcclient.IIdentityProvider, input monitor.AlertNotificationCreateInput) (monitor.AlertNotificationCreateInput, error)
|
||||
ValidateCreateData func(cred mcclient.IIdentityProvider, input monitor.NotificationCreateInput) (monitor.NotificationCreateInput, error)
|
||||
}
|
||||
|
||||
type NotificationConfig notifydrivers.NotificationConfig
|
||||
|
||||
@@ -48,7 +48,7 @@ func NewNotifierBase(config alerting.NotificationConfig) NotifierBase {
|
||||
}
|
||||
|
||||
// ShouldNotify checks this evaluation should send an alert notification
|
||||
func (n *NotifierBase) ShouldNotify(_ context.Context, evalCtx *alerting.EvalContext, state *models.SAlertNotificationState) bool {
|
||||
func (n *NotifierBase) ShouldNotify(_ context.Context, evalCtx *alerting.EvalContext, state *models.SAlertnotification) bool {
|
||||
prevState := evalCtx.PrevAlertState
|
||||
newState := evalCtx.Rule.State
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ func init() {
|
||||
alerting.RegisterNotifier(&alerting.NotifierPlugin{
|
||||
Type: monitor.AlertNotificationTypeDingding,
|
||||
Factory: newDingdingNotifier,
|
||||
ValidateCreateData: func(cred mcclient.IIdentityProvider, input monitor.AlertNotificationCreateInput) (monitor.AlertNotificationCreateInput, error) {
|
||||
ValidateCreateData: func(cred mcclient.IIdentityProvider, input monitor.NotificationCreateInput) (monitor.NotificationCreateInput, error) {
|
||||
settings := new(monitor.NotificationSettingDingding)
|
||||
if err := input.Settings.Unmarshal(settings); err != nil {
|
||||
return input, errors.Wrap(err, "unmarshal setting")
|
||||
|
||||
@@ -34,7 +34,7 @@ func init() {
|
||||
alerting.RegisterNotifier(&alerting.NotifierPlugin{
|
||||
Type: monitor.AlertNotificationTypeFeishu,
|
||||
Factory: newFeishuNotifier,
|
||||
ValidateCreateData: func(cred mcclient.IIdentityProvider, input monitor.AlertNotificationCreateInput) (monitor.AlertNotificationCreateInput, error) {
|
||||
ValidateCreateData: func(cred mcclient.IIdentityProvider, input monitor.NotificationCreateInput) (monitor.NotificationCreateInput, error) {
|
||||
settings := new(monitor.NotificationSettingFeishu)
|
||||
if err := input.Settings.Unmarshal(settings); err != nil {
|
||||
return input, errors.Wrap(err, "unmarshal setting")
|
||||
|
||||
@@ -37,7 +37,7 @@ func init() {
|
||||
alerting.RegisterNotifier(&alerting.NotifierPlugin{
|
||||
Type: monitor.AlertNotificationTypeOneCloud,
|
||||
Factory: newOneCloudNotifier,
|
||||
ValidateCreateData: func(cred mcclient.IIdentityProvider, input monitor.AlertNotificationCreateInput) (monitor.AlertNotificationCreateInput, error) {
|
||||
ValidateCreateData: func(cred mcclient.IIdentityProvider, input monitor.NotificationCreateInput) (monitor.NotificationCreateInput, error) {
|
||||
settings := new(monitor.NotificationSettingOneCloud)
|
||||
if err := input.Settings.Unmarshal(settings); err != nil {
|
||||
return input, errors.Wrap(err, "unmarshal setting")
|
||||
@@ -99,6 +99,8 @@ func GetNotifyTemplateConfig(ctx *alerting.EvalContext) monitor.NotificationTemp
|
||||
if ctx.Rule.State == monitor.AlertStateOK {
|
||||
isRecovery = true
|
||||
topic = fmt.Sprintf("%s %s 告警已恢复", topic, ctx.GetRuleTitle())
|
||||
} else if ctx.NoDataFound {
|
||||
topic = fmt.Sprintf("%s %s 暂无数据", topic, ctx.GetRuleTitle())
|
||||
} else {
|
||||
topic = fmt.Sprintf("%s %s 发生告警", topic, ctx.GetRuleTitle())
|
||||
}
|
||||
@@ -128,7 +130,6 @@ func (oc *OneCloudNotifier) Notify(ctx *alerting.EvalContext) error {
|
||||
Msg: content,
|
||||
}
|
||||
|
||||
log.Errorf("---send msg: %s", jsonutils.Marshal(msg))
|
||||
return notify.Notifications.Send(oc.session, msg)
|
||||
}
|
||||
|
||||
|
||||
@@ -121,8 +121,16 @@ func NewRuleFromDBAlert(ruleDef *models.SAlert) (*Rule, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
model.Level = settings.Level
|
||||
model.Notifications = settings.Notifications
|
||||
model.Level = ruleDef.Level
|
||||
nIds := []string{}
|
||||
notis, err := ruleDef.GetNotifications()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, n := range notis {
|
||||
nIds = append(nIds, n.NotificationId)
|
||||
}
|
||||
model.Notifications = nIds
|
||||
// model.AlertRuleTags = ruleDef.GetTagsFromSettings()
|
||||
|
||||
for index, condition := range settings.Conditions {
|
||||
|
||||
+150
-30
@@ -21,12 +21,14 @@ import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/apis/monitor"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/monitor/validators"
|
||||
@@ -77,20 +79,49 @@ type SAlert struct {
|
||||
|
||||
Frequency int64 `nullable:"false" list:"user" create:"required" update:"user"`
|
||||
Settings jsonutils.JSONObject `nullable:"false" list:"user" create:"required" update:"user"`
|
||||
// Enabled bool `nullable:"false" default:"false" list:"user" create:"optional"`
|
||||
Level string `charset:"ascii" width:"36"nullable:"false" default:"normal" list:"user"`
|
||||
Message string `charset:"utf8" list:"user" update:"user"`
|
||||
UsedBy string `charset:"ascii" list:"user"`
|
||||
|
||||
Message string `charset:"utf8" list:"user" update:"user"`
|
||||
State string `width:"36" charset:"ascii" list:"user"`
|
||||
// Silenced bool
|
||||
ExecutionError string `charset:"utf8" list:"user"`
|
||||
For int64 `nullable:"false" list:"user"`
|
||||
ExecutionError string `charset:"utf8" list:"user"`
|
||||
For int64 `nullable:"false" list:"user"`
|
||||
EvalData jsonutils.JSONObject `list:"user" list:"user"`
|
||||
State string `width:"36" charset:"ascii" nullable:"false" default:"unknown" list:"user"`
|
||||
NoDataState string `width:"36" charset:"ascii" nullable:"false" default:"pending" list:"user"`
|
||||
ExecutionErrorState string `width:"36" charset:"ascii" nullable:"false" default:"alerting" list:"user"`
|
||||
LastStateChange time.Time `list:"user"`
|
||||
StateChanges int `default:"0" nullable:"false" list:"user"`
|
||||
}
|
||||
|
||||
EvalData jsonutils.JSONObject `list:"user"`
|
||||
LastStateChange time.Time `json:"last_state_change" list:"user"`
|
||||
StateChanges int `default:"0" nullable:"false" list:"user" json:"state_changes"`
|
||||
func (alert *SAlert) IsEnable() bool {
|
||||
return alert.Enabled.Bool()
|
||||
}
|
||||
|
||||
NoDataState string `charset:"utf8" list:"user"`
|
||||
ExecutionErrorState string `charset:"utf8" list:"user"`
|
||||
func (alert *SAlert) SetEnable() error {
|
||||
_, err := db.Update(alert, func() error {
|
||||
alert.SetEnabled(true)
|
||||
alert.State = string(monitor.AlertStatePending)
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (alert *SAlert) SetDisable() error {
|
||||
_, err := db.Update(alert, func() error {
|
||||
alert.SEnabledResourceBase.SetEnabled(false)
|
||||
alert.State = string(monitor.AlertStatePaused)
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (alert *SAlert) SetUsedBy(usedBy string) error {
|
||||
_, err := db.Update(alert, func() error {
|
||||
alert.UsedBy = usedBy
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (alert *SAlert) SetTitle(ctx context.Context, t string) error {
|
||||
@@ -251,22 +282,6 @@ func (alert *SAlert) PerformDisable(ctx context.Context, userCred mcclient.Token
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (alert *SAlert) GetNotifications() ([]SAlertNotification, error) {
|
||||
settings, err := alert.GetSettings()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get settings")
|
||||
}
|
||||
nIds := settings.Notifications
|
||||
notis, err := AlertNotificationManager.GetNotifications(nIds)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return notis, nil
|
||||
}
|
||||
|
||||
const (
|
||||
ErrAlertChannotChangeStateOnPaused = errors.Error("Cannot change state on pause alert")
|
||||
)
|
||||
@@ -296,10 +311,115 @@ func (alert *SAlert) SetState(input AlertSetStateInput) error {
|
||||
}
|
||||
|
||||
func (alert *SAlert) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input monitor.AlertUpdateInput) (*jsonutils.JSONDict, error) {
|
||||
if input.Enabled == nil {
|
||||
enable := true
|
||||
input.Enabled = &enable
|
||||
if input.Settings != nil {
|
||||
if err := jsonutils.Update(alert.Settings, jsonutils.Marshal(input.Settings)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := jsonutils.Update(input.Settings, alert.Settings); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
input.Settings = setAlertDefaultSetting(input.Settings, "")
|
||||
return alert.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.JSON(input))
|
||||
}
|
||||
|
||||
func (alert *SAlert) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
input := new(monitor.AlertUpdateInput)
|
||||
if err := data.Unmarshal(input); err != nil {
|
||||
log.Errorf("update unmarshal error: %v", err)
|
||||
return
|
||||
}
|
||||
if _, err := db.Update(alert, func() error {
|
||||
alert.Settings = jsonutils.Marshal(input)
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Errorf("update setting error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (alert *SAlert) IsAttachNotification(noti *SNotification) (bool, error) {
|
||||
q := AlertNotificationManager.Query().Equals("notification_id", noti.GetId()).Equals("alert_id", alert.GetId())
|
||||
cnt, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return cnt > 0, nil
|
||||
}
|
||||
|
||||
func (alert *SAlert) GetNotificationsQuery() *sqlchemy.SQuery {
|
||||
return AlertNotificationManager.Query().Equals("alert_id", alert.GetId())
|
||||
}
|
||||
|
||||
func (alert *SAlert) GetNotifications() ([]SAlertnotification, error) {
|
||||
notis := make([]SAlertnotification, 0)
|
||||
q := alert.GetNotificationsQuery().Asc("index")
|
||||
if err := db.FetchModelObjects(AlertNotificationManager, q, ¬is); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return notis, nil
|
||||
}
|
||||
|
||||
func (alert *SAlert) getNotificationIndex() (int8, error) {
|
||||
notis, err := alert.GetNotifications()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
var max uint
|
||||
for i := 0; i < len(notis); i++ {
|
||||
if uint(notis[i].Index) > max {
|
||||
max = uint(notis[i].Index)
|
||||
}
|
||||
}
|
||||
|
||||
idxs := make([]int, max+1)
|
||||
for i := 0; i < len(notis); i++ {
|
||||
idxs[notis[i].Index] = 1
|
||||
}
|
||||
|
||||
// find first idx not set
|
||||
for i := 0; i < len(idxs); i++ {
|
||||
if idxs[i] != 1 {
|
||||
return int8(i), nil
|
||||
}
|
||||
}
|
||||
|
||||
return int8(max + 1), nil
|
||||
}
|
||||
|
||||
func (alert *SAlert) AttachNotification(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
noti *SNotification,
|
||||
state monitor.AlertNotificationStateType,
|
||||
usedBy string) (*SAlertnotification, error) {
|
||||
attached, err := alert.IsAttachNotification(noti)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if attached {
|
||||
return nil, httperrors.NewNotAcceptableError("alert already attached to notification")
|
||||
}
|
||||
|
||||
defer lockman.ReleaseObject(ctx, alert)
|
||||
lockman.LockObject(ctx, alert)
|
||||
alertNoti := new(SAlertnotification)
|
||||
alertNoti.AlertId = alert.GetId()
|
||||
alertNoti.Index, err = alert.getNotificationIndex()
|
||||
alertNoti.NotificationId = noti.GetId()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alertNoti.State = string(state)
|
||||
alertNoti.UsedBy = usedBy
|
||||
if err := alertNoti.DoSave(ctx, userCred); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return alertNoti, nil
|
||||
}
|
||||
|
||||
func (alert *SAlert) SetFor(forTime time.Duration) error {
|
||||
_, err := db.Update(alert, func() error {
|
||||
alert.For = int64(forTime)
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
|
||||
type SAlertJointsManager struct {
|
||||
db.SVirtualJointResourceBaseManager
|
||||
}
|
||||
|
||||
func NewAlertJointsManager(
|
||||
dt interface{}, tableName string,
|
||||
keyword string, keywordPlural string,
|
||||
slave db.IVirtualModelManager) SAlertJointsManager {
|
||||
return SAlertJointsManager{
|
||||
db.NewVirtualJointResourceBaseManager(
|
||||
dt, tableName, keyword, keywordPlural, AlertManager, slave),
|
||||
}
|
||||
}
|
||||
|
||||
type SAlertJointsBase struct {
|
||||
db.SVirtualJointResourceBase
|
||||
|
||||
AlertId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
}
|
||||
|
||||
func (b *SAlertJointsBase) getAlert() *SAlert {
|
||||
alert, _ := AlertManager.GetAlert(b.AlertId)
|
||||
return alert
|
||||
}
|
||||
|
||||
func (man *SAlertJointsManager) GetMasterFieldName() string {
|
||||
return "alert_id"
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/monitor"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
const (
|
||||
AlertNotificationUsedByMeterAlert = "meter_alert"
|
||||
AlertNotificationUsedByNodeAlert = "node_alert"
|
||||
)
|
||||
|
||||
type SAlertNotificationManager struct {
|
||||
SAlertJointsManager
|
||||
}
|
||||
|
||||
var AlertNotificationManager *SAlertNotificationManager
|
||||
|
||||
func init() {
|
||||
db.InitManager(func() {
|
||||
AlertNotificationManager = &SAlertNotificationManager{
|
||||
SAlertJointsManager: NewAlertJointsManager(
|
||||
SAlertnotification{},
|
||||
"alertnotifications_tbl",
|
||||
"alertnotification",
|
||||
"alertnotifications",
|
||||
NotificationManager),
|
||||
}
|
||||
AlertNotificationManager.SetVirtualObject(AlertNotificationManager)
|
||||
AlertNotificationManager.TableSpec().AddIndex(true, "notification_id", "alert_id")
|
||||
})
|
||||
}
|
||||
|
||||
type SAlertnotification struct {
|
||||
SAlertJointsBase
|
||||
NotificationId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
State string `nullable:"false" list:"user" create:"required"`
|
||||
Index int8 `nullable:"false" default:"0" list:"user" list:"user" update:"user"`
|
||||
UsedBy string `width:"36" charset:"ascii" nullable:"true" list:"user"`
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) GetSlaveFieldName() string {
|
||||
return "notification_id"
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) Get(alertId string, notiId string) (*SAlertnotification, error) {
|
||||
q := man.Query().Equals("alert_id", alertId).Equals("notification_id", notiId)
|
||||
obj := new(SAlertnotification)
|
||||
err := q.First(obj)
|
||||
obj.SetModelManager(man, obj)
|
||||
return obj, err
|
||||
}
|
||||
|
||||
func (joint *SAlertnotification) DoSave(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if err := AlertNotificationManager.TableSpec().Insert(joint); err != nil {
|
||||
return err
|
||||
}
|
||||
joint.SetModelManager(AlertNotificationManager, joint)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (joint *SAlertnotification) Master() db.IStandaloneModel {
|
||||
return db.JointMaster(joint)
|
||||
}
|
||||
|
||||
func (joint *SAlertnotification) Slave() db.IStandaloneModel {
|
||||
return db.JointSlave(joint)
|
||||
}
|
||||
|
||||
func (joint *SAlertnotification) GetNotification() (*SNotification, error) {
|
||||
noti, err := NotificationManager.GetNotification(joint.NotificationId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return noti, nil
|
||||
}
|
||||
|
||||
func (joint *SAlertnotification) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, joint)
|
||||
}
|
||||
|
||||
func (joint *SAlertnotification) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DetachJoint(ctx, userCred, joint)
|
||||
}
|
||||
|
||||
func (joint *SAlertnotification) GetUsedBy() string {
|
||||
return joint.UsedBy
|
||||
}
|
||||
|
||||
func (state *SAlertnotification) SetToPending() error {
|
||||
return state.setState(monitor.AlertNotificationStatePending)
|
||||
}
|
||||
|
||||
func (state *SAlertnotification) SetToCompleted() error {
|
||||
return state.setState(monitor.AlertNotificationStateCompleted)
|
||||
}
|
||||
|
||||
func (state *SAlertnotification) setState(changeState monitor.AlertNotificationStateType) error {
|
||||
_, err := db.Update(state, func() error {
|
||||
state.State = string(changeState)
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (state *SAlertnotification) GetState() monitor.AlertNotificationStateType {
|
||||
return monitor.AlertNotificationStateType(state.State)
|
||||
}
|
||||
@@ -48,7 +48,8 @@ func init() {
|
||||
type IMeterAlertDriver interface {
|
||||
GetType() string
|
||||
GetName() string
|
||||
ToAlertCreateInput(input monitor.MeterAlertCreateInput, notificatoins []string, allAccountIds []string) monitor.AlertCreateInput
|
||||
GetFor() time.Duration
|
||||
ToAlertCreateInput(input monitor.MeterAlertCreateInput, dsId string, allAccountIds []string, level string) monitor.AlertCreateInput
|
||||
}
|
||||
|
||||
type SMeterAlertManager struct {
|
||||
@@ -139,18 +140,6 @@ func (man *SMeterAlertManager) ValidateCreateData(
|
||||
if _, err := time.ParseDuration(data.Period); err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Invalid period format: %s", data.Period)
|
||||
}
|
||||
if data.Recipients == "" {
|
||||
return nil, httperrors.NewInputParameterError("recipients is empty")
|
||||
}
|
||||
notification, err := man.CreateNotification(ctx, userCred, data.Type, data.Channel, data.Recipients)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create notification")
|
||||
}
|
||||
|
||||
if data.ProjectId == "" {
|
||||
return nil, httperrors.NewInputParameterError("project_id is empty")
|
||||
}
|
||||
|
||||
drv := man.GetDriver(data.Type)
|
||||
if drv == nil {
|
||||
return nil, httperrors.NewInputParameterError("not support type %q", data.Type)
|
||||
@@ -166,15 +155,22 @@ func (man *SMeterAlertManager) ValidateCreateData(
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
alertInput := drv.ToAlertCreateInput(
|
||||
data, []string{notification.GetId()},
|
||||
allAccountIds)
|
||||
if data.Recipients == "" {
|
||||
return nil, httperrors.NewInputParameterError("recipients is empty")
|
||||
}
|
||||
|
||||
ds, err := DataSourceManager.GetDefaultSource()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
alertInput := drv.ToAlertCreateInput(data, ds.GetId(), allAccountIds, data.Level)
|
||||
alertInput, err = AlertManager.ValidateCreateData(ctx, userCred, ownerId, query, alertInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Name = name
|
||||
data.AlertCreateInput = &alertInput
|
||||
data.AlertCreateInput = alertInput
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
@@ -188,16 +184,23 @@ func (_ *sMeterDailyFee) GetName() string {
|
||||
return "日消费"
|
||||
}
|
||||
|
||||
func (_ *sMeterDailyFee) GetFor() time.Duration {
|
||||
return 12 * time.Hour
|
||||
}
|
||||
|
||||
func (f *sMeterDailyFee) ToAlertCreateInput(
|
||||
input monitor.MeterAlertCreateInput,
|
||||
notifications []string,
|
||||
dsId string,
|
||||
allAccountIds []string,
|
||||
level string,
|
||||
) monitor.AlertCreateInput {
|
||||
freq, _ := time.ParseDuration(input.Window)
|
||||
ret := monitor.AlertCreateInput{
|
||||
Name: f.GetName(),
|
||||
Level: level,
|
||||
Frequency: int64(freq / time.Second),
|
||||
Settings: GetMeterAlertSetting(input, notifications,
|
||||
Settings: GetMeterAlertSetting(input,
|
||||
dsId,
|
||||
"account_daily_resfee",
|
||||
"meter_db", allAccountIds, "sumDate"),
|
||||
}
|
||||
@@ -214,16 +217,23 @@ func (_ *sMeterMonthFee) GetName() string {
|
||||
return "月消费"
|
||||
}
|
||||
|
||||
func (_ *sMeterMonthFee) GetFor() time.Duration {
|
||||
return 24 * time.Hour
|
||||
}
|
||||
|
||||
func (f *sMeterMonthFee) ToAlertCreateInput(
|
||||
input monitor.MeterAlertCreateInput,
|
||||
notifications []string,
|
||||
dsId string,
|
||||
allAccountIds []string,
|
||||
level string,
|
||||
) monitor.AlertCreateInput {
|
||||
freq, _ := time.ParseDuration(input.Window)
|
||||
ret := monitor.AlertCreateInput{
|
||||
Name: f.GetName(),
|
||||
Level: level,
|
||||
Frequency: int64(freq / time.Second),
|
||||
Settings: GetMeterAlertSetting(input, notifications,
|
||||
Settings: GetMeterAlertSetting(input,
|
||||
dsId,
|
||||
"account_month_resfee",
|
||||
"meter_db", allAccountIds, "sumMonth"),
|
||||
}
|
||||
@@ -232,7 +242,7 @@ func (f *sMeterMonthFee) ToAlertCreateInput(
|
||||
|
||||
func GetMeterAlertSetting(
|
||||
input monitor.MeterAlertCreateInput,
|
||||
ns []string,
|
||||
dsId string,
|
||||
measurement string,
|
||||
db string,
|
||||
accountIds []string,
|
||||
@@ -240,16 +250,15 @@ func GetMeterAlertSetting(
|
||||
) monitor.AlertSetting {
|
||||
q, reducer, eval := GetMeterAlertQuery(input, measurement, db, accountIds, groupByStr)
|
||||
return monitor.AlertSetting{
|
||||
Level: input.Level,
|
||||
Notifications: ns,
|
||||
Conditions: []monitor.AlertCondition{
|
||||
{
|
||||
Type: "query",
|
||||
Operator: "and",
|
||||
Query: monitor.AlertQuery{
|
||||
Model: q,
|
||||
From: input.Period,
|
||||
To: "now",
|
||||
Model: q,
|
||||
From: input.Period,
|
||||
To: "now",
|
||||
DataSourceId: dsId,
|
||||
},
|
||||
Reducer: reducer,
|
||||
Evaluator: eval,
|
||||
@@ -306,7 +315,7 @@ func GetMeterAlertQuery(
|
||||
})
|
||||
}
|
||||
|
||||
log.Debugf("==alertType: %s", alertType)
|
||||
log.Debugf("meteralert alertType: %s", alertType)
|
||||
|
||||
if input.ProjectId != "" {
|
||||
filters = append(filters, monitor.MetricQueryTag{
|
||||
@@ -344,6 +353,18 @@ func (man *SMeterAlertManager) GetAlert(id string) (*SMeterAlert, error) {
|
||||
return obj.(*SMeterAlert), nil
|
||||
}
|
||||
|
||||
func (man *SMeterAlertManager) ListItemFilter(
|
||||
ctx context.Context, q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query monitor.MeterAlertListInput) (*sqlchemy.SQuery, error) {
|
||||
q, err := AlertManager.ListItemFilter(ctx, q, userCred, monitor.AlertListInput{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q.Equals("used_by", AlertNotificationUsedByMeterAlert)
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (man *SMeterAlertManager) CustomizeFilterList(
|
||||
ctx context.Context, q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential, query jsonutils.JSONObject) (
|
||||
@@ -397,6 +418,17 @@ func (man *SMeterAlertManager) CustomizeFilterList(
|
||||
return filters, nil
|
||||
}
|
||||
|
||||
func (alert *SMeterAlert) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
if err := alert.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data); err != nil {
|
||||
return err
|
||||
}
|
||||
input := new(monitor.MeterAlertCreateInput)
|
||||
if err := data.Unmarshal(input); err != nil {
|
||||
return err
|
||||
}
|
||||
return alert.SV1Alert.CustomizeCreate(ctx, userCred, input.Type, input.Channel, input.Recipients, AlertNotificationUsedByMeterAlert)
|
||||
}
|
||||
|
||||
func (alert *SMeterAlert) setType(ctx context.Context, userCred mcclient.TokenCredential, t string) error {
|
||||
return alert.SetMetadata(ctx, MeterAlertMetadataType, t, userCred)
|
||||
}
|
||||
@@ -458,12 +490,16 @@ func (alert *SMeterAlert) PostCreate(ctx context.Context,
|
||||
log.Errorf("set project_id: %v", err)
|
||||
}
|
||||
}
|
||||
forTime := MeterAlertManager.GetDriver(alert.getType()).GetFor()
|
||||
if err := alert.SetFor(forTime); err != nil {
|
||||
log.Errorf("set for error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (alert *SMeterAlert) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (monitor.MeterAlertDetails, error) {
|
||||
var err error
|
||||
out := monitor.MeterAlertDetails{}
|
||||
commonDetails, err := alert.SV1Alert.GetExtraDetails(ctx, userCred, query, isList)
|
||||
commonDetails, err := alert.SV1Alert.GetExtraDetails(ctx, userCred, query, isList, AlertNotificationUsedByMeterAlert)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
@@ -476,3 +512,66 @@ func (alert *SMeterAlert) GetExtraDetails(ctx context.Context, userCred mcclient
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (alert *SMeterAlert) ValidateUpdateData(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, input monitor.MeterAlertUpdateInput) (*jsonutils.JSONDict, error) {
|
||||
ret := new(monitor.AlertUpdateInput)
|
||||
details, err := alert.GetExtraDetails(ctx, userCred, query, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if input.Threshold != nil && *input.Threshold != details.Threshold {
|
||||
details.Threshold = *input.Threshold
|
||||
}
|
||||
|
||||
if input.Comparator != nil && *input.Comparator != details.Comparator {
|
||||
details.Comparator = *input.Comparator
|
||||
}
|
||||
|
||||
ds, err := DataSourceManager.GetDefaultSource()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get default data source")
|
||||
}
|
||||
// hack: update notification here
|
||||
if err := alert.UpdateNotification(AlertNotificationUsedByMeterAlert, input.Channel, input.Recipients); err != nil {
|
||||
return nil, errors.Wrap(err, "update notification")
|
||||
}
|
||||
allAccountIds := []string{}
|
||||
if details.AccountId == "" {
|
||||
allAccountIds, err = MeterAlertManager.getAllBillAccountIds(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
tmpS := alert.getUpdateSetting(details, ds.GetId(), allAccountIds)
|
||||
ret.Settings = &tmpS
|
||||
return alert.SAlert.ValidateUpdateData(ctx, userCred, query, *ret)
|
||||
}
|
||||
|
||||
func (alert *SMeterAlert) getUpdateSetting(details monitor.MeterAlertDetails, dsId string, accountIds []string) monitor.AlertSetting {
|
||||
drv := MeterAlertManager.GetDriver(alert.getType())
|
||||
input := monitor.MeterAlertCreateInput{
|
||||
ResourceAlertV1CreateInput: monitor.ResourceAlertV1CreateInput{
|
||||
Period: details.Period,
|
||||
Window: details.Window,
|
||||
Comparator: details.Comparator,
|
||||
Threshold: details.Threshold,
|
||||
Channel: details.Channel,
|
||||
Recipients: details.Recipients,
|
||||
},
|
||||
Type: details.Type,
|
||||
Provider: details.Provider,
|
||||
ProjectId: details.ProjectId,
|
||||
AccountId: details.AccountId,
|
||||
}
|
||||
input.Level = details.Level
|
||||
out := drv.ToAlertCreateInput(input, dsId, accountIds, details.Level)
|
||||
return out.Settings
|
||||
}
|
||||
|
||||
func (alert *SMeterAlert) CustomizeDelete(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return alert.SV1Alert.CustomizeDelete(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
@@ -78,9 +78,9 @@ func (v1man *SV1AlertManager) CreateNotification(
|
||||
userCred mcclient.TokenCredential,
|
||||
alertName string,
|
||||
channel string,
|
||||
recipients string) (*SAlertNotification, error) {
|
||||
recipients string) (*SNotification, error) {
|
||||
userIds := strings.Split(recipients, ",")
|
||||
return AlertNotificationManager.CreateOneCloudNotification(ctx, userCred, alertName, channel, userIds)
|
||||
return NotificationManager.CreateOneCloudNotification(ctx, userCred, alertName, channel, userIds)
|
||||
}
|
||||
|
||||
func (man *SNodeAlertManager) ValidateCreateData(
|
||||
@@ -107,10 +107,6 @@ func (man *SNodeAlertManager) ValidateCreateData(
|
||||
if data.Recipients == "" {
|
||||
return nil, httperrors.NewInputParameterError("recipients is empty")
|
||||
}
|
||||
notification, err := man.CreateNotification(ctx, userCred, data.Metric, data.Channel, data.Recipients)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create notification")
|
||||
}
|
||||
if data.NodeId == "" {
|
||||
return nil, httperrors.NewInputParameterError("node_id is empty")
|
||||
}
|
||||
@@ -123,12 +119,12 @@ func (man *SNodeAlertManager) ValidateCreateData(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alertInput := data.ToAlertCreateInput(name, field, measurement, "telegraf", []string{notification.GetId()})
|
||||
alertInput := data.ToAlertCreateInput(name, field, measurement, "telegraf")
|
||||
alertInput, err = AlertManager.ValidateCreateData(ctx, userCred, ownerId, query, alertInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.AlertCreateInput = &alertInput
|
||||
data.AlertCreateInput = alertInput
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
@@ -187,11 +183,16 @@ func (man *SNodeAlertManager) ValidateListConditions(ctx context.Context, userCr
|
||||
return query, nil
|
||||
}
|
||||
|
||||
func (man *SV1AlertManager) ListItemFilter(
|
||||
func (man *SNodeAlertManager) ListItemFilter(
|
||||
ctx context.Context, q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query monitor.NodeAlertListInput) (*sqlchemy.SQuery, error) {
|
||||
return AlertManager.ListItemFilter(ctx, q, userCred, query.ToAlertListInput())
|
||||
q, err := AlertManager.ListItemFilter(ctx, q, userCred, query.ToAlertListInput())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q.Equals("used_by", AlertNotificationUsedByNodeAlert)
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (man *SNodeAlertManager) GetAlert(id string) (*SNodeAlert, error) {
|
||||
@@ -236,7 +237,7 @@ func (man *SNodeAlertManager) CustomizeFilterList(
|
||||
}
|
||||
mF := func(obj *SNodeAlert) (bool, error) {
|
||||
settings := new(monitor.AlertSetting)
|
||||
if err := obj.Settings.Unmarshal(settings, "settings"); err != nil {
|
||||
if err := obj.Settings.Unmarshal(settings); err != nil {
|
||||
return false, errors.Wrapf(err, "alert %s unmarshal", obj.GetId())
|
||||
}
|
||||
for _, s := range settings.Conditions {
|
||||
@@ -273,6 +274,38 @@ func (man *SNodeAlertManager) CustomizeFilterList(
|
||||
return filters, nil
|
||||
}
|
||||
|
||||
func (alert *SV1Alert) CustomizeCreate(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
notiName, channel, recipients, usedBy string) error {
|
||||
noti, err := NodeAlertManager.CreateNotification(ctx, userCred, notiName, channel, recipients)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create notification")
|
||||
}
|
||||
if alert.Id == "" {
|
||||
alert.Id = db.DefaultUUIDGenerator()
|
||||
}
|
||||
alert.UsedBy = usedBy
|
||||
_, err = alert.AttachNotification(
|
||||
ctx, userCred, noti,
|
||||
monitor.AlertNotificationStateUnknown,
|
||||
usedBy)
|
||||
return err
|
||||
}
|
||||
|
||||
func (alert *SNodeAlert) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
if err := alert.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := alert.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data); err != nil {
|
||||
return err
|
||||
}
|
||||
input := new(monitor.NodeAlertCreateInput)
|
||||
if err := data.Unmarshal(input); err != nil {
|
||||
return err
|
||||
}
|
||||
return alert.SV1Alert.CustomizeCreate(ctx, userCred, input.Metric, input.Channel, input.Recipients, AlertNotificationUsedByNodeAlert)
|
||||
}
|
||||
|
||||
func (alert *SNodeAlert) getNodeId() string {
|
||||
return alert.GetMetadata(NodeAlertMetadataNodeId, nil)
|
||||
}
|
||||
@@ -320,7 +353,13 @@ func (alert *SNodeAlert) PostCreate(ctx context.Context,
|
||||
}
|
||||
}
|
||||
|
||||
func (alert *SV1Alert) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (monitor.AlertV1Details, error) {
|
||||
func (alert *SV1Alert) GetExtraDetails(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
isList bool,
|
||||
usedBy string,
|
||||
) (monitor.AlertV1Details, error) {
|
||||
var err error
|
||||
out := monitor.AlertV1Details{}
|
||||
out.VirtualResourceDetails, err = alert.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query, isList)
|
||||
@@ -349,15 +388,23 @@ func (alert *SV1Alert) GetExtraDetails(ctx context.Context, userCred mcclient.To
|
||||
case "lt":
|
||||
cmp = "<="
|
||||
}
|
||||
out.Level = setting.Level
|
||||
out.Level = alert.Level
|
||||
out.Comparator = cmp
|
||||
out.Threshold = cond.Evaluator.Params[0]
|
||||
out.Period = cond.Query.From
|
||||
|
||||
notification := alert.GetNotificationBySetting(setting)
|
||||
if notification != nil {
|
||||
out.Recipients = strings.Join(notification.UserIds, ",")
|
||||
out.Channel = notification.Channel
|
||||
noti, err := alert.GetNotification(usedBy)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
if noti != nil {
|
||||
out.NotifierId = noti.GetId()
|
||||
settings := new(monitor.NotificationSettingOneCloud)
|
||||
if err := noti.Settings.Unmarshal(settings); err != nil {
|
||||
return out, err
|
||||
}
|
||||
out.Recipients = strings.Join(settings.UserIds, ",")
|
||||
out.Channel = settings.Channel
|
||||
}
|
||||
|
||||
q := cond.Query
|
||||
@@ -367,20 +414,13 @@ func (alert *SV1Alert) GetExtraDetails(ctx context.Context, userCred mcclient.To
|
||||
out.Measurement = measurement
|
||||
out.Field = field
|
||||
out.DB = db
|
||||
noti, err := alert.GetNotification()
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
if noti != nil {
|
||||
out.NotifierId = noti.GetId()
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (alert *SNodeAlert) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (monitor.NodeAlertDetails, error) {
|
||||
var err error
|
||||
out := monitor.NodeAlertDetails{}
|
||||
commonDetails, err := alert.SV1Alert.GetExtraDetails(ctx, userCred, query, isList)
|
||||
commonDetails, err := alert.SV1Alert.GetExtraDetails(ctx, userCred, query, isList, AlertNotificationUsedByNodeAlert)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
@@ -402,26 +442,24 @@ func (alert *SNodeAlert) GetExtraDetails(ctx context.Context, userCred mcclient.
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (alert *SV1Alert) GetNotification() (*SAlertNotification, error) {
|
||||
setting, err := alert.GetSettings()
|
||||
func (alert *SV1Alert) GetNotification(usedby string) (*SNotification, error) {
|
||||
alertNotis, err := alert.GetNotifications()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nIds := setting.Notifications
|
||||
if len(nIds) == 0 {
|
||||
if len(alertNotis) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
// only get first notification setting
|
||||
nId := nIds[0]
|
||||
obj, err := AlertNotificationManager.GetNotification(nId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Get notificatoin %s", nId)
|
||||
for _, an := range alertNotis {
|
||||
if an.GetUsedBy() == usedby {
|
||||
return an.GetNotification()
|
||||
}
|
||||
}
|
||||
return obj, nil
|
||||
return nil, httperrors.NewNotFoundError("not found alert notification used by %s", usedby)
|
||||
}
|
||||
|
||||
func (alert *SV1Alert) UpdateNotification(channel, recipients *string) error {
|
||||
obj, err := alert.GetNotification()
|
||||
func (alert *SV1Alert) UpdateNotification(usedBy string, channel, recipients *string) error {
|
||||
obj, err := alert.GetNotification(usedBy)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Get notification when update")
|
||||
}
|
||||
@@ -445,30 +483,7 @@ func (alert *SV1Alert) UpdateNotification(channel, recipients *string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (alert *SV1Alert) GetNotificationBySetting(setting *monitor.AlertSetting) *monitor.NotificationSettingOneCloud {
|
||||
nIds := setting.Notifications
|
||||
if len(nIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
// only get first notification setting
|
||||
nId := nIds[0]
|
||||
obj, err := AlertNotificationManager.GetNotification(nId)
|
||||
if err != nil {
|
||||
log.Errorf("Get notification by %s: %v", nId, err)
|
||||
return nil
|
||||
}
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
ocSetting := new(monitor.NotificationSettingOneCloud)
|
||||
if err := obj.Settings.Unmarshal(ocSetting); err != nil {
|
||||
log.Errorf("Unmarshal notification %s setting: %v", nId, err)
|
||||
return nil
|
||||
}
|
||||
return ocSetting
|
||||
}
|
||||
|
||||
func (alert *SNodeAlert) CustomizeDelete(
|
||||
func (alert *SV1Alert) CustomizeDelete(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
notis, err := alert.GetNotifications()
|
||||
@@ -476,10 +491,19 @@ func (alert *SNodeAlert) CustomizeDelete(
|
||||
return err
|
||||
}
|
||||
for _, noti := range notis {
|
||||
if err := noti.CustomizeDelete(ctx, userCred, query, data); err != nil {
|
||||
conf, err := noti.GetNotification()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := noti.Delete(ctx, userCred); err != nil {
|
||||
if !conf.IsDefault {
|
||||
if err := conf.CustomizeDelete(ctx, userCred, query, data); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := conf.Delete(ctx, userCred); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := noti.Detach(ctx, userCred); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -498,7 +522,6 @@ func (alert *SNodeAlert) ValidateUpdateData(
|
||||
nameChange := false
|
||||
if input.NodeId != nil && *input.NodeId != details.NodeId {
|
||||
nameChange = true
|
||||
ret.ResourceId = input.NodeId
|
||||
details.NodeId = *input.NodeId
|
||||
if err := alert.setNodeId(ctx, userCred, details.NodeId); err != nil {
|
||||
return nil, err
|
||||
@@ -506,7 +529,6 @@ func (alert *SNodeAlert) ValidateUpdateData(
|
||||
}
|
||||
if input.Type != nil && *input.Type != details.Type {
|
||||
nameChange = true
|
||||
ret.ResourceType = input.Type
|
||||
details.Type = *input.Type
|
||||
if err := alert.setType(ctx, userCred, details.Type); err != nil {
|
||||
return nil, err
|
||||
@@ -573,15 +595,10 @@ func (alert *SNodeAlert) ValidateUpdateData(
|
||||
return nil, errors.Wrap(err, "get default data source")
|
||||
}
|
||||
// hack: update notification here
|
||||
if err := alert.UpdateNotification(input.Channel, input.Recipients); err != nil {
|
||||
if err := alert.UpdateNotification(AlertNotificationUsedByNodeAlert, input.Channel, input.Recipients); err != nil {
|
||||
return nil, errors.Wrap(err, "update notification")
|
||||
}
|
||||
tmpS := alert.getUpdateSetting(name, details, ds.GetId())
|
||||
os, err := alert.GetSettings()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get origin setting")
|
||||
}
|
||||
tmpS.Notifications = os.Notifications
|
||||
ret.Settings = &tmpS
|
||||
return alert.SAlert.ValidateUpdateData(ctx, userCred, query, ret)
|
||||
}
|
||||
@@ -597,7 +614,6 @@ func (alert *SNodeAlert) getUpdateSetting(
|
||||
Window: details.Window,
|
||||
Comparator: details.Comparator,
|
||||
Threshold: details.Threshold,
|
||||
Level: details.Level,
|
||||
Channel: details.Channel,
|
||||
Recipients: details.Recipients,
|
||||
},
|
||||
@@ -605,7 +621,14 @@ func (alert *SNodeAlert) getUpdateSetting(
|
||||
Type: details.Type,
|
||||
NodeId: details.NodeId,
|
||||
}
|
||||
out := data.ToAlertCreateInput(name, details.Field, details.Measurement, details.DB, []string{details.NotifierId})
|
||||
data.Level = details.Level
|
||||
out := data.ToAlertCreateInput(name, details.Field, details.Measurement, details.DB)
|
||||
out.Settings = *setAlertDefaultSetting(&out.Settings, dsId)
|
||||
return out.Settings
|
||||
}
|
||||
|
||||
func (alert *SNodeAlert) CustomizeDelete(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return alert.SV1Alert.CustomizeDelete(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -31,16 +30,14 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
AlertNotificationManager *SAlertNotificationManager
|
||||
AlertNotificationStateManager *SAlertNotificationStateManager
|
||||
NotificationManager *SNotificationManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
AlertNotificationManager = NewAlertNotificationManager()
|
||||
AlertNotificationStateManager = NewAlertNotificationStateManager()
|
||||
NotificationManager = NewNotificationManager()
|
||||
}
|
||||
|
||||
type SAlertNotificationManager struct {
|
||||
type SNotificationManager struct {
|
||||
db.SVirtualResourceBaseManager
|
||||
}
|
||||
|
||||
@@ -48,11 +45,11 @@ type SAlertNotificationStateManager struct {
|
||||
db.SStandaloneResourceBaseManager
|
||||
}
|
||||
|
||||
func NewAlertNotificationManager() *SAlertNotificationManager {
|
||||
man := &SAlertNotificationManager{
|
||||
func NewNotificationManager() *SNotificationManager {
|
||||
man := &SNotificationManager{
|
||||
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
|
||||
SAlertNotification{},
|
||||
"alert_notifications_tbl",
|
||||
SNotification{},
|
||||
"notifications_tbl",
|
||||
"alert_notification",
|
||||
"alert_notifications",
|
||||
),
|
||||
@@ -61,20 +58,7 @@ func NewAlertNotificationManager() *SAlertNotificationManager {
|
||||
return man
|
||||
}
|
||||
|
||||
func NewAlertNotificationStateManager() *SAlertNotificationStateManager {
|
||||
man := &SAlertNotificationStateManager{
|
||||
SStandaloneResourceBaseManager: db.NewStandaloneResourceBaseManager(
|
||||
SAlertNotificationState{},
|
||||
"alert_notification_states_tbl",
|
||||
"alert_notification_state",
|
||||
"alert_notification_states",
|
||||
),
|
||||
}
|
||||
man.SetVirtualObject(man)
|
||||
return man
|
||||
}
|
||||
|
||||
type SAlertNotification struct {
|
||||
type SNotification struct {
|
||||
db.SVirtualResourceBase
|
||||
|
||||
Type string `nullable:"false" list:"user" create:"required"`
|
||||
@@ -85,15 +69,7 @@ type SAlertNotification struct {
|
||||
Settings jsonutils.JSONObject `nullable:"false" list:"user" create:"required" update:"user"`
|
||||
}
|
||||
|
||||
type SAlertNotificationState struct {
|
||||
db.SStandaloneResourceBase
|
||||
|
||||
AlertId string `nullable:"false" list:"user" create:"required"`
|
||||
NotifierId string `nullable:"false" list:"user" create:"required"`
|
||||
State string `nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) GetPlugin(typ string) (*notifydrivers.NotifierPlugin, error) {
|
||||
func (man *SNotificationManager) GetPlugin(typ string) (*notifydrivers.NotifierPlugin, error) {
|
||||
drv, err := notifydrivers.GetPlugin(typ)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == notifydrivers.ErrUnsupportedNotificationType {
|
||||
@@ -105,7 +81,7 @@ func (man *SAlertNotificationManager) GetPlugin(typ string) (*notifydrivers.Noti
|
||||
return drv, nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) GetNotification(id string) (*SAlertNotification, error) {
|
||||
func (man *SNotificationManager) GetNotification(id string) (*SNotification, error) {
|
||||
obj, err := man.FetchById(id)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
@@ -113,11 +89,11 @@ func (man *SAlertNotificationManager) GetNotification(id string) (*SAlertNotific
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*SAlertNotification), nil
|
||||
return obj.(*SNotification), nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) GetNotifications(ids []string) ([]SAlertNotification, error) {
|
||||
objs := make([]SAlertNotification, 0)
|
||||
func (man *SNotificationManager) GetNotifications(ids []string) ([]SNotification, error) {
|
||||
objs := make([]SNotification, 0)
|
||||
notis := man.Query().SubQuery()
|
||||
q := notis.Query().Filter(sqlchemy.In(notis.Field("id"), ids))
|
||||
if err := db.FetchModelObjects(man, q, &objs); err != nil {
|
||||
@@ -129,8 +105,8 @@ func (man *SAlertNotificationManager) GetNotifications(ids []string) ([]SAlertNo
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) GetNotificationsWithDefault(ids []string) ([]SAlertNotification, error) {
|
||||
objs := make([]SAlertNotification, 0)
|
||||
func (man *SNotificationManager) GetNotificationsWithDefault(ids []string) ([]SNotification, error) {
|
||||
objs := make([]SNotification, 0)
|
||||
notis := man.Query().SubQuery()
|
||||
q := notis.Query().Filter(
|
||||
sqlchemy.OR(
|
||||
@@ -145,7 +121,7 @@ func (man *SAlertNotificationManager) GetNotificationsWithDefault(ids []string)
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, _ jsonutils.JSONObject, input monitor.AlertNotificationCreateInput) (monitor.AlertNotificationCreateInput, error) {
|
||||
func (man *SNotificationManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, _ jsonutils.JSONObject, input monitor.NotificationCreateInput) (monitor.NotificationCreateInput, error) {
|
||||
if input.Type == "" {
|
||||
return input, httperrors.NewInputParameterError("notification type is empty")
|
||||
}
|
||||
@@ -164,12 +140,12 @@ func (man *SAlertNotificationManager) ValidateCreateData(ctx context.Context, us
|
||||
return plug.ValidateCreateData(userCred, input)
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationManager) CreateOneCloudNotification(
|
||||
func (man *SNotificationManager) CreateOneCloudNotification(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
alertName string,
|
||||
channel string,
|
||||
userIds []string) (*SAlertNotification, error) {
|
||||
userIds []string) (*SNotification, error) {
|
||||
settings := &monitor.NotificationSettingOneCloud{
|
||||
Channel: channel,
|
||||
UserIds: userIds,
|
||||
@@ -178,7 +154,7 @@ func (man *SAlertNotificationManager) CreateOneCloudNotification(
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "generate name: %s", alertName)
|
||||
}
|
||||
input := &monitor.AlertNotificationCreateInput{
|
||||
input := &monitor.NotificationCreateInput{
|
||||
Name: newName,
|
||||
Type: monitor.AlertNotificationTypeOneCloud,
|
||||
Settings: jsonutils.Marshal(settings),
|
||||
@@ -187,127 +163,16 @@ func (man *SAlertNotificationManager) CreateOneCloudNotification(
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "create notification input: %s", input.JSON(input))
|
||||
}
|
||||
return obj.(*SAlertNotification), nil
|
||||
return obj.(*SNotification), nil
|
||||
}
|
||||
|
||||
func (n *SAlertNotification) GetStates() ([]SAlertNotificationState, error) {
|
||||
states := AlertNotificationStateManager.Query().SubQuery()
|
||||
q := states.Query().Filter(sqlchemy.Equals(states.Field("notifier_id"), n.GetId()))
|
||||
objs := make([]SAlertNotificationState, 0)
|
||||
if err := db.FetchModelObjects(AlertNotificationStateManager, q, &objs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
func (n *SAlertNotification) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
stats, err := n.GetStates()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, stat := range stats {
|
||||
if err := stat.Delete(ctx, userCred); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationStateManager) ValidateCreateData(
|
||||
func (n *SNotification) AttachToAlert(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
_ jsonutils.JSONObject,
|
||||
input monitor.AlertNotificationStateCreateInput) (monitor.AlertNotificationStateCreateInput, error) {
|
||||
if input.AlertId == "" {
|
||||
return input, httperrors.NewNotEmptyError("alert_id is empty")
|
||||
}
|
||||
if input.NotifierId == "" {
|
||||
return input, httperrors.NewNotEmptyError("notifier_id is empty")
|
||||
}
|
||||
var name string
|
||||
if obj, err := AlertManager.FetchById(input.AlertId); err != nil {
|
||||
return input, err
|
||||
} else {
|
||||
name = obj.GetName()
|
||||
}
|
||||
if obj, err := AlertNotificationManager.FetchById(input.NotifierId); err != nil {
|
||||
return input, err
|
||||
} else {
|
||||
name = fmt.Sprintf("%s_%s", name, obj.GetName())
|
||||
}
|
||||
name, err := db.GenerateName(man, ownerId, name)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
input.Name = name
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationStateManager) CreateState(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
input monitor.AlertNotificationStateCreateInput) (*SAlertNotificationState, error) {
|
||||
obj, err := db.DoCreate(man, ctx, userCred, nil, input.JSON(input), userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "create notification state: %s", input.JSON(input))
|
||||
}
|
||||
return obj.(*SAlertNotificationState), nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationStateManager) GetState(alertId, notifierId string) (*SAlertNotificationState, error) {
|
||||
state := man.Query().SubQuery()
|
||||
q := state.Query().Filter(sqlchemy.AND(
|
||||
sqlchemy.Equals(state.Field("alert_id"), alertId),
|
||||
sqlchemy.Equals(state.Field("notifier_id"), notifierId)))
|
||||
obj := new(SAlertNotificationState)
|
||||
err := q.First(obj)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (man *SAlertNotificationStateManager) GetOrCreateState(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
alertId string,
|
||||
notifierId string) (*SAlertNotificationState, error) {
|
||||
state, err := man.GetState(alertId, notifierId)
|
||||
alertId string) (*SAlertnotification, error) {
|
||||
alert, err := AlertManager.GetAlert(alertId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if state == nil {
|
||||
return man.CreateState(ctx, userCred, monitor.AlertNotificationStateCreateInput{
|
||||
AlertId: alertId,
|
||||
NotifierId: notifierId,
|
||||
State: monitor.AlertNotificationStateUnknown,
|
||||
})
|
||||
}
|
||||
state.SetModelManager(man, state)
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func (state *SAlertNotificationState) SetToPending() error {
|
||||
return state.setState(monitor.AlertNotificationStatePending)
|
||||
}
|
||||
|
||||
func (state *SAlertNotificationState) SetToCompleted() error {
|
||||
return state.setState(monitor.AlertNotificationStateCompleted)
|
||||
}
|
||||
|
||||
func (state *SAlertNotificationState) setState(changeState monitor.AlertNotificationStateType) error {
|
||||
_, err := db.Update(state, func() error {
|
||||
state.State = string(changeState)
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (state *SAlertNotificationState) GetState() monitor.AlertNotificationStateType {
|
||||
return monitor.AlertNotificationStateType(state.State)
|
||||
return alert.AttachNotification(ctx, userCred, n, monitor.AlertNotificationStateUnknown, "")
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ var notifierFactories = make(map[string]*NotifierPlugin)
|
||||
type NotifierPlugin struct {
|
||||
Type string
|
||||
Factory NotifierFactory
|
||||
ValidateCreateData func(cred mcclient.IIdentityProvider, input monitor.AlertNotificationCreateInput) (monitor.AlertNotificationCreateInput, error)
|
||||
ValidateCreateData func(cred mcclient.IIdentityProvider, input monitor.NotificationCreateInput) (monitor.NotificationCreateInput, error)
|
||||
}
|
||||
|
||||
func RegisterNotifier(plugin *NotifierPlugin) {
|
||||
|
||||
@@ -24,8 +24,9 @@ import (
|
||||
func InitHandlers(app *appsrv.Application) {
|
||||
db.InitAllManagers()
|
||||
|
||||
db.RegisterModelManager(db.UserCacheManager)
|
||||
db.RegisterModelManager(db.TenantCacheManager)
|
||||
db.RegisterModelManager(db.UserCacheManager)
|
||||
db.RegistUserCredCacheUpdater()
|
||||
for _, manager := range []db.IModelManager{
|
||||
db.OpsLog,
|
||||
db.Metadata,
|
||||
@@ -33,11 +34,18 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.AlertManager,
|
||||
models.NodeAlertManager,
|
||||
models.MeterAlertManager,
|
||||
models.AlertNotificationManager,
|
||||
models.AlertNotificationStateManager,
|
||||
models.NotificationManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
dispatcher.AddModelDispatcher("", app, handler)
|
||||
}
|
||||
|
||||
for _, manager := range []db.IJointModelManager{
|
||||
models.AlertNotificationManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewJointModelHandler(manager)
|
||||
dispatcher.AddJointModelDispatcher("", app, handler)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user