Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
so-operation-api
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
smart-operation
so-operation-api
Commits
f90898aa
Commit
f90898aa
authored
Oct 18, 2023
by
李科
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: 代码迁移
parent
01beca36
Changes
17
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
414 additions
and
111 deletions
+414
-111
go.mod
go.mod
+1
-1
src/bean/vo/request/alert_class.go
src/bean/vo/request/alert_class.go
+1
-0
src/bean/vo/request/alert_rules.go
src/bean/vo/request/alert_rules.go
+1
-1
src/bean/vo/request/alert_webhook.go
src/bean/vo/request/alert_webhook.go
+1
-1
src/common/conf/options.go
src/common/conf/options.go
+12
-1
src/controller/alert_webhook.go
src/controller/alert_webhook.go
+8
-2
src/main.go
src/main.go
+27
-16
src/router/alertwebhookrouter.go.go
src/router/alertwebhookrouter.go.go
+1
-2
src/service/alert.go
src/service/alert.go
+108
-14
src/service/alert_class.go
src/service/alert_class.go
+60
-4
src/service/alert_overview.go
src/service/alert_overview.go
+6
-5
src/service/alert_rules.go
src/service/alert_rules.go
+36
-8
src/service/alert_webhook.go
src/service/alert_webhook.go
+25
-7
src/service/k8s/prometheusrule.go
src/service/k8s/prometheusrule.go
+35
-19
src/service/prometheus.go
src/service/prometheus.go
+6
-6
src/service/prometheusrule.go
src/service/prometheusrule.go
+81
-22
src/util/http.go
src/util/http.go
+5
-2
No files found.
go.mod
View file @
f90898aa
...
...
@@ -32,6 +32,7 @@ require (
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
...
...
@@ -108,7 +109,6 @@ 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/gjson v1.16.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
...
...
src/bean/vo/request/alert_class.go
View file @
f90898aa
...
...
@@ -9,6 +9,7 @@ type AddAlertClass struct {
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"`
}
...
...
src/bean/vo/request/alert_rules.go
View file @
f90898aa
...
...
@@ -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"`
// 预警规则 字典值
...
...
src/bean/vo/request/alert_webhook.go
View file @
f90898aa
...
...
@@ -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"`
// 预警规则 字典值
...
...
src/common/conf/options.go
View file @
f90898aa
...
...
@@ -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
(
...
...
src/controller/alert_webhook.go
View file @
f90898aa
...
...
@@ -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
)
...
...
src/main.go
View file @
f90898aa
...
...
@@ -48,7 +48,7 @@ func main() {
// 初始化OpenSearch的索引
err
:=
service
.
CheckAndCreateIndex
()
if
err
!=
nil
{
conf
.
Logger
.
Fatal
(
"failed to init OpenSearch index.
"
,
zap
.
Error
(
err
))
conf
.
Logger
.
Error
(
"failed to init OpenSearch index
"
,
zap
.
Error
(
err
))
}
//启动定时任务
...
...
@@ -80,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"
),
...
...
@@ -91,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
(
"S
ms_Template_Alert
"
,
"SMS_461975765"
),
// 预警短信模板 // 短信工单下发模板
SmsTemplateAlert
:
util
.
SetEnvStr
(
"S
MS_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"
),
// OpenSearch连接地址
OpenSearchUserName
:
util
.
SetEnvStr
(
"Open_Search_User_Name"
,
""
),
// OpenSearch用户名
OpenSearchPassword
:
util
.
SetEnvStr
(
"Open_Search_Password"
,
""
),
// OpenSearch密码
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
}
}
...
...
src/router/alertwebhookrouter.go.go
View file @
f90898aa
...
...
@@ -5,12 +5,11 @@ 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"
)
// InitAlertWebhookRouter 初始化预警回调路由
func
InitAlertWebhookRouter
(
e
*
gin
.
Engine
)
{
group
:=
e
.
Group
(
fmt
.
Sprintf
(
"%s/alert_webhook"
,
conf
.
Options
.
Prefix
)
,
header
.
SetContext
)
group
:=
e
.
Group
(
fmt
.
Sprintf
(
"%s/alert_webhook"
,
conf
.
Options
.
Prefix
))
{
group
.
POST
(
""
,
controller
.
AlertWebhook
)
}
...
...
src/service/alert.go
View file @
f90898aa
...
...
@@ -32,7 +32,6 @@ type AlertSvc struct {
}
var
(
OpenSearchIndex
=
"so_alert"
Mapping
=
strings
.
NewReader
(
`{
"settings": {
"number_of_shards": 1,
...
...
@@ -284,7 +283,7 @@ var (
)
func
CheckAndCreateIndex
()
(
err
error
)
{
exist
,
err
:=
checkIndexExists
(
OpenSearchIndex
)
exist
,
err
:=
checkIndexExists
(
conf
.
Options
.
OpenSearchIndex
)
if
err
!=
nil
{
return
}
...
...
@@ -293,7 +292,7 @@ func CheckAndCreateIndex() (err error) {
return
nil
}
err
=
CreateIndex
(
OpenSearchIndex
)
err
=
CreateIndex
(
conf
.
Options
.
OpenSearchIndex
)
if
err
!=
nil
{
return
err
}
...
...
@@ -346,7 +345,7 @@ func (a *AlertSvc) DeleteIndex() error {
return
err
}
res
:=
opensearchapi
.
IndicesDeleteRequest
{
Index
:
[]
string
{
OpenSearchIndex
},
Index
:
[]
string
{
conf
.
Options
.
OpenSearchIndex
},
}
do
,
err
:=
res
.
Do
(
context
.
Background
(),
cli
)
if
err
!=
nil
{
...
...
@@ -427,8 +426,11 @@ func (a *AlertSvc) DocSearch(req request.ListAlert) (resp response.AlertList, er
// 请输入预警点/分类/指标
if
req
.
Keyword
!=
""
{
subBoolQuery
:=
elastic
.
NewBoolQuery
()
subBoolQuery
.
Should
(
elastic
.
NewMultiMatchQuery
(
req
.
Keyword
,
"alert_point"
,
"class_parent_name"
,
"class_name"
,
"metric_config_name"
))
//subBoolQuery.Should(elastic.NewMatchQuery("class_name", req.Keyword))
//subBoolQuery.Should(elastic.NewMultiMatchQuery(req.Keyword, "alert_point", "class_parent_name", "class_name", "metric_config_name"))
subBoolQuery
.
Should
(
elastic
.
NewPrefixQuery
(
"alert_point.keyword"
,
req
.
Keyword
))
subBoolQuery
.
Should
(
elastic
.
NewPrefixQuery
(
"class_parent_name.keyword"
,
req
.
Keyword
))
subBoolQuery
.
Should
(
elastic
.
NewPrefixQuery
(
"class_name.keyword"
,
req
.
Keyword
))
subBoolQuery
.
Should
(
elastic
.
NewPrefixQuery
(
"metric_config_name.keyword"
,
req
.
Keyword
))
boolQuery
.
Must
(
subBoolQuery
)
}
...
...
@@ -467,7 +469,7 @@ func (a *AlertSvc) DocSearch(req request.ListAlert) (resp response.AlertList, er
"size": %d}`
,
string
(
b
),
req
.
GetPageSize
()
*
(
req
.
GetPage
()
-
1
),
req
.
GetPageSize
()))
res
:=
opensearchapi
.
SearchRequest
{
Index
:
[]
string
{
OpenSearchIndex
},
Index
:
[]
string
{
conf
.
Options
.
OpenSearchIndex
},
Body
:
content
,
Sort
:
[]
string
{
"id"
},
}
...
...
@@ -493,6 +495,38 @@ func (a *AlertSvc) DocSearch(req request.ListAlert) (resp response.AlertList, er
for
_
,
hit
:=
range
sources
.
Hits
.
Hits
{
resp
.
List
=
append
(
resp
.
List
,
hit
.
Source
)
}
// 推送人数:推送记录中去重的人数
// 推送次数:发起推送的总次数(钉钉、短信、工单算单次)
for
i
:=
0
;
i
<
len
(
resp
.
List
);
i
++
{
var
userSet
[]
string
var
pushCountSet
[]
string
mergedData
:=
make
(
map
[
string
]
entity
.
PushRecord
)
for
_
,
record
:=
range
resp
.
List
[
i
]
.
PushRecords
{
userSet
=
append
(
userSet
,
record
.
SystemAccount
)
pushCountSet
=
append
(
pushCountSet
,
record
.
PushTime
.
String
())
key
:=
record
.
AlertRulesId
+
record
.
PushTime
.
String
()
// 映射中已存在相同键的数据,则合并user_id
if
existingRecord
,
found
:=
mergedData
[
key
];
found
{
existingRecord
.
SystemAccount
+=
", "
+
record
.
SystemAccount
existingRecord
.
UserName
+=
", "
+
record
.
UserName
mergedData
[
key
]
=
existingRecord
}
else
{
mergedData
[
key
]
=
record
}
}
var
mergedRecords
[]
entity
.
PushRecord
for
_
,
v
:=
range
mergedData
{
mergedRecords
=
append
(
mergedRecords
,
v
)
}
resp
.
List
[
i
]
.
PushRecords
=
mergedRecords
resp
.
List
[
i
]
.
NotificationCount
=
len
(
funk
.
UniqString
(
userSet
))
resp
.
List
[
i
]
.
PushCount
=
len
(
funk
.
UniqString
(
pushCountSet
))
}
resp
.
TotalCount
=
int64
(
sources
.
Hits
.
Total
.
Value
)
return
}
...
...
@@ -524,7 +558,7 @@ func (a *AlertSvc) IndexDocExist(req request.ExistAlert) (exist bool, err error)
"size": %d}`
,
string
(
b
),
0
,
1
))
res
:=
opensearchapi
.
SearchRequest
{
Index
:
[]
string
{
OpenSearchIndex
},
Index
:
[]
string
{
conf
.
Options
.
OpenSearchIndex
},
Body
:
content
,
Sort
:
[]
string
{
"id"
},
}
...
...
@@ -567,7 +601,7 @@ func (a *AlertSvc) CatCount(indexName ...string) (count int) {
if
len
(
indexName
)
>
0
&&
indexName
[
0
]
!=
""
{
index
=
indexName
[
0
]
+
"*"
}
else
{
index
=
OpenSearchIndex
+
"*"
index
=
conf
.
Options
.
OpenSearchIndex
+
"*"
}
res
:=
opensearchapi
.
CatCountRequest
{
...
...
@@ -597,6 +631,66 @@ func (a *AlertSvc) CatCount(indexName ...string) (count int) {
return
}
func
(
a
*
AlertSvc
)
GetIndexMaxID
(
indexName
...
string
)
(
maxId
int
,
err
error
)
{
var
(
index
string
)
cli
,
err
:=
client
.
GetOpenSearch
()
if
err
!=
nil
{
return
0
,
err
}
if
len
(
indexName
)
>
0
&&
indexName
[
0
]
!=
""
{
index
=
indexName
[
0
]
}
else
{
index
=
conf
.
Options
.
OpenSearchIndex
}
// 构建 aggregation 查询
aggregationQuery
:=
`
{
"size": 0,
"aggs": {
"max_id": {
"max": {
"field": "id"
}
}
}
}
`
res
:=
opensearchapi
.
SearchRequest
{
Index
:
[]
string
{
index
},
Body
:
strings
.
NewReader
(
aggregationQuery
),
}
do
,
err
:=
res
.
Do
(
context
.
Background
(),
cli
)
if
err
!=
nil
{
return
0
,
err
}
defer
do
.
Body
.
Close
()
if
do
.
StatusCode
<
http
.
StatusOK
&&
do
.
StatusCode
>
http
.
StatusIMUsed
{
return
0
,
errors
.
New
(
do
.
String
())
}
// 解析聚合结果
var
responseMap
map
[
string
]
interface
{}
err
=
json
.
NewDecoder
(
do
.
Body
)
.
Decode
(
&
responseMap
)
if
err
!=
nil
{
return
0
,
err
}
// 提取最大值
aggregations
:=
responseMap
[
"aggregations"
]
.
(
map
[
string
]
interface
{})
maxIDAgg
:=
aggregations
[
"max_id"
]
.
(
map
[
string
]
interface
{})
maxIDValue
:=
maxIDAgg
[
"value"
]
maxId
=
int
(
maxIDValue
.
(
float64
))
return
maxId
,
nil
}
func
(
a
*
AlertSvc
)
DocCreate
(
req
request
.
CreateAlert
)
(
err
error
)
{
var
(
sources
response
.
OpenSearchSource
...
...
@@ -616,7 +710,7 @@ func (a *AlertSvc) DocCreate(req request.CreateAlert) (err error) {
content
:=
strings
.
NewReader
(
fmt
.
Sprintf
(
`%s`
,
docStr
))
res
:=
opensearchapi
.
CreateRequest
{
Index
:
OpenSearchIndex
,
Index
:
conf
.
Options
.
OpenSearchIndex
,
DocumentID
:
cast
.
ToString
(
req
.
Id
),
Body
:
content
,
}
...
...
@@ -696,7 +790,7 @@ func (a *AlertSvc) DocUpdate(req request.UpdateAlert) (err error) {
}`
,
docStr
))
res
:=
opensearchapi
.
UpdateRequest
{
Index
:
OpenSearchIndex
,
Index
:
conf
.
Options
.
OpenSearchIndex
,
DocumentID
:
cast
.
ToString
(
req
.
Id
),
Body
:
content
,
Source
:
[]
string
{
"true"
},
...
...
@@ -730,7 +824,7 @@ func (a *AlertSvc) Create() error {
return
err
}
res
:=
opensearchapi
.
IndicesCreateRequest
{
Index
:
OpenSearchIndex
,
Index
:
conf
.
Options
.
OpenSearchIndex
,
Body
:
Mapping
,
}
do
,
err
:=
res
.
Do
(
context
.
Background
(),
cli
)
...
...
@@ -926,7 +1020,7 @@ func (a *AlertSvc) DisposeAlert(req request.DisposeAlert) (err error) {
}`
,
docStr
))
res
:=
opensearchapi
.
UpdateRequest
{
Index
:
OpenSearchIndex
,
Index
:
conf
.
Options
.
OpenSearchIndex
,
DocumentID
:
cast
.
ToString
(
req
.
Id
),
Body
:
content
,
Source
:
[]
string
{
"true"
},
...
...
src/service/alert_class.go
View file @
f90898aa
...
...
@@ -52,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
}
...
...
@@ -150,6 +150,9 @@ func (a *AlertClassSvc) List(req request.ListAlertClass) (resp response.AlertCla
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
...
...
@@ -234,8 +237,61 @@ func (a *AlertClassSvc) SortOrderMax(parentId int) (max int, err error) {
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
}
src/service/alert_overview.go
View file @
f90898aa
...
...
@@ -14,6 +14,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/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"
"io"
...
...
@@ -132,7 +133,7 @@ func (a *AlertOverviewSvc) AlertOverview(req request.DetailAlertOverview) (resp
}
}`
,
req
.
StartTime
,
req
.
EndTime
)
body
,
err
:=
executeQuery
(
cli
,
OpenSearchIndex
,
content
)
body
,
err
:=
executeQuery
(
cli
,
conf
.
Options
.
OpenSearchIndex
,
content
)
if
err
!=
nil
{
return
}
...
...
@@ -190,7 +191,7 @@ func (a *AlertOverviewSvc) RiskLevelDistribution(req request.DetailAlertOverview
req
.
EndTime
=
time
.
Now
()
.
Add
(
time
.
Hour
*
24
)
.
Format
(
"2006-01-02"
)
}
body
,
err
:=
executeQuery
(
cli
,
OpenSearchIndex
,
buildAggQueryContent
(
req
.
StartTime
,
req
.
EndTime
,
"risk_level"
))
body
,
err
:=
executeQuery
(
cli
,
conf
.
Options
.
OpenSearchIndex
,
buildAggQueryContent
(
req
.
StartTime
,
req
.
EndTime
,
"risk_level"
))
if
err
!=
nil
{
return
}
...
...
@@ -235,7 +236,7 @@ func (a *AlertOverviewSvc) AlertStatusDistribution(req request.DetailAlertOvervi
req
.
EndTime
=
time
.
Now
()
.
Add
(
time
.
Hour
*
24
)
.
Format
(
"2006-01-02"
)
}
body
,
err
:=
executeQuery
(
cli
,
OpenSearchIndex
,
buildAggQueryContent
(
req
.
StartTime
,
req
.
EndTime
,
"status"
))
body
,
err
:=
executeQuery
(
cli
,
conf
.
Options
.
OpenSearchIndex
,
buildAggQueryContent
(
req
.
StartTime
,
req
.
EndTime
,
"status"
))
if
err
!=
nil
{
return
}
...
...
@@ -279,7 +280,7 @@ func (a *AlertOverviewSvc) AlertClassDistribution(req request.DetailAlertOvervie
req
.
EndTime
=
time
.
Now
()
.
Add
(
time
.
Hour
*
24
)
.
Format
(
"2006-01-02"
)
}
body
,
err
:=
executeQuery
(
cli
,
OpenSearchIndex
,
buildAggQueryContent
(
req
.
StartTime
,
req
.
EndTime
,
"class_id"
))
body
,
err
:=
executeQuery
(
cli
,
conf
.
Options
.
OpenSearchIndex
,
buildAggQueryContent
(
req
.
StartTime
,
req
.
EndTime
,
"class_id"
))
if
err
!=
nil
{
return
}
...
...
@@ -355,7 +356,7 @@ func (a *AlertOverviewSvc) AlertFrequencyDistribution(req request.DetailAlertOve
}
}`
body
,
err
:=
executeQuery
(
cli
,
OpenSearchIndex
,
content
)
body
,
err
:=
executeQuery
(
cli
,
conf
.
Options
.
OpenSearchIndex
,
content
)
if
err
!=
nil
{
return
}
...
...
src/service/alert_rules.go
View file @
f90898aa
...
...
@@ -74,12 +74,14 @@ func (a *AlertRulesSvc) Add(req request.AddAlertRules) (err error) {
return
nil
,
err
}
data
.
ClassId
=
classId
req
.
ClassId
=
classId
// 添加指标配置
metricConfigSvc
:=
MetricConfigSvc
{
User
:
a
.
User
}
_
=
copier
.
Copy
(
&
addMetricConfig
,
&
req
)
addMetricConfig
.
Source
=
constant
.
SourceCustom
addMetricConfig
.
MetricName
=
req
.
MetricConfigName
addMetricConfig
.
ClassId
=
classId
metricConfigId
,
err
=
metricConfigSvc
.
Add
(
session
,
addMetricConfig
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -88,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
}
...
...
@@ -125,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
}
...
...
@@ -134,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
}
alertClass
Item
,
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
:
alertClass
Item
.
ParentId
,
ClassId
:
alertClass
.
ParentId
,
ClassName
:
req
.
ClassParentName
,
ParentId
:
alertParentClass
.
ParentId
,
})
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -166,11 +193,12 @@ func (a *AlertRulesSvc) Update(req request.UpdateAlertRules) (err error) {
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
}
...
...
@@ -312,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
)
...
...
src/service/alert_webhook.go
View file @
f90898aa
...
...
@@ -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
}
alertI
d
:=
max
+
1
i
d
:=
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
:
alertI
d
,
Id
:
i
d
,
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
,
...
...
src/service/k8s/prometheusrule.go
View file @
f90898aa
...
...
@@ -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
}
// GetPrometheusRule
Name
获取规则CRD名称
func
GetPrometheusRule
Name
(
alertRules
Id
string
)
string
{
return
fmt
.
Sprintf
(
"%s-%s"
,
PrometheusRuleNamePrefix
,
alertRules
Id
)
// GetPrometheusRule
Id
获取规则CRD名称
func
GetPrometheusRule
Id
(
alertPolicy
Id
string
)
string
{
return
fmt
.
Sprintf
(
"%s-%s"
,
conf
.
Options
.
PrometheusRuleNamePrefix
,
alertPolicy
Id
)
}
// 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
:
PrometheusRule
ApiVersion
,
Metadata
:
pRule
.
ObjectMeta
,
Spec
:
pRule
.
Spec
}
c
:=
&
Content
{
Kind
:
"PrometheusRule"
,
ApiVersion
:
conf
.
Options
.
Monitor
ApiVersion
,
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
...
...
src/service/prometheus.go
View file @
f90898aa
...
...
@@ -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
)
...
...
src/service/prometheusrule.go
View file @
f90898aa
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
)
{
prometheusRule
Name
:=
k8s
.
GetPrometheusRuleName
(
data
.
Id
)
prometheusRule
ObjName
:=
k8s
.
GetPrometheusRuleId
(
data
.
Id
)
pr
:=
monitoringv1
.
PrometheusRule
{
ObjectMeta
:
v1
.
ObjectMeta
{
Name
:
prometheusRuleName
,
Namespace
:
k8s
.
Namespace
,
Labels
:
k8s
.
AlertDefLabels
,
Name
:
prometheusRule
Obj
Name
,
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
)
{
prometheusRule
Name
:=
k8s
.
GetPrometheusRuleName
(
data
.
Id
)
prometheusRule
ObjName
:=
k8s
.
GetPrometheusRuleId
(
data
.
Id
)
pr
:=
monitoringv1
.
PrometheusRule
{
ObjectMeta
:
v1
.
ObjectMeta
{
Name
:
prometheusRuleName
,
Namespace
:
k8s
.
Namespace
,
Labels
:
k8s
.
AlertDefLabels
,
Name
:
prometheusRule
Obj
Name
,
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
)
{
prometheusRule
Name
:=
k8s
.
GetPrometheusRuleName
(
data
.
Id
)
prometheusRule
ObjName
:=
k8s
.
GetPrometheusRuleId
(
data
.
Id
)
pr
:=
monitoringv1
.
PrometheusRule
{
ObjectMeta
:
v1
.
ObjectMeta
{
Name
:
prometheusRuleName
,
Namespace
:
k8s
.
Namespace
,
Labels
:
k8s
.
AlertDefLabels
,
Name
:
prometheusRule
Obj
Name
,
Namespace
:
conf
.
Options
.
MonitorMatchNs
,
Labels
:
k8s
.
GetAlertDefLabels
()
,
},
}
...
...
src/util/http.go
View file @
f90898aa
...
...
@@ -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
)
(
[]
byt
e
,
error
)
{
func
Request
(
url
string
,
method
string
,
body
[]
byte
,
headers
map
[
string
]
string
)
(
*
fasthttp
.
Respons
e
,
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
res
p
.
Body
()
,
nil
return
res
ult
,
nil
}
// HttpSend , http请求 GET/DELETE/POST/PUT
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment