Commit de712f7c authored by 黄智's avatar 黄智

Merge remote-tracking branch 'origin/dev' into dev

parents 847da67f b4a16368
......@@ -26,11 +26,13 @@ require (
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.66.0
github.com/prometheus/alertmanager v0.25.0
github.com/robfig/cron v1.2.0
github.com/robfig/cron/v3 v3.0.1
github.com/satori/go.uuid v1.2.0
github.com/spf13/cast v1.5.0
github.com/spf13/pflag v1.0.5
github.com/tealeg/xlsx v1.0.5
github.com/thoas/go-funk v0.9.3
github.com/tidwall/gjson v1.16.0
github.com/valyala/fasthttp v1.47.0
github.com/wanghuiyt/ding v0.0.2
go.uber.org/zap v1.24.0
......@@ -107,6 +109,8 @@ require (
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect
github.com/sirupsen/logrus v1.9.2 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
......
......@@ -579,6 +579,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
......@@ -645,6 +647,12 @@ github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=
github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
......
......@@ -7,7 +7,7 @@ type AlertClass struct {
ClassName string `json:"class_name" xorm:"'class_name'"` // 分类名称
ParentId int `json:"parent_id" xorm:"'parent_id'"` // 父级id
SortOrder int `json:"sort_order" xorm:"'sort_order'"` // 排序
SourceFrom int `json:"source_from" xorm:"source_from"` // 数据来源 1:默认 2:自定义
Source int `json:"source" xorm:"source"` // 数据来源 1:默认 2:自定义
CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人
CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间
UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人
......
......@@ -21,24 +21,8 @@ type AlertArray struct {
TotalCount int `json:"total_count"` // 总预警数
}
type RiskLevelDistribution struct {
type AlertDistribution struct {
Name string `json:"name"` // 名称
//RiskLevel int `json:"risk_level"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
//Percentage string `json:"percentage"` // 百分比
Value int `json:"value"`
}
type AlertStatusDistribution struct {
Name string `json:"name"` // 名称
//Status int `json:"status"` // 状态,1:已恢复 2:未恢复 3:已关闭
//Percentage string `json:"percentage"` // 百分比
Value int `json:"value"`
}
type AlertClassDistribution struct {
Name string `json:"name"` // 名称
//ClassId int `json:"class_id"` // 预警分类id
//Percentage string `json:"percentage"` // 百分比
Value int `json:"value"`
}
......
package entity
import (
"github.com/prometheus/alertmanager/notify/webhook"
)
type Message webhook.Message
......@@ -13,7 +13,7 @@ type MetricConfig struct {
CheckPeriod int `json:"check_period" xorm:"'check_period'"` // 检查周期 单位:分钟
IsEnabled int `json:"is_enabled" xorm:"'is_enabled'"` // 是否开启 1:是 2:否
AlertRuleType string `json:"alert_rule_type" xorm:"'alert_rule_type'"` // 预警规则类型 关联字典表
SourceFrom int `json:"source_from" xorm:"source_from"` // 数据来源 1:默认 2:自定义
Source int `json:"source" xorm:"source"` // 数据来源 1:默认 2:自定义
CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人
CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间
UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人
......
......@@ -25,9 +25,9 @@ type SystemUser struct {
}
type SystemUserInfo struct {
Id int `json:"id" xorm:"pk autoincr" ` // id
Id int `json:"id" xorm:"pk autoincr"` // id
Name string `json:"name" ` // 名称
SystemAccount string `json:"system_account" ` // 账号
SystemAccount string `json:"system_account"` // 账号
OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织
Password string `json:"password,omitempty"` // 密码
State int `json:"state" xorm:"state"` // 状态0禁用1启用
......
package entity
import "time"
import (
"time"
)
type WorkOrder struct {
Id int `json:"id" xorm:"pk autoincr" ` // id
OrderName string `json:"order_name" xorm:"order_name"` // 工单名称
OrderLevel int `json:"order_level" xorm:"order_level"` // 工单等级(1紧急任务 2重要任务 3一般任务)
OrderDesc string `json:"order_desc" xorm:"order_desc"` // 工单描述
OrderCnt int `json:"order_cnt" xorm:"order_cnt"` // 实例工单数
//OrderCnt int `json:"order_cnt" xorm:"order_cnt"` // 实例工单数
PushObj string `json:"push_obj" xorm:"push_obj"` // 推送对象
TimingType int `json:"timing_type" xorm:"timing_type"` // 定时类型(1手动下发 2按周 3自定义时间)
TimingRule string `json:"timing_rule" xorm:"timing_rule"` // 定时规则
......
......@@ -15,6 +15,7 @@ type ListAlert struct {
RiskLevel int `json:"risk_level" form:"risk_level" binding:"omitempty,oneof=1 2 3 4"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
Status int `json:"status" form:"status" binding:"omitempty,oneof=1 2 3"` // 状态,1:已恢复 2:未恢复 3:已关闭
Keyword string `json:"keyword" form:"keyword"` // 预警点/分类/指标
SystemAccount string `json:"system_account" form:"system_account"` // 预警推送用户
StartTime string `json:"start_time" form:"start_time" binding:"omitempty,datetime=2006-01-02 15:04:05"`
EndTime string `json:"end_time" form:"end_time" binding:"omitempty,datetime=2006-01-02 15:04:05"`
Pagination
......
......@@ -2,13 +2,14 @@ package request
type AddAlertClass struct {
ClassName string `json:"class_name" form:"class_name" binding:"required"`
ParentId int `json:"parent_id" form:"parent_id" binding:"omitempty,oneof=0 1"`
ParentId int `json:"parent_id" form:"parent_id"`
SortOrder int `json:"sort_order" form:"sort_order"`
SourceFrom int `json:"source_from" form:"source_from" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义
Source int `json:"source" form:"source" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义
}
type UpdateAlertClass struct {
ClassId int `json:"class_id" form:"class_id" binding:"required"`
ParentId int `json:"parent_id" form:"parent_id"`
ClassName string `json:"class_name" form:"class_name" binding:"required"`
}
......
......@@ -33,7 +33,7 @@ type UpdateAlertRules struct {
ClassId int `json:"class_id" form:"class_id" binding:"required_if=DetectionType 1"` // 预警对象id(级联:预警分类/预警对象)
ClassParentName string `json:"class_parent_name" form:"class_parent_name" binding:"required_if=DetectionType 2"` // 预警分类名称
ClassName string `json:"class_name" form:"class_name" binding:"required_if=DetectionType 2"` // 预警对象名称
MetricConfigId string `json:"metric_config_id" form:"'metric_config_id'" binding:"required_if=DetectionType 1"` // 预警指标id
MetricConfigId string `json:"metric_config_id" form:"metric_config_id" binding:"required_if=DetectionType 1"` // 预警指标id
MetricConfigName string `json:"metric_config_name" form:"metric_config_name" binding:"required_if=DetectionType 2"` // 预警指标名称(映射entity.MetricConfig.MetricName)
Expr string `json:"expr" form:"expr" binding:"required_if=DetectionType 2"` // 指标表达式(PromQL语句)
AlertCondition []entity.AlertCondition `json:"alert_condition" form:"alert_condition" binding:"required"` // 预警规则 字典值
......
......@@ -10,7 +10,7 @@ type AddAlertWebhook struct {
ClassId int `json:"class_id" form:"class_id" binding:"required_if=DetectionType 1"` // 预警对象id(级联:预警分类/预警对象)
ClassParentName string `json:"class_parent_name" form:"class_parent_name" binding:"required_if=DetectionType 2"` // 预警分类名称
ClassName string `json:"class_name" form:"class_name" binding:"required_if=DetectionType 2"` // 预警对象名称
MetricConfigId string `json:"metric_config_id" form:"'metric_config_id'" binding:"required_if=DetectionType 1"` // 预警指标id
MetricConfigId string `json:"metric_config_id" form:"metric_config_id" binding:"required_if=DetectionType 1"` // 预警指标id
MetricConfigName string `json:"metric_config_name" form:"metric_config_name" binding:"required_if=DetectionType 2"` // 预警指标名称(映射entity.MetricConfig.MetricName)
Expr string `json:"expr" form:"expr" binding:"required_if=DetectionType 2"` // 指标表达式(PromQL语句)
AlertCondition []entity.AlertCondition `json:"alert_condition" form:"alert_condition" binding:"required,dive"` // 预警规则 字典值
......
......@@ -12,7 +12,7 @@ type AddMetricConfig struct {
CheckPeriod int `json:"check_period" form:"check_period" binding:"oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟
IsEnabled int `json:"is_enabled" form:"is_enabled" binding:"omitempty,oneof=1 2"` // 是否开启 1:是 2:否
AlertRuleType string `json:"alert_rule_type" form:"alert_rule_type" binding:"required"` // 预警规则类型 关联字典表
SourceFrom int `json:"source_from" form:"source_from" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义
Source int `json:"source" form:"source" binding:"omitempty,oneof=1 2"` // 数据来源(自定义为非正常数据) 1:默认 2:自定义
}
type UpdateMetricConfig struct {
......@@ -26,7 +26,7 @@ type UpdateMetricConfig struct {
CheckPeriod int `json:"check_period" form:"check_period" binding:"omitempty,oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟
IsEnabled int `json:"is_enabled" form:"is_enabled" binding:"omitempty,oneof=1 2"` // 是否开启 1:是 2:否
AlertRuleType string `json:"alert_rule_type" form:"alert_rule_type"` // 预警规则类型 关联字典表
SourceFrom int `json:"source_from" form:"source_from" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义
Source int `json:"source" form:"source" binding:"omitempty,oneof=1 2"` // 数据来源 1:默认 2:自定义
}
type DeleteMetricConfig struct {
......
package request
type AddWorkOrderReq struct {
IsPush int `json:"is_push"` // 是否立刻下发(0否 1是)
IsPush int `json:"is_push" binding:"oneof=0 1"` // 是否立刻下发(0否 1是)
OrderName string `json:"order_name" binding:"required"` // 工单名称
OrderLevel int `json:"order_level" binding:"oneof=1 2 3"` // 工单等级(1紧急任务 2重要任务 3一般任务)
OrderDesc string `json:"order_desc" binding:"required"` // 工单描述
......@@ -36,7 +36,7 @@ type TimingCustom struct {
}
type EditWorkOrderReq struct {
IsPush int `json:"is_push" binding:"required"` // 是否立刻下发(0否 1是)
IsPush int `json:"is_push" binding:"oneof=0 1"` // 是否立刻下发(0否 1是)
Id int `json:"id" binding:"required"` // 主键id
OrderLevel int `json:"order_level" binding:"oneof=1 2 3"` // 工单等级(1紧急任务 2重要任务 3一般任务)
OrderDesc string `json:"order_desc" binding:"required"` // 工单描述
......
......@@ -62,3 +62,46 @@ type Hits struct {
MaxScore float64 `json:"max_score"`
Hits []SubHits `json:"hits"`
}
type AggAlertOverview struct {
Group struct {
DocCountErrorUpperBound int `json:"doc_count_error_upper_bound"`
SumOtherDocCount int `json:"sum_other_doc_count"`
Buckets []struct {
Key int `json:"key"`
DocCount int `json:"doc_count"`
Group struct {
DocCountErrorUpperBound int `json:"doc_count_error_upper_bound"`
SumOtherDocCount int `json:"sum_other_doc_count"`
Buckets []struct {
Key string `json:"key"`
DocCount int `json:"doc_count"`
UnresolvedCount struct {
DocCount int `json:"doc_count"`
} `json:"unresolved_count"`
} `json:"buckets"`
} `json:"group"`
} `json:"buckets"`
} `json:"group"`
}
type AlertDistributionGroup struct {
Group struct {
DocCountErrorUpperBound int `json:"doc_count_error_upper_bound"`
SumOtherDocCount int `json:"sum_other_doc_count"`
Buckets []struct {
Key int `json:"key"`
DocCount int `json:"doc_count"`
} `json:"buckets"`
} `json:"group"`
}
type DateHistogramGroup struct {
Group struct {
Buckets []struct {
KeyAsString string `json:"key_as_string"`
Key int64 `json:"key"`
DocCount int `json:"doc_count"`
} `json:"buckets"`
} `json:"group"`
}
......@@ -6,9 +6,9 @@ import (
type AlertOverviewItem struct {
AlertOverview []entity.AlertOverview `json:"alert_overview"`
RiskLevelDistribution []entity.RiskLevelDistribution `json:"risk_level_distribution"`
AlertStatusDistribution []entity.AlertStatusDistribution `json:"alert_status_distribution"`
AlertClassDistribution []entity.AlertClassDistribution `json:"alert_class_distribution"`
RiskLevelDistribution []entity.AlertDistribution `json:"risk_level_distribution"`
AlertStatusDistribution []entity.AlertDistribution `json:"alert_status_distribution"`
AlertClassDistribution []entity.AlertDistribution `json:"alert_class_distribution"`
AlertFrequencyDistribution entity.AlertFrequencyDistribution `json:"alert_frequency_distribution"`
}
......
......@@ -31,7 +31,7 @@ type Config struct {
MinioSecretKey string
MinioBucket string
//TempDirPrefix string
PrometheusHost string
AccessRuleModeKey string
LocationUrl string
LocationKey string
......@@ -49,9 +49,20 @@ type Config struct {
AweRestURL string
KubernetesToken string
OpenSearchIndex string
OpenSearchAddresses string
OpenSearchUserName string
OpenSearchPassword string
MonitorApiVersion string
MonitorMatchNs string
MonitorMatchLabelsStr string
MonitorMatchLabels map[string]interface{}
Namespace string
PrometheusHost string
PrometheusRuleLabel string
PrometheusRuleNamePrefix string
}
const (
......
......@@ -31,6 +31,7 @@ func ListAlert(c *gin.Context) {
return
}
svc := service.AlertSvc{User: header.GetUser(c)}
// TODO 我的预警工单
data, err := svc.List(req)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
......
......@@ -3,10 +3,10 @@ package controller
import (
"github.com/gin-gonic/gin"
"github.com/prometheus/alertmanager/notify/webhook"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/service"
"go.uber.org/zap"
)
......@@ -14,12 +14,18 @@ import (
// AlertWebhook 回调
func AlertWebhook(c *gin.Context) {
var req webhook.Message
conf.Logger.Info("------>webhook.start------>")
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
conf.Logger.Info("------>webhook.Message------>", zap.Any("message", req))
svc := service.AlertWebhookSvc{User: header.GetUser(c)}
svc := service.AlertWebhookSvc{User: entity.SystemUserInfo{
Name: "prometheus",
SystemAccount: "prometheus",
OrganizationId: "",
State: 1,
}}
db, err := client.GetDbClient()
if err != nil {
SendJsonResponse(c, resp.DbConnectError.WithError(err), nil)
......
......@@ -5,6 +5,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/service"
......@@ -243,3 +244,36 @@ func ListWorkOrderMe(c *gin.Context) {
}
SendJsonPageResponse(c, resp.OK, list, total)
}
// WorkOrderListAlert 我的预警工单
func WorkOrderListAlert(c *gin.Context) {
var req request.ListAlert
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
user := header.GetUser(c)
req.SystemAccount = user.SystemAccount
if user.SystemAccount == "" {
SendJsonResponse(c, resp.FAIL.WithError(errors.New("system_account cannot be empty")), nil)
return
}
svc := service.AlertSvc{User: user}
data, err := svc.List(req)
// 回显使用:内部字段对外覆盖处理
// disposed_list[].is_disposed --映射--> is_disposed
for i := 0; i < len(data.List); i++ {
for j := 0; j < len(data.List[i].DisposedList); j++ {
if data.List[i].IsDisposed != constant.IsDisposedYes {
if data.List[i].DisposedList[j].DisposalUser == user.SystemAccount {
data.List[i].IsDisposed = constant.IsDisposedYes
}
}
}
}
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, data)
}
......@@ -45,9 +45,15 @@ func main() {
// redis client
go client.GetRedisClient()
// 初始化OpenSearch的索引
err := service.CheckAndCreateIndex()
if err != nil {
conf.Logger.Error("failed to init OpenSearch index", zap.Error(err))
}
//启动定时任务
cron.StartCron()
service.PushWorkOrderMessage()
service.CronPushWorkOrder()
// server start...
conf.Logger.Info("config info", zap.Any("options", conf.Options))
conf.Logger.Error("server start err", zap.Error(newServer().ListenAndServe()))
......@@ -74,7 +80,6 @@ func initConfig() {
MinioAccessKey: util.SetEnvStr("MINIO_ACCESS_KEY", "beagleadmin"), // Minio Access Key
MinioSecretKey: util.SetEnvStr("MINIO_SECRET_KEY", "H76cPmwvH7vJ"), // Minio Secret
MinioBucket: util.SetEnvStr("MINIO_BUCKET", "so-operation"), // Minio Bucket
PrometheusHost: util.SetEnvStr("PROMETHEUS_HOST", "https://prometheus.wodcloud.com"), // Prometheus Host
AccessRuleModeKey: "accessRuleMode",
LocationUrl: util.SetEnvStr("LOCATION_URL", "https://apis.map.qq.com/ws/location/v1/ip"),
LocationKey: util.SetEnvStr("LOCATION_KEY", "QKFBZ-PGGWJ-VZQFF-FHPA7-QWT5H-YHF4T"),
......@@ -85,14 +90,26 @@ func initConfig() {
SmsAccessKeyId: util.SetEnvStr("SMS_ACCESS_KEY", "LTAI4GBcVubRjzX7ABPcHnhB"), // 短信key
SmsAccessSecret: util.SetEnvStr("SMS_ACCESS_SECRET", "dYE2dtABFOqYtK1ijcrits0yedHkw7"), // 短信secret
SmsTemplateLogin: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_212925130"), // 短信验证码模板
SmsTemplateAlert: util.SetEnvStr("Sms_Template_Alert", "SMS_461975765"), // 预警短信模板 // 短信工单下发模板
SmsTemplateAlert: util.SetEnvStr("SMS_TEMPLATE_ALERT", "SMS_461975765"), // 预警短信模板 // 短信工单下发模板
SmsWorkOrderTemplate: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_462020767"), // 短信工单下发模板
SmsSignName: util.SetEnvStr("SMS_SIGN_NAME", "比格数据"), // 签名
AweRestURL: util.SetEnvStr("AWE_REST_URL", "http://awecloud-rest.beagle-system/awecloud/rest"), // awecloud-rest
KubernetesToken: util.SetEnvStr("AWE_REST_K8S_TOKEN", "eyJhbGciOiJSUzI1NiIsImtpZCI6InJ1alJzNEVGamN5UC0wRU1rS1BKQ0JZVUtNNWpzR0t2bmlrSlJhY2Q3R00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJiZWFnbGUtc3lzdGVtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InJvb3QiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicm9vdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRlMDM0OTI3LTc0ZTMtNDQ5Yy1hN2RlLWExMGE3MjU1NGYyMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpiZWFnbGUtc3lzdGVtOnJvb3QifQ.YPLE_E2kIeo-YFQtKScBt5p4KhnniJF9n3iWN2i9UMYS06lIsq2-2wBrgON-YsJihWJupYyDQRiZ9h8bUWTrQzhnpsnuJ_aUclKyAw3QOT9rjvZhJp7qP--27dmdspSHncKtvIiprWE7UTUKzvF33WsMB0fSYFqYXOggNFMoT-fXmWwUXjgar3op0iOl3c3deJ_GeBzFyLSHEuGM7OVdjU8032aUmTen0Kji_P1yB4-O3Iqd0OdVs33BQy_tycjbxhQ8TDEpqrqhLnXjAwJCprLDEpFMx7ODZbjB9Wmuns8yJhaRDxTO47rTME7ZIAxjZ-zLR_QybtW97rlwnUTaNw"),
OpenSearchAddresses: util.SetEnvStr("Open_Search_Addresses", "https://so-opensearch.wodcloud.com"), // 短信验证码模板
OpenSearchUserName: util.SetEnvStr("Open_Search_User_Name", ""), // 短信验证码模板
OpenSearchPassword: util.SetEnvStr("Open_Search_Password", ""), // 短信验证码模板
OpenSearchIndex: util.SetEnvStr("OPEN_SEARCH_INDEX", "so_alert"),
OpenSearchAddresses: util.SetEnvStr("OPEN_SEARCH_ADDRESSES", "https://so-opensearch.wodcloud.com"), // OpenSearch连接地址
OpenSearchUserName: util.SetEnvStr("OPEN_SEARCH_USER_NAME", ""), // OpenSearch用户名
OpenSearchPassword: util.SetEnvStr("OPEN_SEARCH_PASSWORD", ""), // OpenSearch密码
Namespace: util.SetEnvStr("NAMESPACE", "smart-manage"), //采集器部署命名空间
PrometheusHost: util.SetEnvStr("PROMETHEUS_HOST", "https://prometheus.wodcloud.com"), // Prometheus Host
PrometheusRuleNamePrefix: util.SetEnvStr("PROMETHEUS_RULE_NAME_PREFIX", "beagle-prometheus-so-operation-api-rules"), // prometheusrules资源名前缀
PrometheusRuleLabel: util.SetEnvStr("PROMETHEUS_RULE_LABEL", `{"source":"so-operation-api","severity":"warning"}`), // prometheusrules标签,用于区分项目来源
MonitorApiVersion: util.SetEnvStr("MONITOR_API_VERSION", "monitoring.beagle.io/v1"), //Prometheus Operator 资源版本
MonitorMatchNs: util.SetEnvStr("MONITOR_MATCH_NS", "beagle-monitoring"), //Monitor匹配 命名空间
MonitorMatchLabelsStr: util.SetEnvStr("MONITOR_MATCH_LABELS", `{"prometheus-operator":"monitoring"}`), //Monitor匹配 标签JSON
}
}
......@@ -145,12 +162,6 @@ func initAnsibleHosts() {
if err != nil {
fmt.Println(err.Error())
}
//else {
// _, err := f.Write([]byte("[web]\n"))
// if err != nil {
// fmt.Println(err.Error())
// }
//}
}
func initTempDirPrefix() {
......@@ -175,14 +186,4 @@ func initAnsibleSSH() {
fmt.Println(err.Error())
}
}
//f2, err := os.CreateIndex("/root/.ssh/id_rsa.pub")
//defer f2.Close()
//if err != nil {
// fmt.Println(err.Error())
//} else {
// _, err := f.Write([]byte(conf.Options.PublicKeySSH))
// if err != nil {
// fmt.Println(err.Error())
// }
//}
}
......@@ -123,6 +123,12 @@ var OpTypeIntMap = map[OpType]int{
Export: 14,
}
// 数据来源(自定义为非正常数据) 1:默认 2:自定义
const (
SourceDefault = 1
SourceCustom = 2
)
// RiskLevel 风险等级
const (
RiskLevelLow = iota + 1 // 1:低风险
......@@ -142,7 +148,7 @@ func RiskLeveText(code int) string {
case RiskLevelCritical:
return "重大风险"
default:
return ""
return "未知"
}
}
......@@ -152,3 +158,40 @@ const (
AlertNotRecovered
AlertClosed
)
func AlertStatusText(code int) string {
switch code {
case AlertRecovered:
return "已恢复"
case AlertNotRecovered:
return "未恢复"
case AlertClosed:
return "已关闭"
default:
return "未知"
}
}
// 是否处置(工单管理),1:已处置,2:未处置
const (
IsDisposedYes = 1
IsDisposedNo = 2
)
func DisposedStatusText(code int) string {
switch code {
case IsDisposedYes:
return "已处置"
case IsDisposedNo:
return "未处置"
default:
return "未知"
}
}
// 工单定时类型
const (
TimingClick = 1 //手动下发
TimingWeekly = 2 //按周
TimingCustom = 3 //自定义时间
)
......@@ -5,11 +5,12 @@ import (
"github.com/gin-gonic/gin"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/controller"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header"
)
// InitAlertListRouter 初始化预警列表配置路由
func InitAlertListRouter(e *gin.Engine) {
group := e.Group(fmt.Sprintf("%s/alert", conf.Options.Prefix))
group := e.Group(fmt.Sprintf("%s/alert", conf.Options.Prefix), header.SetContext)
{
group.GET("", controller.DetailAlert)
group.GET("list", controller.ListAlert)
......
......@@ -5,11 +5,12 @@ import (
"github.com/gin-gonic/gin"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/controller"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header"
)
// InitAlertRulesRouter 初始化预警规则配置路由
func InitAlertRulesRouter(e *gin.Engine) {
group := e.Group(fmt.Sprintf("%s/alert_rules", conf.Options.Prefix))
group := e.Group(fmt.Sprintf("%s/alert_rules", conf.Options.Prefix), header.SetContext)
{
group.POST("", controller.AddAlertRules)
group.PUT("", controller.UpdateAlertRules)
......
......@@ -5,11 +5,12 @@ import (
"github.com/gin-gonic/gin"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/controller"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/router/middleware/header"
)
// InitMetricConfigRouter 初始化指标配置路由
func InitMetricConfigRouter(e *gin.Engine) {
mcGroup := e.Group(fmt.Sprintf("%s/metric_config", conf.Options.Prefix))
mcGroup := e.Group(fmt.Sprintf("%s/metric_config", conf.Options.Prefix), header.SetContext)
{
mcGroup.POST("", controller.AddMetricConfig)
mcGroup.PUT("", controller.UpdateMetricConfig)
......@@ -18,7 +19,7 @@ func InitMetricConfigRouter(e *gin.Engine) {
mcGroup.GET("list", controller.ListMetricConfig)
}
acGroup := e.Group(fmt.Sprintf("%s/alert_class", conf.Options.Prefix))
acGroup := e.Group(fmt.Sprintf("%s/alert_class", conf.Options.Prefix), header.SetContext)
{
acGroup.POST("", controller.AddAlertClass)
acGroup.PUT("move/:direction", controller.MoveAlertClass)
......
......@@ -10,12 +10,12 @@ import (
// InitWorkOrderRouter 初始化工单路由
func InitWorkOrderRouter(e *gin.Engine) {
so := e.Group(fmt.Sprintf("%s/work_order", conf.Options.Prefix))
so := e.Group(fmt.Sprintf("%s/work_order", conf.Options.Prefix), header.SetContext)
//预警工单管理
alert := so.Group("/alert")
{
alert.GET("", controller.DetailAlert) // 详情
alert.GET("/list", controller.ListAlert) // 列表
alert.GET("/list", controller.WorkOrderListAlert) // 列表
alert.PUT("/dispose", controller.DisposeAlert) // 处置反馈
}
......@@ -46,5 +46,4 @@ func InitWorkOrderRouter(e *gin.Engine) {
me.PUT("/feedback", controller.FeedbackWorkOrderMe) // 处置反馈
me.GET("/list", controller.ListWorkOrderMe) // 我的业务工单列表
}
//so.POST("/note_sg", controller.WorkOrderPushNoteMsg)
}
This diff is collapsed.
......@@ -8,6 +8,7 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"sort"
......@@ -26,6 +27,9 @@ func (a *AlertClassSvc) Add(session *xorm.Session, req request.AddAlertClass) (c
UpdatedBy: a.User.SystemAccount,
UpdatedAt: now,
}
if req.Source != constant.SourceCustom {
req.Source = constant.SourceDefault
}
_ = copier.Copy(&data, &req)
var max int
......@@ -48,7 +52,7 @@ func (a *AlertClassSvc) Update(session *xorm.Session, req request.UpdateAlertCla
UpdatedAt: now,
}
_ = copier.Copy(&data, &req)
_, err := session.Cols("class_name", "updated_by", "updated_at").ID(data.ClassId).Update(&data)
_, err := session.Cols("parent_id", "class_name", "updated_by", "updated_at").ID(data.ClassId).Update(&data)
if err != nil {
return err
}
......@@ -66,7 +70,7 @@ func (a *AlertClassSvc) Move(req request.MoveAlertClass) (err error) {
_ = copier.Copy(&data, &req)
var list []entity.AlertClass
_, err = db.NewSession().Where("class_id = ?", req.ClassId).Get(&data)
err = db.NewSession().Where("parent_id = ?", data.ParentId).Where("source_from = 1").OrderBy("sort_order asc").Find(&list)
err = db.NewSession().Where("parent_id = ?", data.ParentId).Where("source = 1").OrderBy("sort_order asc").Find(&list)
var previousIndex int
var nextIndex int
for i := 0; i < len(list); i++ {
......@@ -139,18 +143,33 @@ func (a *AlertClassSvc) List(req request.ListAlertClass) (resp response.AlertCla
}
session := db.NewSession()
defer session.Close()
session.Where("source_from = 1")
session.Where("source = 1")
if req.ClassId != 0 {
session.Where("class_id = ?", req.ClassId)
}
if req.ClassName != "" {
session.Where("class_name LIKE ?", "%"+req.ClassName+"%")
}
if req.Page == -1 {
req.PageSize = 100000
}
resp.TotalCount, err = session.Limit(req.GetPageSize(), (req.GetPage()-1)*req.GetPageSize()).
OrderBy("sort_order").FindAndCount(&resp.List)
return
}
func (a *AlertClassSvc) AlertObjectList() (resp response.AlertClassList, err error) {
db, err := client.GetDbClient()
if err != nil {
return
}
session := db.NewSession()
defer session.Close()
session.Where("parent_id <> 0")
resp.TotalCount, err = session.OrderBy("sort_order").FindAndCount(&resp.List)
return
}
func (a *AlertClassSvc) Tree(req request.ListAlertClass) (resp []*response.AlertClassNode, err error) {
db, err := client.GetDbClient()
if err != nil {
......@@ -159,7 +178,7 @@ func (a *AlertClassSvc) Tree(req request.ListAlertClass) (resp []*response.Alert
session := db.NewSession()
defer session.Close()
var list []entity.AlertClass
session.Where("source_from = 1")
session.Where("source = 1")
_, err = session.OrderBy("sort_order").FindAndCount(&list)
// TODO 对req进行过滤
resp, err = AlertClassTree(list)
......@@ -211,15 +230,68 @@ func (a *AlertClassSvc) SortOrderMax(parentId int) (max int, err error) {
}
_, err = db.NewSession().Table(new(entity.AlertClass)).
Select("max(sort_order)").
Where("parent_id = ?", parentId).Where("source_from = 1").Get(&max)
Where("parent_id = ?", parentId).Where("source = 1").Get(&max)
return
}
func (a *AlertClassSvc) Delete(ids []int) (err error) {
db, err := client.GetDbClient()
if err != nil {
return
return err
}
_, err = db.NewSession().In("class_id", ids).Delete(&entity.AlertClass{})
return
var classes []entity.AlertClass
err = db.In("class_id", ids).Find(&classes)
// 检查是否所有指定的 ids 都存在于数据库中
if len(ids) > len(classes) {
return errors.New("部分数据不存在")
}
var notExist []int
idSet := make(map[int]bool)
for _, v := range classes {
idSet[v.ClassId] = true
}
for _, id := range ids {
if !idSet[id] {
notExist = append(notExist, id)
}
}
if len(notExist) > 0 {
return errors.New(fmt.Sprintf("指标分类或对象id为%v的数据未查询到", notExist))
}
for _, v := range classes {
if v.ParentId == 0 {
// 如果是父级数据,判断是否存在子集
var num int
has, err := db.Table(new(entity.AlertClass)).Select("count(*)").Where("parent_id = ?", v.ClassId).Get(&num)
if err != nil {
return err
}
if has && num > 0 {
return errors.New("当前分类存在指标对象子集数据,不允许删除")
}
} else {
// 如果为子集数据,判断是否存在指标配置关联
var configCount int
has, err := db.Table(new(entity.MetricConfig)).Select("count(*)").Where("class_id = ?", v.ClassId).Get(&configCount)
if err != nil {
return err
}
if has && configCount > 0 {
return errors.New("指标对象存在指标配置关联,不允许删除")
}
}
// 删除数据
_, err = db.ID(v.ClassId).Delete(v)
if err != nil {
return err
}
}
return nil
}
This diff is collapsed.
......@@ -9,6 +9,7 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
......@@ -58,7 +59,7 @@ func (a *AlertRulesSvc) Add(req request.AddAlertRules) (err error) {
classParentId, err = alertClassSvc.Add(session, request.AddAlertClass{
ClassName: req.ClassParentName,
SortOrder: -1,
SourceFrom: 2,
Source: constant.SourceCustom,
})
if err != nil {
return nil, err
......@@ -67,18 +68,20 @@ func (a *AlertRulesSvc) Add(req request.AddAlertRules) (err error) {
ClassName: req.ClassName,
ParentId: classParentId,
SortOrder: -1,
SourceFrom: 2,
Source: constant.SourceCustom,
})
if err != nil {
return nil, err
}
data.ClassId = classId
req.ClassId = classId
// 添加指标配置
metricConfigSvc := MetricConfigSvc{User: a.User}
_ = copier.Copy(&addMetricConfig, &req)
addMetricConfig.SourceFrom = 2
addMetricConfig.Source = constant.SourceCustom
addMetricConfig.MetricName = req.MetricConfigName
addMetricConfig.ClassId = classId
metricConfigId, err = metricConfigSvc.Add(session, addMetricConfig)
if err != nil {
return nil, err
......@@ -87,14 +90,22 @@ func (a *AlertRulesSvc) Add(req request.AddAlertRules) (err error) {
// 添加预警规则配置
_, err = session.Insert(&data)
if err != nil {
return nil, err
}
return nil, err
})
err = a.CreatePrometheusRule(req.IsEnabled, data.Id, db, "")
if err != nil {
return err
}
}
err = a.CreatePrometheusRule(req.IsEnabled, data.Id, db, "")
if err != nil {
return err
}
return nil
}
......@@ -124,7 +135,11 @@ func (a *AlertRulesSvc) Update(req request.UpdateAlertRules) (err error) {
}
switch req.DetectionType {
case 1:
_, err = db.ID(data.Id).Update(&data)
_, err = db.ID(data.Id).MustCols("duration").Update(&data)
if err != nil {
return err
}
err = a.CreatePrometheusRule(req.IsEnabled, data.Id, db, "update")
if err != nil {
return err
}
......@@ -133,24 +148,37 @@ func (a *AlertRulesSvc) Update(req request.UpdateAlertRules) (err error) {
// 更新自定义分类
var (
updateMetricConfig request.UpdateMetricConfig
alertClassItem response.AlertClassItem
alertClass response.AlertClassItem
alertParentClass response.AlertClassItem
)
alertClassSvc := AlertClassSvc{User: a.User}
alertClassItem, err = alertClassSvc.GetDataById(request.DetailAlertClass{ClassId: dbAlertRules.ClassId})
alertClass, err = alertClassSvc.GetDataById(request.DetailAlertClass{ClassId: dbAlertRules.ClassId})
if err != nil {
return nil, err
}
err = alertClassSvc.Update(session, request.UpdateAlertClass{
ClassId: dbAlertRules.ClassId,
ClassName: req.ClassName,
ParentId: alertClass.ParentId,
})
if err != nil {
return nil, err
}
if alertClass.ParentId == 0 {
return nil, errors.New("预警分类为空")
}
alertParentClass, err = alertClassSvc.GetDataById(request.DetailAlertClass{ClassId: alertClass.ParentId})
if err != nil {
return nil, err
}
err = alertClassSvc.Update(session, request.UpdateAlertClass{
ClassId: alertClassItem.ParentId,
ClassId: alertClass.ParentId,
ClassName: req.ClassParentName,
ParentId: alertParentClass.ParentId,
})
if err != nil {
return nil, err
......@@ -159,17 +187,18 @@ func (a *AlertRulesSvc) Update(req request.UpdateAlertRules) (err error) {
// 更新指标配置
metricConfigSvc := MetricConfigSvc{User: a.User}
_ = copier.Copy(&updateMetricConfig, &req)
updateMetricConfig.SourceFrom = 2
updateMetricConfig.Source = constant.SourceCustom
updateMetricConfig.Id = dbAlertRules.MetricConfigId
err = metricConfigSvc.Update(session, updateMetricConfig)
if err != nil {
return nil, err
}
// 更新预警规则配置
_, err = session.ID(data.Id).Update(&data)
return nil, err
})
// 更新预警策略配置
_, err = session.ID(data.Id).MustCols("duration").Update(&data)
err = a.CreatePrometheusRule(req.IsEnabled, data.Id, db, "update")
if err != nil {
return err
}
......@@ -237,16 +266,20 @@ func (a *AlertRulesSvc) UpdateIsEnabled(req request.UpdateIsEnabledAlertRules) (
return
}
if req.IsEnabled == 2 {
if item.IsEnabled == 1 {
prSvc := PrometheusRuleSvc{User: a.User}
var exist bool
_, exist, err = prSvc.Get(item)
if exist {
err = prSvc.Delete(item)
if err != nil {
return
}
}
} else if req.IsEnabled == 1 {
if item.IsEnabled == 2 {
prSvc := PrometheusRuleSvc{User: a.User}
var exist bool
_, exist, err = prSvc.Get(item)
if !exist {
err = prSvc.Create(item)
if err != nil {
return
......@@ -307,7 +340,7 @@ func (a *AlertRulesSvc) List(req request.ListAlertRules) (resp response.AlertRul
Or("acp.class_name LIKE ?", "%"+req.Keyword+"%")
}
resp.TotalCount, err = session.Limit(req.GetPageSize(), (req.GetPage()-1)*req.GetPageSize()).
OrderBy("r.created_at desc").
OrderBy("r.is_enabled asc,r.created_at desc").
FindAndCount(&resp.List)
for i := 0; i < len(resp.List); i++ {
_ = json.Unmarshal([]byte(resp.List[i].AlertRules.AlertCondition), &resp.List[i].AlertCondition)
......@@ -332,14 +365,15 @@ func (a *AlertRulesSvc) Delete(ids []string) (err error) {
}
if !exist {
prSvc := PrometheusRuleSvc{User: a.User}
var has bool
_, has, err = prSvc.Get(response.AlertRulesItem{AlertRules: entity.AlertRules{Id: id}})
if has {
err = prSvc.Delete(response.AlertRulesItem{AlertRules: entity.AlertRules{Id: id}})
if err != nil {
return
}
_, err = db.NewSession().Where("id = ?", id).Delete(new(entity.AlertRules))
if err != nil {
return
}
_, err = db.NewSession().Where("id = ?", id).Delete(new(entity.AlertRules))
} else {
return errors.New("alert_rules_id already exists in opensearch")
}
......
......@@ -7,8 +7,11 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"go.uber.org/zap"
"time"
"xorm.io/xorm"
)
......@@ -37,16 +40,20 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
)
if alertRulesId, ok = alert.Labels["alert_rules_id"]; !ok {
return errors.New("alert_rules_id not found in the map")
err = errors.New("alert_rules_id not found in the map")
conf.Logger.Error("err", zap.Error(err))
}
if riskLevelStr, ok = alert.Labels["risk_level"]; !ok {
return errors.New("risk_level not found in the map")
err = errors.New("risk_level not found in the map")
conf.Logger.Error("err", zap.Error(err))
}
riskLevel = cast.ToInt(riskLevelStr)
if currentValueStr, ok = alert.Annotations["value"]; !ok {
return errors.New("value not found in the map")
err = errors.New("value not found in the map")
conf.Logger.Error("err", zap.Error(err))
return
}
currentValue = cast.ToFloat64(currentValueStr)
......@@ -55,6 +62,11 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
return
}
if alertRulesItem.Id == "" {
conf.Logger.Error("err", zap.Error(errors.New("告警规则查询为空")))
return
}
alertItem, err = alertSvc.GetDataByAlertRulesIdAndRiskLevel(alertRulesId, riskLevel, 2)
if err != nil {
return
......@@ -68,12 +80,18 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
switch isNewAlert {
case true: // 新增数据到OpenSearch
max := alertSvc.CatCount(OpenSearchIndex)
var max int
max, err = alertSvc.GetIndexMaxID(conf.Options.OpenSearchIndex)
if err != nil {
// 获取id最大值
max = alertSvc.CatCount(conf.Options.OpenSearchIndex)
}
if max == 0 {
err = errors.New("failed to get doc count for index")
conf.Logger.Error("err", zap.Error(err))
return
}
alertId := max + 1
id := max + 1
for _, v := range alertRulesItem.AlertCondition {
if v.RiskLevel == riskLevel {
alertCondition = v
......@@ -81,12 +99,12 @@ func (a *AlertWebhookSvc) AlertWebhook(session *xorm.Session, req webhook.Messag
}
}
createAlert := request.CreateAlert{Alert: entity.Alert{
Id: alertId,
Id: id,
AlertPoint: alertRulesItem.ClassParentName + "/" + alertRulesItem.MetricName,
AlertRulesId: alertRulesItem.Id,
AlertRulesName: alertRulesItem.MetricName,
RiskLevel: riskLevel,
AlertTime: jsontime.Time(alert.StartsAt),
AlertTime: jsontime.Time(alert.StartsAt.Add(time.Hour * 8)),
ClassId: alertRulesItem.ClassId,
ClassParentName: alertRulesItem.ClassParentName,
ClassName: alertRulesItem.ClassName,
......
......@@ -10,6 +10,4 @@ func StartCron() {
defer c.Start()
c.AddFunc("0 0 0 * * *", service.CronStatusDetection) // 每天凌晨0点状态检测
c.AddFunc("0 0 0 * * *", service.CronWorkOrderIssuance) // 每天凌晨0点扫描当天需下发工单
}
......@@ -6,30 +6,46 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"strings"
"sync"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
)
var (
PrometheusRuleGroup = "monitoring.beagle.io" // kubectl api-resources | grep -i prome
PrometheusRuleVersion = "v1"
PrometheusRuleKind = "PrometheusRule"
Namespace = "beagle-monitoring"
PrometheusRuleApiVersion = PrometheusRuleGroup + "/" + PrometheusRuleVersion
PrometheusRuleName = strings.ToLower(PrometheusRuleKind) + "s." + PrometheusRuleGroup
PrometheusRuleNamePrefix = "beagle-prometheus-so-operation-api-rules" // beagle-monitoring beagle-prometheus-prometheus-operator 43d
promOnce sync.Once
prometheusRuleName string
alertOnce sync.Once
alertDefLabels map[string]string
)
var AlertDefLabels = map[string]string{
"app": "prometheus",
"app.bd-apaas.com/cluster-component": "monitoring",
"prometheus-operator": "monitoring",
"release": "beagle-prometheus",
func GetPrometheusRuleCRDName() string {
promOnce.Do(func() {
url := conf.Options.MonitorApiVersion // 请确保 conf 和其他相关配置可用
parts := strings.Split(url, "/")
if len(parts) == 0 || parts[0] == "" {
prometheusRuleName = "prometheusrules.monitoring.beagle.io"
} else {
prometheusRuleName = fmt.Sprintf("prometheusrules.%s", parts[0])
}
})
return prometheusRuleName
}
func GetAlertDefLabels() map[string]string {
alertOnce.Do(func() {
alertDefLabels = make(map[string]string)
err := json.Unmarshal([]byte(conf.Options.MonitorMatchLabelsStr), &alertDefLabels)
if err != nil {
fmt.Println("Error parsing JSON:", err)
}
})
return alertDefLabels
}
// GetPrometheusRuleName 获取规则CRD名称
func GetPrometheusRuleName(alertRulesId string) string {
return fmt.Sprintf("%s-%s", PrometheusRuleNamePrefix, alertRulesId)
// GetPrometheusRuleId 获取规则CRD名称
func GetPrometheusRuleId(alertPolicyId string) string {
return fmt.Sprintf("%s-%s", conf.Options.PrometheusRuleNamePrefix, alertPolicyId)
}
// GetPrometheusRuleGroupName 获取规则组名称
......@@ -43,19 +59,19 @@ type PrometheusRule struct {
func (p PrometheusRule) Create(pRule *monitoringv1.PrometheusRule) error {
k8sSvc := K8sSvc{Header: p.Header}
c := &Content{Kind: PrometheusRuleKind, ApiVersion: PrometheusRuleApiVersion, Metadata: pRule.ObjectMeta, Spec: pRule.Spec}
c := &Content{Kind: "PrometheusRule", ApiVersion: conf.Options.MonitorApiVersion, Metadata: pRule.ObjectMeta, Spec: pRule.Spec}
_, err := k8sSvc.SendFile(c)
return err
}
func (p PrometheusRule) Delete(namespace string, name string) error {
delUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, PrometheusRuleName, namespace, name)
delUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, GetPrometheusRuleCRDName(), namespace, name)
_, err := util.ProxySendRes("DELETE", delUrl, "", p.Header)
return err
}
func (p PrometheusRule) Update(pRule *monitoringv1.PrometheusRule) error {
updateUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, PrometheusRuleName, pRule.Namespace, pRule.Name)
updateUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, GetPrometheusRuleCRDName(), pRule.Namespace, pRule.Name)
body, _ := json.Marshal(pRule)
p.Header["Content-Type"] = "application/json"
_, err := util.ProxySendRes("PUT", updateUrl, string(body), p.Header)
......@@ -63,7 +79,7 @@ func (p PrometheusRule) Update(pRule *monitoringv1.PrometheusRule) error {
}
func (p PrometheusRule) Get(namespace string, name string) (obj *monitoringv1.PrometheusRule, err error) {
getUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, PrometheusRuleName, namespace, name)
getUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, GetPrometheusRuleCRDName(), namespace, name)
res, err := util.ProxySendRes("GET", getUrl, "", p.Header)
if err != nil {
return
......
......@@ -7,6 +7,7 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"xorm.io/xorm"
......@@ -25,6 +26,9 @@ func (m *MetricConfigSvc) Add(session *xorm.Session, req request.AddMetricConfig
UpdatedBy: m.User.SystemAccount,
UpdatedAt: now,
}
if req.Source != constant.SourceCustom {
req.Source = constant.SourceDefault
}
_ = copier.Copy(&data, &req)
data.AlertRange = util.ConvertToString(req.AlertRange)
_, err = session.Insert(&data)
......@@ -89,6 +93,17 @@ func (m *MetricConfigSvc) List(req request.ListMetricConfig) (resp response.Metr
return
}
func (m *MetricConfigSvc) NameList() (resp response.MetricConfigList, err error) {
db, err := client.GetDbClient()
if err != nil {
return
}
session := db.NewSession()
defer session.Close()
resp.TotalCount, err = session.Select("id,metric_name").FindAndCount(&resp.List)
return
}
func (m *MetricConfigSvc) Delete(ids []string) (err error) {
db, err := client.GetDbClient()
if err != nil {
......
......@@ -26,10 +26,10 @@ func (p *PrometheusSvc) Label(req request.PrometheusLabel) (resp response.Promet
if req.LabelName != "" {
url := fmt.Sprintf("%s%s", conf.Options.PrometheusHost, "/api/v1/series")
bytes, _ := util.Request(url, http.MethodPost,
response, _ := util.Request(url, http.MethodPost,
[]byte(fmt.Sprintf("match[]=%s", req.LabelName)),
map[string]string{"Content-Type": util.MediaTypeForm})
_ = json.Unmarshal(bytes, &prometheusSeries)
_ = json.Unmarshal(response.Body(), &prometheusSeries)
for _, v := range prometheusSeries.Data {
for k, _ := range v {
resp.List = append(resp.List, k)
......@@ -41,8 +41,8 @@ func (p *PrometheusSvc) Label(req request.PrometheusLabel) (resp response.Promet
} else {
url := fmt.Sprintf("%s%s", conf.Options.PrometheusHost, "/api/v1/label/__name__/values")
bytes, _ := util.Request(url, http.MethodGet, nil, nil)
_ = json.Unmarshal(bytes, &prometheusLabel)
response, _ := util.Request(url, http.MethodGet, nil, nil)
_ = json.Unmarshal(response.Body(), &prometheusLabel)
resp.TotalCount = int64(len(prometheusLabel.Data))
resp.List = prometheusLabel.Data
}
......@@ -57,10 +57,10 @@ func (p *PrometheusSvc) LabelValue(req request.PrometheusLabelValue) (resp respo
)
url := fmt.Sprintf("%s%s", conf.Options.PrometheusHost, "/api/v1/series")
bytes, _ := util.Request(url, http.MethodPost,
response, _ := util.Request(url, http.MethodPost,
[]byte(fmt.Sprintf("match[]=%s", req.MetricName)),
map[string]string{"Content-Type": util.MediaTypeForm})
_ = json.Unmarshal(bytes, &prometheusSeries)
_ = json.Unmarshal(response.Body(), &prometheusSeries)
for _, v := range prometheusSeries.Data {
for key, value := range v {
metricLabelMap[key] = append(metricLabelMap[key], value)
......
package service
import (
"errors"
"fmt"
json "github.com/json-iterator/go"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/spf13/cast"
"github.com/tidwall/gjson"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/service/k8s"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"go.uber.org/zap"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"net/http"
"net/url"
"strings"
"sync"
)
var prometheusRuleLabel map[string]string
var once sync.Once
func initPrometheusRuleLabel() {
once.Do(func() {
str := conf.Options.PrometheusRuleLabel
err := json.Unmarshal([]byte(str), &prometheusRuleLabel)
if err != nil {
prometheusRuleLabel = map[string]string{ // 返回默认标签
"source": "aiops-systemmonitor-api",
}
}
})
}
// GetPrometheusRuleLabel 返回 prometheusRuleLabel 单例
func GetPrometheusRuleLabel() map[string]string {
initPrometheusRuleLabel()
return prometheusRuleLabel
}
type PrometheusRuleSvc struct {
User entity.SystemUserInfo
}
func (p *PrometheusRuleSvc) Create(data response.AlertRulesItem) (err error) {
prometheusRuleName := k8s.GetPrometheusRuleName(data.Id)
prometheusRuleObjName := k8s.GetPrometheusRuleId(data.Id)
pr := monitoringv1.PrometheusRule{
ObjectMeta: v1.ObjectMeta{
Name: prometheusRuleName,
Namespace: k8s.Namespace,
Labels: k8s.AlertDefLabels,
Name: prometheusRuleObjName,
Namespace: conf.Options.MonitorMatchNs,
Labels: k8s.GetAlertDefLabels(),
},
}
......@@ -38,17 +66,24 @@ func (p *PrometheusRuleSvc) Create(data response.AlertRulesItem) (err error) {
item := fmt.Sprintf(`%s%s"%s"`, v.MetricLabel, v.Compare, v.Value) // http_requests_total{method="GET",pod="LeaseGrant"}
data.Expr = strings.ReplaceAll(data.Expr, v.VariableName, item)
}
for _, v := range data.AlertCondition {
rule := monitoringv1.Rule{
Alert: data.MetricConfigName,
For: &ruleFor,
Labels: map[string]string{
for k, v := range data.AlertCondition {
labels := map[string]string{
"severity": "warning",
"risk_level": cast.ToString(v.RiskLevel),
"risk_level_name": constant.RiskLeveText(v.RiskLevel),
"source": "so-operation-api",
"alert_rules_id": data.MetricConfigId,
},
"namespace": conf.Options.MonitorMatchNs,
"alert_rules_id": data.Id,
"metric_config_id": data.MetricConfigId,
}
for key, value := range GetPrometheusRuleLabel() {
labels[key] = value
}
rule := monitoringv1.Rule{
// promhttp超过5万次告警-prom指标控制器请求数-较大风险-3
Alert: fmt.Sprintf("%s-%s-%s-%d", data.MetricName, data.MetricConfigName, constant.RiskLeveText(v.RiskLevel), k+1),
For: &ruleFor,
Labels: labels,
Annotations: map[string]string{
"value": "{{ $value }}",
"summary": fmt.Sprintf("分组名:%s, 检查周期:%s, 持续时间:%s", group.Name, string(groupInterval), string(ruleFor)),
......@@ -68,6 +103,11 @@ func (p *PrometheusRuleSvc) Create(data response.AlertRulesItem) (err error) {
condition += 2
}
// 为"空"状态下,默认表达式已经有比较判断,故直接使用表达式即可
if data.AlertRuleTypeName == "空" {
condition = 0
}
switch condition {
default:
expr = data.Expr
......@@ -79,6 +119,12 @@ func (p *PrometheusRuleSvc) Create(data response.AlertRulesItem) (err error) {
expr = fmt.Sprintf("%s <= %s <=%s", cast.ToString(v.ThresholdsMin), data.Expr, cast.ToString(v.ThresholdsMax))
}
// 校验表达式正确性
err = CheckPrometheusQuerySyntax(expr)
if err != nil {
return
}
rule.Expr = intstr.FromString(expr)
group.Rules = append(group.Rules, rule)
}
......@@ -91,12 +137,12 @@ func (p *PrometheusRuleSvc) Create(data response.AlertRulesItem) (err error) {
}
func (p *PrometheusRuleSvc) Get(data response.AlertRulesItem) (obj *monitoringv1.PrometheusRule, exist bool, err error) {
prometheusRuleName := k8s.GetPrometheusRuleName(data.Id)
prometheusRuleObjName := k8s.GetPrometheusRuleId(data.Id)
pr := monitoringv1.PrometheusRule{
ObjectMeta: v1.ObjectMeta{
Name: prometheusRuleName,
Namespace: k8s.Namespace,
Labels: k8s.AlertDefLabels,
Name: prometheusRuleObjName,
Namespace: conf.Options.MonitorMatchNs,
Labels: k8s.GetAlertDefLabels(),
},
}
header := map[string]string{"Authorization": "Bearer " + conf.Options.KubernetesToken}
......@@ -109,13 +155,26 @@ func (p *PrometheusRuleSvc) Get(data response.AlertRulesItem) (obj *monitoringv1
return
}
// CheckPrometheusQuerySyntax 校验普罗米修斯语法正确性
func CheckPrometheusQuerySyntax(expr string) error {
params := url.Values{}
params.Add("query", expr)
query := params.Encode()
webUrl := fmt.Sprintf("%s%s%s", conf.Options.PrometheusHost, "/api/v1/query?", query)
resp, _ := util.Request(webUrl, http.MethodGet, nil, nil)
if resp.StatusCode() != http.StatusOK {
return errors.New(fmt.Sprintf("%s, err: %s", "普罗米修斯语法PromQL错误", gjson.GetBytes(resp.Body(), "error").String()))
}
return nil
}
func (p *PrometheusRuleSvc) Delete(data response.AlertRulesItem) (err error) {
prometheusRuleName := k8s.GetPrometheusRuleName(data.Id)
prometheusRuleObjName := k8s.GetPrometheusRuleId(data.Id)
pr := monitoringv1.PrometheusRule{
ObjectMeta: v1.ObjectMeta{
Name: prometheusRuleName,
Namespace: k8s.Namespace,
Labels: k8s.AlertDefLabels,
Name: prometheusRuleObjName,
Namespace: conf.Options.MonitorMatchNs,
Labels: k8s.GetAlertDefLabels(),
},
}
......
......@@ -272,85 +272,6 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq, script string) (id
return
}
go ExecAnsible(id, req.TaskId, req.Value)
////执行ansible命令
//var cmd *exec.Cmd
//if req.Value != "" {
// cmd = exec.Command("ansible-playbook", "-i", "/etc/ansible/hosts_"+fmt.Sprintf("%d", req.TaskId), "/etc/ansible/ansible_"+fmt.Sprintf("%d", req.TaskId)+".yml", "--extra-vars", req.Value)
//} else {
// cmd = exec.Command("ansible-playbook", "-i", "/etc/ansible/hosts_"+fmt.Sprintf("%d", req.TaskId), "/etc/ansible/ansible_"+fmt.Sprintf("%d", req.TaskId)+".yml")
//}
////ansible-playbook -i /tmp/hosts --list-hosts debug.yml
////捕获正常日志
//stdout, err := cmd.StdoutPipe()
//if err != nil {
// err = resp.CmdExecError.WithError(err)
// return
//}
////捕获异常日志
//stderr, err := cmd.StderrPipe()
//if err != nil {
// err = resp.CmdExecError.WithError(err)
// return
//}
////执行cmd命令
//if err = cmd.Start(); err != nil {
// err = resp.CmdExecError.WithError(err)
// return
//}
////获取 正常/异常 输出流
//outputBuf := bufio.NewReader(stdout)
//readerr := bufio.NewReader(stderr)
//
//var out, outErr int
//var execLog string
//for {
//
// //逐行输出日志
// lineOut, err1 := outputBuf.ReadString('\n')
// if (err1 != nil || io.EOF == err1) && out == 0 {
// out = 1
// } else if out == 0 {
// //存储执行日志
// execLog = execLog + lineOut + " \n "
// UpdateExecHistory(request.UpdateExecHistory{
// TaskHistoryId: id,
// ExecLog: execLog,
// })
// }
//
// lineErr, err2 := readerr.ReadString('\n')
// if (err2 != nil || io.EOF == err2) && outErr == 0 {
// outErr = 1
// } else if outErr == 0 {
// //存储异常执行日志
// execLog = execLog + lineErr + " \n "
// UpdateExecHistory(request.UpdateExecHistory{
// TaskHistoryId: id,
// ExecLog: execLog,
// })
// }
//
// if out == 1 && outErr == 1 {
// break
// }
//}
//cmd.Wait()
//
//if cmd.ProcessState.Success() {
// //任务执行成功
// UpdateExecHistory(request.UpdateExecHistory{
// TaskHistoryId: id,
// ExecLog: execLog,
// State: 1,
// })
//} else {
// //任务执行失败
// UpdateExecHistory(request.UpdateExecHistory{
// TaskHistoryId: id,
// ExecLog: execLog,
// State: 2,
// })
//}
return
}
......
This diff is collapsed.
......@@ -60,7 +60,7 @@ Request("https://httpbin.org/put",
"Cookie": "aweToken=3ab9f63f-b0b3-4935-80ec-405d76ac111d",
})
*/
func Request(url string, method string, body []byte, headers map[string]string) ([]byte, error) {
func Request(url string, method string, body []byte, headers map[string]string) (*fasthttp.Response, error) {
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
......@@ -98,8 +98,11 @@ func Request(url string, method string, body []byte, headers map[string]string)
return nil, err
}
result := new(fasthttp.Response)
resp.CopyTo(result)
// 返回响应体和错误信息
return resp.Body(), nil
return result, nil
}
// HttpSend , http请求 GET/DELETE/POST/PUT
......
......@@ -16,3 +16,14 @@ func ConvertToString(v interface{}) string {
}
return string(jsonData)
}
// IntsToStrings 将int切片转换为字符串切片
func IntsToStrings(ints []int) []string {
strs := make([]string, len(ints))
for i, v := range ints {
strs[i] = fmt.Sprint(v)
}
return strs
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment