diff --git a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT
index 0d444f4ac4..df4b0d3d6e 100644
--- a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT
+++ b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT
@@ -6,4 +6,4 @@
资源数量:{{len .matches}}
资源名称:{{.resource_name}}
-详情地址: {{.web_url}}/commonalerts
\ No newline at end of file
+详情地址: {{.web_url}}
\ No newline at end of file
diff --git a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT.email b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT.email
index 5042b578c9..35127eeb08 100644
--- a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT.email
+++ b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@cn/DEFAULT.email
@@ -92,7 +92,7 @@
diff --git a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT
index 0cfd74b27b..723fd671e2 100644
--- a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT
+++ b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT
@@ -6,4 +6,4 @@ TriggerCondition: {{.description | unescaped}}
ResourceCount: {{len .matches}}
ResourceName: {{.resource_name}}
-WebUrl: {{.web_url}}/commonalerts
+WebUrl: {{.web_url}}
diff --git a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT.email b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT.email
index 173666faa0..2906601ab9 100644
--- a/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT.email
+++ b/build/monitor/root/opt/yunion/share/notify_templates/monitor/content@en/DEFAULT.email
@@ -33,7 +33,7 @@
font-weight: bold;
}
.td {
- width: 80px;
+ width: 120px;
padding-left: 20px;
height: 35px;
font-weight: 400;
@@ -92,8 +92,8 @@
diff --git a/pkg/monitor/alerting/eval_context.go b/pkg/monitor/alerting/eval_context.go
index 071e15ae72..68e841da14 100644
--- a/pkg/monitor/alerting/eval_context.go
+++ b/pkg/monitor/alerting/eval_context.go
@@ -128,7 +128,7 @@ func (c *EvalContext) GetCallbackURLPrefix() string {
return ""
}
url, _ := config.GetString("config", "default", "api_server")
- return url
+ return url + "/alertrecord"
}
// GetNewState returns the new state from the alert rule evaluation.
@@ -207,7 +207,11 @@ func (c *EvalContext) GetNotificationTemplateConfig() monitor.NotificationTempla
func (c *EvalContext) GetEvalMatches() []monitor.EvalMatch {
ret := make([]monitor.EvalMatch, 0)
- for _, c := range c.EvalMatches {
+ matches := c.EvalMatches
+ if !c.Firing {
+ matches = c.AlertOkEvalMatches
+ }
+ for _, c := range matches {
ret = append(ret, monitor.EvalMatch{
Condition: c.Condition,
Value: c.Value,
diff --git a/pkg/monitor/alerting/notifier.go b/pkg/monitor/alerting/notifier.go
index ad21f4b431..6bfd0ba80a 100644
--- a/pkg/monitor/alerting/notifier.go
+++ b/pkg/monitor/alerting/notifier.go
@@ -170,10 +170,23 @@ func (n *notificationService) createAlertRecordWhenNotify(evalCtx *EvalContext)
}
recordCreateInput.ResType = recordCreateInput.AlertRule.ResType
createData := recordCreateInput.JSON(recordCreateInput)
- record, err := db.DoCreate(models.AlertRecordManager, evalCtx.Ctx, evalCtx.UserCred, jsonutils.NewDict(), createData, evalCtx.UserCred)
+ alert, _ := models.CommonAlertManager.GetAlert(evalCtx.Rule.Id)
+ log.Errorf("alert:%v", jsonutils.Marshal(alert))
+ record, err := db.DoCreate(models.AlertRecordManager, evalCtx.Ctx, evalCtx.UserCred, jsonutils.NewDict(),
+ createData, evalCtx.UserCred)
if err != nil {
log.Errorf("create alert record err:%v", err)
}
+ alertData := jsonutils.Marshal(alert)
+ alertData.(*jsonutils.JSONDict).Set("project_id", jsonutils.NewString(alert.GetProjectId()))
+ db.PerformSetScope(evalCtx.Ctx, record.(*models.SAlertRecord), evalCtx.UserCred, alertData)
+ dbMatches, _ := record.(*models.SAlertRecord).GetEvalData()
+ if !evalCtx.Firing {
+ evalCtx.AlertOkEvalMatches = make([]*monitor.EvalMatch, len(dbMatches))
+ for i, _ := range dbMatches {
+ evalCtx.AlertOkEvalMatches[i] = &dbMatches[i]
+ }
+ }
record.PostCreate(evalCtx.Ctx, evalCtx.UserCred, evalCtx.UserCred, nil, createData)
}
diff --git a/pkg/monitor/alerting/notifiers/onecloud.go b/pkg/monitor/alerting/notifiers/onecloud.go
index 7e84b83198..bda0765e1a 100644
--- a/pkg/monitor/alerting/notifiers/onecloud.go
+++ b/pkg/monitor/alerting/notifiers/onecloud.go
@@ -17,7 +17,9 @@ package notifiers
import (
"context"
"fmt"
+ "strings"
+ "golang.org/x/sync/errgroup"
"golang.org/x/text/language"
"yunion.io/x/jsonutils"
@@ -32,6 +34,7 @@ import (
"yunion.io/x/onecloud/pkg/i18n"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
+ "yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/modules/notify"
"yunion.io/x/onecloud/pkg/monitor/alerting"
"yunion.io/x/onecloud/pkg/monitor/alerting/notifiers/templates"
@@ -39,7 +42,18 @@ import (
"yunion.io/x/onecloud/pkg/monitor/options"
)
+const (
+ SUFFIX = "onecloudNotifier"
+)
+
+var (
+ i18nTable = i18n.Table{}
+ i18nEnTry = i18n.NewTableEntry().EN("en").CN("cn")
+)
+
func init() {
+ i18nTable.Set(SUFFIX, i18nEnTry)
+
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: monitor.AlertNotificationTypeOneCloud,
Factory: newOneCloudNotifier,
@@ -153,16 +167,42 @@ func GetNotifyTemplateConfigOfEN(ctx *alerting.EvalContext) monitor.Notification
// Notify sends the alert notification.
func (oc *OneCloudNotifier) Notify(ctx *alerting.EvalContext, _ jsonutils.JSONObject) error {
log.Infof("Sending alert notification %s to onecloud", ctx.GetRuleTitle())
- oc.Ctx = i18n.WithLangTag(oc.Ctx, language.Chinese)
+ langIdsMap, err := GetUserLangIdsMap(oc.Setting.UserIds)
+ if err != nil {
+ return errors.Wrapf(err, "OneCloudNotifier getIds:%s userLang err", oc.Setting.UserIds)
+ }
+ langNotifyGroup, _ := errgroup.WithContext(ctx.Ctx)
+ for lang, _ := range langIdsMap {
+ ids := langIdsMap[lang]
+ langTag, _ := language.Parse(lang)
+ langStr := i18nTable.LookupByLang(langTag, SUFFIX)
+ langContext := i18n.WithLangTag(context.Background(), getLangBystr(langStr))
+ langNotifyGroup.Go(func() error {
+ return oc.notifyByContextLang(langContext, ctx, ids)
+ })
+ }
+ return langNotifyGroup.Wait()
+}
+
+func getLangBystr(str string) language.Tag {
+ for lang, val := range i18nEnTry {
+ if val == str {
+ return lang
+ }
+ }
+ return language.English
+}
+
+func (oc *OneCloudNotifier) notifyByContextLang(ctx context.Context, evalCtx *alerting.EvalContext, uids []string) error {
var config monitor.NotificationTemplateConfig
- lang := i18n.Lang(oc.Ctx)
+ lang := i18n.Lang(ctx)
switch lang {
case language.English:
- config = GetNotifyTemplateConfigOfEN(ctx)
+ config = GetNotifyTemplateConfigOfEN(evalCtx)
default:
- config = GetNotifyTemplateConfig(ctx)
+ config = GetNotifyTemplateConfig(evalCtx)
}
- oc.filterMatchTagsForConfig(&config)
+ oc.filterMatchTagsForConfig(&config, ctx)
contentConfig := oc.buildContent(config)
@@ -179,7 +219,7 @@ func (oc *OneCloudNotifier) Notify(ctx *alerting.EvalContext, _ jsonutils.JSONOb
}
msg := notify.SNotifyMessage{
- Uid: oc.Setting.UserIds,
+ Uid: uids,
ContactType: notify.TNotifyChannel(oc.Setting.Channel),
Topic: config.Title,
Priority: notify.TNotifyPriority(config.Priority),
@@ -192,12 +232,36 @@ func (oc *OneCloudNotifier) Notify(ctx *alerting.EvalContext, _ jsonutils.JSONOb
return sendImp.send()
}
+func GetUserLangIdsMap(ids []string) (map[string][]string, error) {
+ session := auth.GetAdminSession(context.Background(), "", "")
+ langIdsMap := make(map[string][]string)
+ params := jsonutils.NewDict()
+ params.Set("filter", jsonutils.NewString(fmt.Sprintf("id.in(%s)", strings.Join(ids, ","))))
+ params.Set("details", jsonutils.JSONFalse)
+ params.Set("scope", jsonutils.NewString("system"))
+ params.Set("system", jsonutils.JSONTrue)
+ ret, err := modules.UsersV3.List(session, params)
+ if err != nil {
+ return nil, err
+ }
+ for i := range ret.Data {
+ id, _ := ret.Data[i].GetString("id")
+ langStr, _ := ret.Data[i].GetString("lang")
+ if _, ok := langIdsMap[langStr]; ok {
+ langIdsMap[langStr] = append(langIdsMap[langStr], id)
+ continue
+ }
+ langIdsMap[langStr] = []string{id}
+ }
+ return langIdsMap, nil
+}
+
var (
companyInfo models.SCompanyInfo
)
-func (oc *OneCloudNotifier) filterMatchTagsForConfig(config *monitor.NotificationTemplateConfig) {
- sCompanyInfo, err := models.GetCompanyInfo(oc.Ctx)
+func (oc *OneCloudNotifier) filterMatchTagsForConfig(config *monitor.NotificationTemplateConfig, ctx context.Context) {
+ sCompanyInfo, err := models.GetCompanyInfo(ctx)
if err != nil {
log.Errorf("GetCompanyInfo error:%#v", err)
return
diff --git a/pkg/monitor/models/alertrecord.go b/pkg/monitor/models/alertrecord.go
index c84a3d63da..8401235802 100644
--- a/pkg/monitor/models/alertrecord.go
+++ b/pkg/monitor/models/alertrecord.go
@@ -9,7 +9,6 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/timeutils"
- "yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis/monitor"
@@ -108,45 +107,6 @@ func (manager *SAlertRecordManager) ListItemFilter(
return q, nil
}
-func (man *SAlertRecordManager) CustomizeFilterList(
- ctx context.Context, q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential, query jsonutils.JSONObject) (
- *db.CustomizeListFilters, error) {
- filters := db.NewCustomizeListFilters()
- input := new(monitor.AlertRecordListInput)
- if err := query.Unmarshal(input); err != nil {
- return nil, err
- }
- wrapF := func(f func(obj *SAlertRecord) (bool, error)) func(object jsonutils.JSONObject) (bool, error) {
- return func(data jsonutils.JSONObject) (bool, error) {
- id, err := data.GetString("id")
- if err != nil {
- return false, err
- }
- obj, err := man.GetAlertRecord(id)
- if err != nil {
- return false, err
- }
- return f(obj)
- }
- }
-
- if len(input.ResType) != 0 {
- mF := func(obj *SAlertRecord) (bool, error) {
- rule := new(monitor.AlertRecordRule)
- if err := obj.AlertRule.Unmarshal(rule); err != nil {
- return false, errors.Wrapf(err, "alert %s unmarshal", obj.GetId())
- }
- if ok, _ := utils.InStringArray(rule.ResType, input.ResType); ok {
- return true, nil
- }
- return false, nil
- }
- filters.Append(wrapF(mF))
- }
- return filters, nil
-}
-
func (man *SAlertRecordManager) GetAlertRecord(id string) (*SAlertRecord, error) {
obj, err := man.FetchById(id)
if err != nil {
@@ -251,6 +211,10 @@ func (record *SAlertRecord) CustomizeCreate(
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) error {
+ err := record.SMonitorScopedResource.CustomizeCreate(ctx, userCred, ownerId, query, data)
+ if err != nil {
+ return err
+ }
obj, err := db.NewModelObject(AlertRecordManager)
if err != nil {
return errors.Wrapf(err, "NewModelObject %s", AlertRecordManager.Keyword())
diff --git a/pkg/monitor/models/commonalert.go b/pkg/monitor/models/commonalert.go
index d0a562aa3c..cad792c1a3 100644
--- a/pkg/monitor/models/commonalert.go
+++ b/pkg/monitor/models/commonalert.go
@@ -7,6 +7,8 @@ import (
"strings"
"time"
+ "golang.org/x/text/language"
+
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
@@ -20,6 +22,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/hostman/hostinfo/hostconsts"
"yunion.io/x/onecloud/pkg/httperrors"
+ "yunion.io/x/onecloud/pkg/i18n"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
@@ -36,7 +39,7 @@ const (
CommonAlertMetadataPointStr = "point_str"
CommonAlertMetadataName = "meta_name"
- COMPANY_COPYRIGHT_ONECLOUD = "北京云联万维技术有限公司"
+ COMPANY_COPYRIGHT_ONECLOUD = "云联"
BRAND_ONECLOUD_NAME_CN = "云联壹云"
BRAND_ONECLOUD_NAME_EN = "YunionCloud"
)
@@ -1101,13 +1104,13 @@ func GetCompanyInfo(ctx context.Context) (SCompanyInfo, error) {
return SCompanyInfo{}, err
}
if strings.Contains(info.Copyright, COMPANY_COPYRIGHT_ONECLOUD) {
- //lang := i18n.Lang(ctx)
- //switch lang {
- //case language.English:
- // info.Name = BRAND_ONECLOUD_NAME_EN
- //default:
- //}
- info.Name = BRAND_ONECLOUD_NAME_CN
+ lang := i18n.Lang(ctx)
+ switch lang {
+ case language.English:
+ info.Name = BRAND_ONECLOUD_NAME_EN
+ default:
+ info.Name = BRAND_ONECLOUD_NAME_CN
+ }
}
return info, nil
}
diff --git a/pkg/monitor/models/query_signature.go b/pkg/monitor/models/query_signature.go
index de4326db7b..d0de13a495 100644
--- a/pkg/monitor/models/query_signature.go
+++ b/pkg/monitor/models/query_signature.go
@@ -32,6 +32,7 @@ func ValidateQuerySignature(input jsonutils.JSONObject) error {
return errors.Wrap(err, "get signature")
}
if signature != digestQuerySignature(data) {
+
return httperrors.NewBadRequestError("signature error")
}
return nil
diff --git a/pkg/monitor/models/unifiedmonitor.go b/pkg/monitor/models/unifiedmonitor.go
index a78d31167f..431513ac22 100644
--- a/pkg/monitor/models/unifiedmonitor.go
+++ b/pkg/monitor/models/unifiedmonitor.go
@@ -190,7 +190,9 @@ func (self *SUnifiedMonitorManager) AllowPerformQuery(ctx context.Context, userC
}
func (self *SUnifiedMonitorManager) PerformQuery(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- if err := ValidateQuerySignature(data); err != nil {
+ tmp := jsonutils.DeepCopy(data)
+ self.handleDataPreSignature(tmp)
+ if err := ValidateQuerySignature(tmp); err != nil {
return nil, errors.Wrap(err, "ValidateQuerySignature")
}
inputQuery := new(monitor.MetricInputQuery)
@@ -233,6 +235,25 @@ func (self *SUnifiedMonitorManager) PerformQuery(ctx context.Context, userCred m
return jsonutils.Marshal(rtn), nil
}
+func (self *SUnifiedMonitorManager) handleDataPreSignature(data jsonutils.JSONObject) {
+ scope, _ := data.GetString("scope")
+ switch scope {
+ case "system":
+ case "domain":
+ domain, err := data.GetString("project_domain")
+ if err == nil {
+ data.(*jsonutils.JSONDict).Remove("project_domain")
+ data.(*jsonutils.JSONDict).Set("domain_id", jsonutils.NewString(domain))
+ }
+ default:
+ project, err := data.GetString("project")
+ if err == nil {
+ data.(*jsonutils.JSONDict).Remove("project")
+ data.(*jsonutils.JSONDict).Set("project_id", jsonutils.NewString(project))
+ }
+ }
+}
+
func doQuery(query monitor.MetricInputQuery) (*mq.Metrics, error) {
conditions := make([]*monitor.AlertCondition, 0)
for _, q := range query.MetricQuery {