Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
梦中观雨
cat
提交
30de9a29
C
cat
项目概览
梦中观雨
/
cat
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
cat
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
30de9a29
编写于
5月 19, 2014
作者:
Y
youyong205
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #304 from leonindy/master
add monitor rule page & job
上级
d6e47be2
5ffbb084
变更
33
隐藏空白更改
内联
并排
Showing
33 changed file
with
2000 addition
and
80 deletion
+2000
-80
cat-client/src/main/resources/com/dianping/cat/configuration/client/config.xsd
...esources/com/dianping/cat/configuration/client/config.xsd
+1
-2
cat-client/src/main/resources/com/dianping/cat/status/model/status.xsd
...c/main/resources/com/dianping/cat/status/model/status.xsd
+1
-2
cat-home/pom.xml
cat-home/pom.xml
+1
-0
cat-home/src/main/java/com/dianping/cat/report/page/alteration/Handler.java
...java/com/dianping/cat/report/page/alteration/Handler.java
+11
-2
cat-home/src/main/java/com/dianping/cat/report/page/alteration/Payload.java
...java/com/dianping/cat/report/page/alteration/Payload.java
+38
-4
cat-home/src/main/java/com/dianping/cat/report/task/metric/AlertConfig.java
...java/com/dianping/cat/report/task/metric/AlertConfig.java
+184
-22
cat-home/src/main/java/com/dianping/cat/report/task/metric/MetricAlert.java
...java/com/dianping/cat/report/task/metric/MetricAlert.java
+148
-31
cat-home/src/main/java/com/dianping/cat/report/task/metric/RuleType.java
...in/java/com/dianping/cat/report/task/metric/RuleType.java
+96
-0
cat-home/src/main/java/com/dianping/cat/report/task/metric/SwitchAlert.java
...java/com/dianping/cat/report/task/metric/SwitchAlert.java
+431
-0
cat-home/src/main/java/com/dianping/cat/report/task/metric/SwitchAlertConfig.java
...om/dianping/cat/report/task/metric/SwitchAlertConfig.java
+264
-0
cat-home/src/main/java/com/dianping/cat/system/config/MetricRuleConfigManager.java
...m/dianping/cat/system/config/MetricRuleConfigManager.java
+176
-0
cat-home/src/main/java/com/dianping/cat/system/page/config/Action.java
...main/java/com/dianping/cat/system/page/config/Action.java
+2
-0
cat-home/src/main/java/com/dianping/cat/system/page/config/Handler.java
...ain/java/com/dianping/cat/system/page/config/Handler.java
+13
-0
cat-home/src/main/java/com/dianping/cat/system/page/config/JspFile.java
...ain/java/com/dianping/cat/system/page/config/JspFile.java
+2
-0
cat-home/src/main/java/com/dianping/cat/system/page/config/JspViewer.java
...n/java/com/dianping/cat/system/page/config/JspViewer.java
+2
-0
cat-home/src/main/resources/META-INF/dal/model/monitor-rules-codegen.xml
...in/resources/META-INF/dal/model/monitor-rules-codegen.xml
+29
-0
cat-home/src/main/resources/META-INF/dal/model/monitor-rules-manifest.xml
...n/resources/META-INF/dal/model/monitor-rules-manifest.xml
+6
-0
cat-home/src/main/resources/META-INF/dal/model/monitor-rules-model.xml
...main/resources/META-INF/dal/model/monitor-rules-model.xml
+31
-0
cat-home/src/main/resources/META-INF/plexus/components.xml
cat-home/src/main/resources/META-INF/plexus/components.xml
+12
-0
cat-home/src/main/resources/META-INF/wizard/model/wizard.xml
cat-home/src/main/resources/META-INF/wizard/model/wizard.xml
+3
-0
cat-home/src/main/resources/config/default-metric-rule-config.xml
.../src/main/resources/config/default-metric-rule-config.xml
+43
-0
cat-home/src/main/webapp/images/rule.png
cat-home/src/main/webapp/images/rule.png
+0
-0
cat-home/src/main/webapp/jsp/report/alteration/alter_query.jsp
...ome/src/main/webapp/jsp/report/alteration/alter_query.jsp
+22
-3
cat-home/src/main/webapp/jsp/report/alteration/alter_view.jsp
...home/src/main/webapp/jsp/report/alteration/alter_view.jsp
+33
-11
cat-home/src/main/webapp/jsp/report/home/home.jsp
cat-home/src/main/webapp/jsp/report/home/home.jsp
+2
-0
cat-home/src/main/webapp/jsp/report/home/monitorRule.jsp
cat-home/src/main/webapp/jsp/report/home/monitorRule.jsp
+43
-0
cat-home/src/main/webapp/jsp/system/configTree.jsp
cat-home/src/main/webapp/jsp/system/configTree.jsp
+1
-0
cat-home/src/main/webapp/jsp/system/metricRule/metricRuleConfig.jsp
...rc/main/webapp/jsp/system/metricRule/metricRuleConfig.jsp
+49
-0
cat-home/src/test/java/com/dianping/cat/demo/RuleConfigTest.java
...e/src/test/java/com/dianping/cat/demo/RuleConfigTest.java
+98
-0
cat-home/src/test/java/com/dianping/cat/report/task/metric/AlertConfigTest.java
.../com/dianping/cat/report/task/metric/AlertConfigTest.java
+103
-3
cat-home/src/test/resources/config/demo-rule-monitor.xml
cat-home/src/test/resources/config/demo-rule-monitor.xml
+45
-0
cat-home/src/test/resources/config/test-minute-monitor.xml
cat-home/src/test/resources/config/test-minute-monitor.xml
+12
-0
cat-home/src/test/resources/config/test-rule-monitor.xml
cat-home/src/test/resources/config/test-rule-monitor.xml
+98
-0
未找到文件。
cat-client/src/main/resources/com/dianping/cat/configuration/client/config.xsd
浏览文件 @
30de9a29
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs=
"http://www.w3.org/2001/XMLSchema"
elementFormDefault=
"qualified"
attributeFormDefault=
"unqualified"
>
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs=
"http://www.w3.org/2001/XMLSchema"
elementFormDefault=
"qualified"
attributeFormDefault=
"unqualified"
>
<xs:element
name=
"config"
type=
"ConfigType"
/>
<xs:complexType
name=
"ConfigType"
>
<xs:sequence>
...
...
cat-client/src/main/resources/com/dianping/cat/status/model/status.xsd
浏览文件 @
30de9a29
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs=
"http://www.w3.org/2001/XMLSchema"
elementFormDefault=
"qualified"
attributeFormDefault=
"unqualified"
>
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs=
"http://www.w3.org/2001/XMLSchema"
elementFormDefault=
"qualified"
attributeFormDefault=
"unqualified"
>
<xs:element
name=
"status"
type=
"StatusType"
/>
<xs:complexType
name=
"StatusType"
>
<xs:sequence>
...
...
cat-home/pom.xml
浏览文件 @
30de9a29
...
...
@@ -164,6 +164,7 @@
${basedir}/src/main/resources/META-INF/dal/model/metric-aggregation-config-manifest.xml,
${basedir}/src/main/resources/META-INF/dal/model/netgraph-manifest.xml,
${basedir}/src/main/resources/META-INF/dal/model/alert-report-manifest.xml,
${basedir}/src/main/resources/META-INF/dal/model/monitor-rules-manifest.xml,
</manifest>
</configuration>
</execution>
...
...
cat-home/src/main/java/com/dianping/cat/report/page/alteration/Handler.java
浏览文件 @
30de9a29
package
com.dianping.cat.report.page.alteration
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.net.URLDecoder
;
import
java.util.Date
;
import
java.util.List
;
...
...
@@ -47,9 +49,15 @@ public class Handler implements PageHandler<Context> {
alt
.
setUser
(
user
);
alt
.
setAltGroup
(
group
);
alt
.
setContent
(
content
);
alt
.
setUrl
(
url
);
alt
.
setHostname
(
hostname
);
alt
.
setDate
(
date
);
try
{
alt
.
setUrl
(
URLDecoder
.
decode
(
url
,
"UTF-8"
));
}
catch
(
UnsupportedEncodingException
e
)
{
Cat
.
logError
(
e
);
alt
.
setUrl
(
""
);
}
return
alt
;
}
...
...
@@ -113,6 +121,7 @@ public class Handler implements PageHandler<Context> {
}
}
public
boolean
isArguComplete
(
Payload
payload
)
{
if
(
StringUtils
.
isEmpty
(
payload
.
getType
()))
{
return
false
;
...
...
@@ -150,7 +159,7 @@ public class Handler implements PageHandler<Context> {
}
else
if
(
status
==
1
)
{
model
.
setInsertResult
(
"{\"status\":500}"
);
}
else
if
(
status
==
2
)
{
model
.
setInsertResult
(
"{\"status\":
2
00, \"errorMessage\":\"lack args\"}"
);
model
.
setInsertResult
(
"{\"status\":
5
00, \"errorMessage\":\"lack args\"}"
);
}
}
...
...
cat-home/src/main/java/com/dianping/cat/report/page/alteration/Payload.java
浏览文件 @
30de9a29
...
...
@@ -22,6 +22,15 @@ public class Payload extends AbstractReportPayload<Action> {
@FieldMeta
(
"fullScreen"
)
private
boolean
fullScreen
=
false
;
@FieldMeta
(
"showPuppet"
)
private
boolean
m_isShowPuppet
=
true
;
@FieldMeta
(
"showWorkflow"
)
private
boolean
m_isShowWorkflow
=
true
;
@FieldMeta
(
"showLazyman"
)
private
boolean
m_isShowLazyman
=
true
;
@FieldMeta
(
"group"
)
private
String
m_group
;
...
...
@@ -37,7 +46,7 @@ public class Payload extends AbstractReportPayload<Action> {
@FieldMeta
(
"domain"
)
private
String
m_domain
;
@FieldMeta
(
"ip"
)
private
String
m_ip
;
...
...
@@ -58,7 +67,7 @@ public class Payload extends AbstractReportPayload<Action> {
@FieldMeta
(
"endTime"
)
private
String
m_endTime
;
@FieldMeta
(
"hostname"
)
private
String
m_hostname
;
...
...
@@ -124,14 +133,15 @@ public class Payload extends AbstractReportPayload<Action> {
return
m_hostname
;
}
}
public
String
getIp
()
{
return
m_ip
;
}
public
ReportPage
getPage
()
{
return
m_page
;
}
public
Date
getStartTime
()
{
if
(
m_startTime
==
null
||
m_startTime
.
length
()
==
0
)
{
...
...
@@ -173,6 +183,18 @@ public class Payload extends AbstractReportPayload<Action> {
return
m_refresh
;
}
public
boolean
isShowLazyman
()
{
return
m_isShowLazyman
;
}
public
boolean
isShowPuppet
()
{
return
m_isShowPuppet
;
}
public
boolean
isShowWorkflow
()
{
return
m_isShowWorkflow
;
}
public
void
setAction
(
String
action
)
{
m_action
=
Action
.
getByName
(
action
,
Action
.
VIEW
);
}
...
...
@@ -226,6 +248,18 @@ public class Payload extends AbstractReportPayload<Action> {
m_refresh
=
refresh
;
}
public
void
setShowLazyman
(
boolean
isShowLazyman
)
{
m_isShowLazyman
=
isShowLazyman
;
}
public
void
setShowPuppet
(
boolean
isShowPuppet
)
{
m_isShowPuppet
=
isShowPuppet
;
}
public
void
setShowWorkflow
(
boolean
isShowWorkflow
)
{
m_isShowWorkflow
=
isShowWorkflow
;
}
public
void
setStartTime
(
String
startTime
)
{
m_startTime
=
startTime
;
}
...
...
cat-home/src/main/java/com/dianping/cat/report/task/metric/AlertConfig.java
浏览文件 @
30de9a29
...
...
@@ -10,29 +10,45 @@ import org.unidal.tuple.Pair;
import
com.dianping.cat.advanced.metric.config.entity.MetricItemConfig
;
import
com.dianping.cat.consumer.company.model.entity.ProductLine
;
import
com.dianping.cat.home.monitorrules.entity.Condition
;
import
com.dianping.cat.home.monitorrules.entity.Config
;
import
com.dianping.cat.home.monitorrules.entity.Subcondition
;
import
com.dianping.cat.core.dal.Project
;
import
com.site.helper.Splitters
;
public
class
AlertConfig
{
public
List
<
String
>
buildMailReceivers
(
Project
project
)
{
private
DecimalFormat
m_df
=
new
DecimalFormat
(
"0.0"
);
private
static
final
Long
ONE_MINUTE_MILLSEC
=
60000L
;
private
static
final
int
JUDGE_DEFAULT_MINUTE
=
3
;
public
List
<
String
>
buildExceptionSMSReceivers
(
ProductLine
productLine
)
{
List
<
String
>
phones
=
new
ArrayList
<
String
>();
phones
.
add
(
"15201789489"
);
// 佳林
return
phones
;
}
public
List
<
String
>
buildMailReceivers
(
ProductLine
productLine
)
{
List
<
String
>
emails
=
new
ArrayList
<
String
>();
String
emailList
=
pro
ject
.
getEmail
();
String
emailList
=
pro
ductLine
.
getEmail
();
emails
.
add
(
"yong.you@dianping.com"
);
emails
.
add
(
"jialin.sun@dianping.com"
);
emails
.
add
(
"argus@dianping.com"
);
emails
.
add
(
"monitor@dianping.com"
);
emails
.
addAll
(
Splitters
.
by
(
","
).
noEmptyItem
().
split
(
emailList
));
return
emails
;
}
public
List
<
String
>
buildMailReceivers
(
Pro
ductLine
productLine
)
{
public
List
<
String
>
buildMailReceivers
(
Pro
ject
project
)
{
List
<
String
>
emails
=
new
ArrayList
<
String
>();
String
emailList
=
pro
ductLine
.
getEmail
();
String
emailList
=
pro
ject
.
getEmail
();
emails
.
add
(
"yong.you@dianping.com"
);
emails
.
add
(
"jialin.sun@dianping.com"
);
emails
.
add
(
"argus@dianping.com"
);
emails
.
add
(
"monitor@dianping.com"
);
emails
.
addAll
(
Splitters
.
by
(
","
).
noEmptyItem
().
split
(
emailList
));
return
emails
;
}
...
...
@@ -49,22 +65,18 @@ public class AlertConfig {
List
<
String
>
phones
=
new
ArrayList
<
String
>();
String
phonesList
=
productLine
.
getPhone
();
phones
.
add
(
"13916536843"
);
//值班
phones
.
add
(
"18616671676"
);
//尤勇
phones
.
add
(
"13858086694"
);
//黄河
phones
.
add
(
"13916536843"
);
//
值班
phones
.
add
(
"18616671676"
);
//
尤勇
phones
.
add
(
"13858086694"
);
//
黄河
phones
.
addAll
(
Splitters
.
by
(
","
).
noEmptyItem
().
split
(
phonesList
));
return
phones
;
}
public
List
<
String
>
buildExceptionSMSReceivers
(
ProductLine
productLine
)
{
List
<
String
>
phones
=
new
ArrayList
<
String
>();
phones
.
add
(
"15201789489"
);
//佳林
return
phones
;
}
public
Pair
<
Boolean
,
String
>
checkData
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
)
{
int
length
=
value
.
length
;
int
listLength
=
value
.
length
;
int
length
=
JUDGE_DEFAULT_MINUTE
>
listLength
?
listLength
:
JUDGE_DEFAULT_MINUTE
;
double
[]
valueTrim
=
getLastMinutes
(
value
,
length
);
double
[]
baseLineTrim
=
getLastMinutes
(
baseline
,
length
);
StringBuilder
baselines
=
new
StringBuilder
();
StringBuilder
values
=
new
StringBuilder
();
double
decreasePercent
=
config
.
getDecreasePercentage
();
...
...
@@ -81,8 +93,78 @@ public class AlertConfig {
}
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
baselines
.
append
(
df
.
format
(
baseline
[
i
])).
append
(
" "
);
values
.
append
(
df
.
format
(
value
[
i
])).
append
(
" "
);
baselines
.
append
(
df
.
format
(
baseLineTrim
[
i
])).
append
(
" "
);
values
.
append
(
df
.
format
(
valueTrim
[
i
])).
append
(
" "
);
valueSum
=
valueSum
+
valueTrim
[
i
];
baselineSum
=
baselineSum
+
baseLineTrim
[
i
];
if
(
baseLineTrim
[
i
]
<=
0
)
{
baseLineTrim
[
i
]
=
100
;
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
if
(
type
==
MetricType
.
COUNT
||
type
==
MetricType
.
SUM
)
{
if
(
valueTrim
[
i
]
/
baseLineTrim
[
i
]
>
(
1
-
decreasePercent
/
100
)
||
(
baseLineTrim
[
i
]
-
valueTrim
[
i
])
<
decreaseValue
)
{
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
}
}
double
percent
=
(
1
-
valueSum
/
baselineSum
)
*
100
;
StringBuilder
sb
=
new
StringBuilder
();
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
sb
.
append
(
"[基线值:"
).
append
(
baselines
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[实际值:"
).
append
(
values
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[下降:"
).
append
(
df
.
format
(
percent
)).
append
(
"%"
).
append
(
"]"
);
sb
.
append
(
"[告警时间:"
).
append
(
sdf
.
format
(
new
Date
())
+
"]"
);
return
new
Pair
<
Boolean
,
String
>(
true
,
sb
.
toString
());
}
public
Pair
<
Boolean
,
String
>
checkData
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
,
List
<
Config
>
configs
)
{
int
valLength
=
value
.
length
;
for
(
Config
con
:
configs
)
{
int
dataLength
=
getMaxMinute
(
con
);
if
(
dataLength
>
valLength
)
{
continue
;
}
double
[]
validVal
=
getLastMinutes
(
value
,
dataLength
);
double
[]
validBase
=
getLastMinutes
(
baseline
,
dataLength
);
Pair
<
Boolean
,
String
>
tmpResult
=
checkDataByConfig
(
config
,
validVal
,
validBase
,
type
,
con
);
if
(
tmpResult
.
getKey
()
==
true
)
{
return
tmpResult
;
}
}
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
private
int
getMaxMinute
(
Config
con
)
{
int
maxMinute
=
0
;
for
(
Condition
condition
:
con
.
getConditions
())
{
int
tmpMinute
=
condition
.
getMinute
();
if
(
tmpMinute
>
maxMinute
)
{
maxMinute
=
tmpMinute
;
}
}
return
maxMinute
;
}
private
Pair
<
Boolean
,
String
>
checkDataByConfig
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
,
Config
con
)
{
int
length
=
value
.
length
;
StringBuilder
baselines
=
new
StringBuilder
();
StringBuilder
values
=
new
StringBuilder
();
double
valueSum
=
0
;
double
baselineSum
=
0
;
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
baselines
.
append
(
m_df
.
format
(
baseline
[
i
])).
append
(
" "
);
values
.
append
(
m_df
.
format
(
value
[
i
])).
append
(
" "
);
valueSum
=
valueSum
+
value
[
i
];
baselineSum
=
baselineSum
+
baseline
[
i
];
...
...
@@ -91,7 +173,7 @@ public class AlertConfig {
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
if
(
type
==
MetricType
.
COUNT
||
type
==
MetricType
.
SUM
)
{
if
(
value
[
i
]
/
baseline
[
i
]
>
(
1
-
decreasePercent
/
100
)
||
(
baseline
[
i
]
-
value
[
i
])
<
decreaseValue
)
{
if
(
!
judgeByRule
(
con
,
value
[
i
],
baseline
[
i
],
i
,
length
)
)
{
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
}
...
...
@@ -102,8 +184,88 @@ public class AlertConfig {
sb
.
append
(
"[基线值:"
).
append
(
baselines
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[实际值:"
).
append
(
values
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[下降:"
).
append
(
df
.
format
(
percent
)).
append
(
"%"
).
append
(
"]"
);
sb
.
append
(
"[下降:"
).
append
(
m_
df
.
format
(
percent
)).
append
(
"%"
).
append
(
"]"
);
sb
.
append
(
"[告警时间:"
).
append
(
sdf
.
format
(
new
Date
())
+
"]"
);
return
new
Pair
<
Boolean
,
String
>(
true
,
sb
.
toString
());
}
private
double
[]
getLastMinutes
(
double
[]
doubleList
,
int
remainCount
)
{
double
[]
result
=
new
double
[
remainCount
];
int
startIndex
=
doubleList
.
length
-
remainCount
;
for
(
int
i
=
0
;
i
<
remainCount
;
i
++)
{
result
[
i
]
=
doubleList
[
startIndex
+
i
];
}
return
result
;
}
private
Long
getMillsByString
(
String
time
)
throws
Exception
{
String
[]
times
=
time
.
split
(
":"
);
int
hour
=
Integer
.
parseInt
(
times
[
0
]);
int
minute
=
Integer
.
parseInt
(
times
[
1
]);
long
result
=
hour
*
60
*
60
*
1000
+
minute
*
60
*
1000
;
return
result
;
}
private
boolean
judgeByRule
(
Config
ruleConfig
,
double
value
,
double
baseline
,
int
index
,
int
length
)
{
boolean
isRuleTriggered
=
false
;
long
ruleStartTime
;
long
ruleEndTime
;
long
nowTime
=
(
System
.
currentTimeMillis
()
+
8
*
60
*
60
*
1000
)
%
(
24
*
60
*
60
*
1000
);
try
{
ruleStartTime
=
getMillsByString
(
ruleConfig
.
getStarttime
());
ruleEndTime
=
getMillsByString
(
ruleConfig
.
getEndtime
())
+
ONE_MINUTE_MILLSEC
;
}
catch
(
Exception
ex
)
{
ruleStartTime
=
0L
;
ruleEndTime
=
86400000L
;
}
if
(
nowTime
<
ruleStartTime
||
nowTime
>
ruleEndTime
)
{
return
false
;
}
for
(
Condition
condition
:
ruleConfig
.
getConditions
())
{
if
(
isRuleTriggered
)
{
break
;
}
int
minute
=
condition
.
getMinute
();
if
(
minute
==
0
)
{
minute
=
JUDGE_DEFAULT_MINUTE
;
}
if
(
index
<
length
-
minute
)
{
continue
;
}
boolean
isSubRuleTriggered
=
true
;
for
(
Subcondition
subCondition
:
condition
.
getSubconditions
())
{
if
(!
isSubRuleTriggered
)
{
break
;
}
String
ruleType
=
subCondition
.
getType
();
int
ruleValue
=
Integer
.
parseInt
(
subCondition
.
getText
());
RuleType
rule
=
RuleType
.
getByTypeId
(
ruleType
);
if
(
rule
==
null
)
{
continue
;
}
else
{
isSubRuleTriggered
=
rule
.
executeRule
(
value
,
baseline
,
ruleValue
);
}
}
if
(
isSubRuleTriggered
)
{
isRuleTriggered
=
true
;
}
}
return
isRuleTriggered
;
}
}
cat-home/src/main/java/com/dianping/cat/report/task/metric/MetricAlert.java
浏览文件 @
30de9a29
...
...
@@ -23,11 +23,15 @@ import com.dianping.cat.consumer.metric.ProductLineConfigManager;
import
com.dianping.cat.consumer.metric.model.entity.MetricReport
;
import
com.dianping.cat.consumer.metric.model.entity.Segment
;
import
com.dianping.cat.helper.TimeUtil
;
import
com.dianping.cat.home.monitorrules.entity.Condition
;
import
com.dianping.cat.home.monitorrules.entity.Config
;
import
com.dianping.cat.home.monitorrules.entity.Subcondition
;
import
com.dianping.cat.message.Event
;
import
com.dianping.cat.message.Transaction
;
import
com.dianping.cat.report.baseline.BaselineService
;
import
com.dianping.cat.service.ModelPeriod
;
import
com.dianping.cat.service.ModelRequest
;
import
com.dianping.cat.system.config.MetricRuleConfigManager
;
import
com.dianping.cat.system.tool.MailSMS
;
public
class
MetricAlert
implements
Task
,
LogEnabled
{
...
...
@@ -38,6 +42,9 @@ public class MetricAlert implements Task, LogEnabled {
@Inject
private
ProductLineConfigManager
m_productLineConfigManager
;
@Inject
private
MetricRuleConfigManager
m_metricRuleConfigManager
;
@Inject
private
BaselineService
m_baselineService
;
...
...
@@ -65,34 +72,125 @@ public class MetricAlert implements Task, LogEnabled {
private
Logger
m_logger
;
private
void
addDescMetricIfNotExist
(
MetricItemConfig
config
,
List
<
Config
>
configs
)
{
double
descPer
=
config
.
getDecreasePercentage
();
double
descVal
=
config
.
getDecreaseValue
();
boolean
isDescPerExist
=
false
;
boolean
isDescValExist
=
false
;
String
dayBeginTime
=
"00:00"
;
String
dayEndTime
=
"24:00"
;
if
(
descPer
==
0
)
{
descPer
=
50
;
}
if
(
descVal
==
0
)
{
descVal
=
100
;
}
for
(
Config
con
:
configs
)
{
String
startTime
=
con
.
getStarttime
();
String
endTime
=
con
.
getEndtime
();
if
(
startTime
==
null
||
!
startTime
.
equals
(
dayBeginTime
)
||
endTime
==
null
||
!
endTime
.
equals
(
dayEndTime
))
{
continue
;
}
for
(
Condition
c
:
con
.
getConditions
())
{
List
<
Subcondition
>
subCons
=
c
.
getSubconditions
();
if
(
subCons
.
size
()
!=
2
)
{
continue
;
}
for
(
Subcondition
sub
:
subCons
)
{
RuleType
type
=
RuleType
.
getByTypeId
(
sub
.
getType
());
switch
(
type
)
{
case
DecreasePercentage:
isDescPerExist
=
true
;
break
;
case
DecreaseValue:
isDescValExist
=
true
;
break
;
default
:
break
;
}
}
if
(
isDescPerExist
&&
isDescValExist
)
{
break
;
}
else
{
isDescPerExist
=
false
;
isDescValExist
=
false
;
}
}
}
if
(
isDescPerExist
&&
isDescValExist
)
{
return
;
}
else
{
addNewCondition
(
configs
,
"DescPer"
,
descPer
,
"DescVal"
,
descVal
,
dayBeginTime
,
dayEndTime
);
}
}
private
void
addNewCondition
(
List
<
Config
>
configs
,
String
type
,
double
val
,
String
type2
,
double
val2
,
String
dayBeginTime
,
String
dayEndTime
)
{
configs
.
add
(
new
Config
()
.
setStarttime
(
dayBeginTime
)
.
setEndtime
(
dayEndTime
)
.
addCondition
(
new
Condition
().
setTitle
(
"default rule"
)
.
addSubcondition
(
new
Subcondition
().
setType
(
type
).
setText
(
String
.
valueOf
(
val
)))
.
addSubcondition
(
new
Subcondition
().
setType
(
type2
).
setText
(
String
.
valueOf
(
val2
)))));
}
private
Pair
<
Boolean
,
String
>
checkDataByJudge
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
,
List
<
Config
>
configs
)
{
Pair
<
Boolean
,
String
>
originResult
=
m_alertConfig
.
checkData
(
config
,
value
,
baseline
,
type
);
addDescMetricIfNotExist
(
config
,
configs
);
Pair
<
Boolean
,
String
>
ruleJudgeResult
=
m_alertConfig
.
checkData
(
config
,
value
,
baseline
,
type
,
configs
);
if
(
originResult
.
getKey
()
!=
ruleJudgeResult
.
getKey
())
{
Cat
.
logError
(
"rule execute error!"
,
new
Exception
());
}
return
originResult
;
}
private
Pair
<
Boolean
,
String
>
computeAlertInfo
(
int
minute
,
String
product
,
MetricItemConfig
config
,
MetricType
type
)
{
double
[]
value
=
null
;
double
[]
baseline
=
null
;
String
metricKey
=
m_metricConfigManager
.
buildMetricKey
(
config
.
getDomain
(),
config
.
getType
(),
config
.
getMetricKey
());
String
domain
=
config
.
getDomain
();
String
key
=
config
.
getMetricKey
();
String
metricKey
=
m_metricConfigManager
.
buildMetricKey
(
domain
,
config
.
getType
(),
key
);
List
<
Config
>
configs
=
m_metricRuleConfigManager
.
getConfigs
(
product
,
domain
,
key
,
metricKey
);
int
maxMinute
=
getMaxMinute
(
configs
);
if
(
minute
>=
DATA_CHECK_MINUTE
-
1
)
{
if
(
minute
>=
maxMinute
-
1
)
{
MetricReport
report
=
fetchMetricReport
(
product
,
ModelPeriod
.
CURRENT
);
if
(
report
!=
null
)
{
int
start
=
minute
+
1
-
DATA_CHECK_MINUTE
;
int
start
=
minute
+
1
-
maxMinute
;
int
end
=
minute
;
value
=
queryRealData
(
start
,
end
,
metricKey
,
report
,
type
);
baseline
=
queryBaseLine
(
start
,
end
,
metricKey
,
new
Date
(
ModelPeriod
.
CURRENT
.
getStartTime
()),
type
);
return
m_alertConfig
.
checkData
(
config
,
value
,
baseline
,
type
);
return
checkDataByJudge
(
config
,
value
,
baseline
,
type
,
configs
);
}
}
else
if
(
minute
<
0
)
{
MetricReport
lastReport
=
fetchMetricReport
(
product
,
ModelPeriod
.
LAST
);
if
(
lastReport
!=
null
)
{
int
start
=
60
+
minute
+
1
-
(
DATA_CHECK_MINUTE
);
int
start
=
60
+
minute
+
1
-
(
maxMinute
);
int
end
=
60
+
minute
;
value
=
queryRealData
(
start
,
end
,
metricKey
,
lastReport
,
type
);
baseline
=
queryBaseLine
(
start
,
end
,
metricKey
,
new
Date
(
ModelPeriod
.
LAST
.
getStartTime
()),
type
);
return
m_alertConfig
.
checkData
(
config
,
value
,
baseline
,
type
);
return
checkDataByJudge
(
config
,
value
,
baseline
,
type
,
configs
);
}
}
else
{
MetricReport
currentReport
=
fetchMetricReport
(
product
,
ModelPeriod
.
CURRENT
);
...
...
@@ -104,7 +202,7 @@ public class MetricAlert implements Task, LogEnabled {
double
[]
currentBaseline
=
queryBaseLine
(
currentStart
,
currentEnd
,
metricKey
,
new
Date
(
ModelPeriod
.
CURRENT
.
getStartTime
()),
type
);
int
lastStart
=
60
+
1
-
(
DATA_CHECK_MINUTE
-
minute
);
int
lastStart
=
60
+
1
-
(
maxMinute
-
minute
);
int
lastEnd
=
59
;
double
[]
lastValue
=
queryRealData
(
lastStart
,
lastEnd
,
metricKey
,
lastReport
,
type
);
double
[]
lastBaseline
=
queryBaseLine
(
lastStart
,
lastEnd
,
metricKey
,
...
...
@@ -112,7 +210,7 @@ public class MetricAlert implements Task, LogEnabled {
value
=
mergerArray
(
lastValue
,
currentValue
);
baseline
=
mergerArray
(
lastBaseline
,
currentBaseline
);
return
m_alertConfig
.
checkData
(
config
,
value
,
baseline
,
type
);
return
checkDataByJudge
(
config
,
value
,
baseline
,
type
,
configs
);
}
}
return
null
;
...
...
@@ -159,6 +257,20 @@ public class MetricAlert implements Task, LogEnabled {
}
}
private
int
getMaxMinute
(
List
<
Config
>
configs
)
{
int
maxMinute
=
DATA_CHECK_MINUTE
;
for
(
Config
config
:
configs
)
{
for
(
Condition
con
:
config
.
getConditions
())
{
int
tmpMinute
=
con
.
getMinute
();
if
(
tmpMinute
>
maxMinute
)
{
maxMinute
=
tmpMinute
;
}
}
}
return
maxMinute
;
}
@Override
public
String
getName
()
{
return
"metric-alert"
;
...
...
@@ -180,6 +292,31 @@ public class MetricAlert implements Task, LogEnabled {
return
result
;
}
private
void
processMetricItemConfig
(
MetricItemConfig
config
,
int
minute
,
String
product
,
ProductLine
productLine
)
{
if
((!
config
.
getAlarm
()
&&
!
config
.
isShowAvgDashboard
()
&&
!
config
.
isShowSumDashboard
()
&&
!
config
.
isShowCountDashboard
()))
{
return
;
}
Pair
<
Boolean
,
String
>
alert
=
null
;
if
(
config
.
isShowAvg
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
AVG
);
}
if
(
config
.
isShowCount
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
COUNT
);
}
if
(
config
.
isShowSum
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
SUM
);
}
if
(
alert
!=
null
&&
alert
.
getKey
())
{
config
.
setId
(
m_metricConfigManager
.
buildMetricKey
(
config
.
getDomain
(),
config
.
getType
(),
config
.
getMetricKey
()));
m_alertInfo
.
addMetric
(
config
,
new
Date
().
getTime
());
sendAlertInfo
(
productLine
,
config
,
alert
.
getValue
());
}
}
private
void
processProductLine
(
ProductLine
productLine
)
{
List
<
String
>
domains
=
m_productLineConfigManager
.
queryDomainsByProductLine
(
productLine
.
getId
());
List
<
MetricItemConfig
>
configs
=
m_metricConfigManager
.
queryMetricItemConfigs
(
new
HashSet
<
String
>(
domains
));
...
...
@@ -188,28 +325,7 @@ public class MetricAlert implements Task, LogEnabled {
String
product
=
productLine
.
getId
();
for
(
MetricItemConfig
config
:
configs
)
{
if
((!
config
.
getAlarm
()
&&
!
config
.
isShowAvgDashboard
()
&&
!
config
.
isShowSumDashboard
()
&&
!
config
.
isShowCountDashboard
()))
{
continue
;
}
Pair
<
Boolean
,
String
>
alert
=
null
;
if
(
config
.
isShowAvg
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
AVG
);
}
if
(
config
.
isShowCount
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
COUNT
);
}
if
(
config
.
isShowSum
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
SUM
);
}
if
(
alert
!=
null
&&
alert
.
getKey
())
{
config
.
setId
(
m_metricConfigManager
.
buildMetricKey
(
config
.
getDomain
(),
config
.
getType
(),
config
.
getMetricKey
()));
m_alertInfo
.
addMetric
(
config
,
new
Date
().
getTime
());
sendAlertInfo
(
productLine
,
config
,
alert
.
getValue
());
}
processMetricItemConfig
(
config
,
minute
,
product
,
productLine
);
}
}
...
...
@@ -275,6 +391,7 @@ public class MetricAlert implements Task, LogEnabled {
Cat
.
logError
(
e
);
}
}
t
.
setStatus
(
Transaction
.
SUCCESS
);
}
catch
(
Exception
e
)
{
t
.
setStatus
(
e
);
...
...
cat-home/src/main/java/com/dianping/cat/report/task/metric/RuleType.java
0 → 100644
浏览文件 @
30de9a29
package
com.dianping.cat.report.task.metric
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
public
enum
RuleType
{
DecreasePercentage
{
@Override
public
boolean
executeRule
(
double
value
,
double
baseline
,
double
ruleValue
)
{
return
value
/
baseline
<=
(
1
-
ruleValue
/
100
);
}
@Override
public
String
getId
()
{
return
"DescPer"
;
}
},
DecreaseValue
{
@Override
public
boolean
executeRule
(
double
value
,
double
baseline
,
double
ruleValue
)
{
return
baseline
-
value
>=
ruleValue
;
}
@Override
public
String
getId
()
{
return
"DescVal"
;
}
},
IncreasePercentage
{
@Override
public
boolean
executeRule
(
double
value
,
double
baseline
,
double
ruleValue
)
{
return
value
/
baseline
>=
(
1
+
ruleValue
/
100
);
}
@Override
public
String
getId
()
{
return
"AscPer"
;
}
},
IncreaseValue
{
@Override
public
boolean
executeRule
(
double
value
,
double
baseline
,
double
ruleValue
)
{
return
value
-
baseline
>=
ruleValue
;
}
@Override
public
String
getId
()
{
return
"AscVal"
;
}
},
absoluteMaxValue
{
@Override
public
boolean
executeRule
(
double
value
,
double
baseline
,
double
ruleValue
)
{
return
value
>=
ruleValue
;
}
@Override
public
String
getId
()
{
return
"MaxVal"
;
}
},
absoluteMinValue
{
@Override
public
boolean
executeRule
(
double
value
,
double
baseline
,
double
ruleValue
)
{
return
value
<=
ruleValue
;
}
@Override
public
String
getId
()
{
return
"MinVal"
;
}
};
static
Map
<
String
,
RuleType
>
s_map
=
new
LinkedHashMap
<
String
,
RuleType
>();
static
{
for
(
RuleType
type
:
RuleType
.
values
()){
s_map
.
put
(
type
.
getId
(),
type
);
}
}
public
abstract
boolean
executeRule
(
double
value
,
double
baseline
,
double
ruleValue
);
public
abstract
String
getId
();
public
static
RuleType
getByTypeId
(
String
typeId
){
return
s_map
.
get
(
typeId
);
}
}
cat-home/src/main/java/com/dianping/cat/report/task/metric/SwitchAlert.java
0 → 100644
浏览文件 @
30de9a29
package
com.dianping.cat.report.task.metric
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
org.codehaus.plexus.logging.LogEnabled
;
import
org.codehaus.plexus.logging.Logger
;
import
org.unidal.helper.Threads.Task
;
import
org.unidal.lookup.annotation.Inject
;
import
org.unidal.tuple.Pair
;
import
com.dianping.cat.Cat
;
import
com.dianping.cat.advanced.metric.config.entity.MetricItemConfig
;
import
com.dianping.cat.consumer.company.model.entity.ProductLine
;
import
com.dianping.cat.consumer.metric.MetricAnalyzer
;
import
com.dianping.cat.consumer.metric.MetricConfigManager
;
import
com.dianping.cat.consumer.metric.ProductLineConfigManager
;
import
com.dianping.cat.consumer.metric.model.entity.MetricReport
;
import
com.dianping.cat.consumer.metric.model.entity.Segment
;
import
com.dianping.cat.helper.TimeUtil
;
import
com.dianping.cat.home.monitorrules.entity.Condition
;
import
com.dianping.cat.home.monitorrules.entity.Config
;
import
com.dianping.cat.home.monitorrules.entity.Subcondition
;
import
com.dianping.cat.message.Event
;
import
com.dianping.cat.message.Transaction
;
import
com.dianping.cat.report.baseline.BaselineService
;
import
com.dianping.cat.service.ModelPeriod
;
import
com.dianping.cat.service.ModelRequest
;
import
com.dianping.cat.system.config.MetricRuleConfigManager
;
import
com.dianping.cat.system.tool.MailSMS
;
public
class
SwitchAlert
implements
Task
,
LogEnabled
{
@Inject
private
MetricConfigManager
m_metricConfigManager
;
@Inject
private
ProductLineConfigManager
m_productLineConfigManager
;
@Inject
private
MetricRuleConfigManager
m_metricRuleConfigManager
;
@Inject
private
BaselineService
m_baselineService
;
@Inject
private
MailSMS
m_mailSms
;
@Inject
private
RemoteMetricReportService
m_service
;
@Inject
private
SwitchAlertConfig
m_alertConfig
;
@Inject
private
AlertInfo
m_alertInfo
;
private
static
final
long
DURATION
=
TimeUtil
.
ONE_MINUTE
;
private
static
final
int
DATA_CHECK_MINUTE
=
3
;
private
static
final
int
DATA_AREADY_MINUTE
=
1
;
private
Map
<
String
,
MetricReport
>
m_currentReports
=
new
HashMap
<
String
,
MetricReport
>();
private
Map
<
String
,
MetricReport
>
m_lastReports
=
new
HashMap
<
String
,
MetricReport
>();
private
Logger
m_logger
;
private
void
addDescMetricIfNotExist
(
MetricItemConfig
config
,
List
<
Config
>
configs
)
{
double
descPer
=
config
.
getDecreasePercentage
();
double
descVal
=
config
.
getDecreaseValue
();
boolean
isDescPerExist
=
false
;
boolean
isDescValExist
=
false
;
String
dayBeginTime
=
"00:00"
;
String
dayEndTime
=
"24:00"
;
if
(
descPer
==
0
)
{
descPer
=
50
;
}
if
(
descVal
==
0
)
{
descVal
=
100
;
}
for
(
Config
con
:
configs
)
{
String
startTime
=
con
.
getStarttime
();
String
endTime
=
con
.
getEndtime
();
if
(
startTime
==
null
||
!
startTime
.
equals
(
dayBeginTime
)
||
endTime
==
null
||
!
endTime
.
equals
(
dayEndTime
))
{
continue
;
}
for
(
Condition
c
:
con
.
getConditions
())
{
List
<
Subcondition
>
subCons
=
c
.
getSubconditions
();
if
(
subCons
.
size
()
!=
2
)
{
continue
;
}
for
(
Subcondition
sub
:
subCons
)
{
RuleType
type
=
RuleType
.
getByTypeId
(
sub
.
getType
());
switch
(
type
)
{
case
DecreasePercentage:
isDescPerExist
=
true
;
break
;
case
DecreaseValue:
isDescValExist
=
true
;
break
;
default
:
break
;
}
}
if
(
isDescPerExist
&&
isDescValExist
)
{
break
;
}
else
{
isDescPerExist
=
false
;
isDescValExist
=
false
;
}
}
}
if
(
isDescPerExist
&&
isDescValExist
)
{
return
;
}
else
{
addNewCondition
(
configs
,
"DescPer"
,
descPer
,
"DescVal"
,
descVal
,
dayBeginTime
,
dayEndTime
);
}
}
private
void
addNewCondition
(
List
<
Config
>
configs
,
String
type
,
double
val
,
String
type2
,
double
val2
,
String
dayBeginTime
,
String
dayEndTime
)
{
configs
.
add
(
new
Config
()
.
setStarttime
(
dayBeginTime
)
.
setEndtime
(
dayEndTime
)
.
addCondition
(
new
Condition
().
setTitle
(
"default rule"
)
.
addSubcondition
(
new
Subcondition
().
setType
(
type
).
setText
(
String
.
valueOf
(
val
)))
.
addSubcondition
(
new
Subcondition
().
setType
(
type2
).
setText
(
String
.
valueOf
(
val2
)))));
}
private
Pair
<
Boolean
,
String
>
checkDataByJudge
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
,
List
<
Config
>
configs
)
{
Pair
<
Boolean
,
String
>
originResult
=
m_alertConfig
.
checkData
(
config
,
value
,
baseline
,
type
);
addDescMetricIfNotExist
(
config
,
configs
);
Pair
<
Boolean
,
String
>
ruleJudgeResult
=
m_alertConfig
.
checkData
(
config
,
value
,
baseline
,
type
,
configs
);
if
(
originResult
.
getKey
()
!=
ruleJudgeResult
.
getKey
())
{
Cat
.
logError
(
"rule execute error!"
,
new
Exception
());
}
return
originResult
;
}
private
Pair
<
Boolean
,
String
>
computeAlertInfo
(
int
minute
,
String
product
,
MetricItemConfig
config
,
MetricType
type
)
{
double
[]
value
=
null
;
double
[]
baseline
=
null
;
String
domain
=
config
.
getDomain
();
String
key
=
config
.
getMetricKey
();
String
metricKey
=
m_metricConfigManager
.
buildMetricKey
(
domain
,
config
.
getType
(),
key
);
List
<
Config
>
configs
=
m_metricRuleConfigManager
.
getConfigs
(
product
,
domain
,
key
,
metricKey
);
int
maxMinute
=
getMaxMinute
(
configs
);
if
(
minute
>=
maxMinute
-
1
)
{
MetricReport
report
=
fetchMetricReport
(
product
,
ModelPeriod
.
CURRENT
);
if
(
report
!=
null
)
{
int
start
=
minute
+
1
-
maxMinute
;
int
end
=
minute
;
value
=
queryRealData
(
start
,
end
,
metricKey
,
report
,
type
);
baseline
=
queryBaseLine
(
start
,
end
,
metricKey
,
new
Date
(
ModelPeriod
.
CURRENT
.
getStartTime
()),
type
);
return
checkDataByJudge
(
config
,
value
,
baseline
,
type
,
configs
);
}
}
else
if
(
minute
<
0
)
{
MetricReport
lastReport
=
fetchMetricReport
(
product
,
ModelPeriod
.
LAST
);
if
(
lastReport
!=
null
)
{
int
start
=
60
+
minute
+
1
-
(
maxMinute
);
int
end
=
60
+
minute
;
value
=
queryRealData
(
start
,
end
,
metricKey
,
lastReport
,
type
);
baseline
=
queryBaseLine
(
start
,
end
,
metricKey
,
new
Date
(
ModelPeriod
.
LAST
.
getStartTime
()),
type
);
return
checkDataByJudge
(
config
,
value
,
baseline
,
type
,
configs
);
}
}
else
{
MetricReport
currentReport
=
fetchMetricReport
(
product
,
ModelPeriod
.
CURRENT
);
MetricReport
lastReport
=
fetchMetricReport
(
product
,
ModelPeriod
.
LAST
);
if
(
currentReport
!=
null
&&
lastReport
!=
null
)
{
int
currentStart
=
0
,
currentEnd
=
minute
;
double
[]
currentValue
=
queryRealData
(
currentStart
,
currentEnd
,
metricKey
,
currentReport
,
type
);
double
[]
currentBaseline
=
queryBaseLine
(
currentStart
,
currentEnd
,
metricKey
,
new
Date
(
ModelPeriod
.
CURRENT
.
getStartTime
()),
type
);
int
lastStart
=
60
+
1
-
(
maxMinute
-
minute
);
int
lastEnd
=
59
;
double
[]
lastValue
=
queryRealData
(
lastStart
,
lastEnd
,
metricKey
,
lastReport
,
type
);
double
[]
lastBaseline
=
queryBaseLine
(
lastStart
,
lastEnd
,
metricKey
,
new
Date
(
ModelPeriod
.
LAST
.
getStartTime
()),
type
);
value
=
mergerArray
(
lastValue
,
currentValue
);
baseline
=
mergerArray
(
lastBaseline
,
currentBaseline
);
return
checkDataByJudge
(
config
,
value
,
baseline
,
type
,
configs
);
}
}
return
null
;
}
@Override
public
void
enableLogging
(
Logger
logger
)
{
m_logger
=
logger
;
}
private
MetricReport
fetchMetricReport
(
String
product
,
ModelPeriod
period
)
{
if
(
period
==
ModelPeriod
.
CURRENT
)
{
MetricReport
report
=
m_currentReports
.
get
(
product
);
if
(
report
!=
null
)
{
return
report
;
}
else
{
ModelRequest
request
=
new
ModelRequest
(
product
,
ModelPeriod
.
CURRENT
.
getStartTime
()).
setProperty
(
"requireAll"
,
"ture"
);
report
=
m_service
.
invoke
(
request
);
if
(
report
!=
null
)
{
m_currentReports
.
put
(
product
,
report
);
}
return
report
;
}
}
else
if
(
period
==
ModelPeriod
.
LAST
)
{
MetricReport
report
=
m_lastReports
.
get
(
product
);
if
(
report
!=
null
)
{
return
report
;
}
else
{
ModelRequest
request
=
new
ModelRequest
(
product
,
ModelPeriod
.
LAST
.
getStartTime
()).
setProperty
(
"requireAll"
,
"ture"
);
report
=
m_service
.
invoke
(
request
);
if
(
report
!=
null
)
{
m_lastReports
.
put
(
product
,
report
);
}
return
report
;
}
}
else
{
throw
new
RuntimeException
(
"internal error, this can't be reached."
);
}
}
private
int
getMaxMinute
(
List
<
Config
>
configs
)
{
int
maxMinute
=
DATA_CHECK_MINUTE
;
for
(
Config
config
:
configs
)
{
for
(
Condition
con
:
config
.
getConditions
())
{
int
tmpMinute
=
con
.
getMinute
();
if
(
tmpMinute
>
maxMinute
)
{
maxMinute
=
tmpMinute
;
}
}
}
return
maxMinute
;
}
@Override
public
String
getName
()
{
return
"metric-alert"
;
}
private
double
[]
mergerArray
(
double
[]
from
,
double
[]
to
)
{
int
fromLength
=
from
.
length
;
int
toLength
=
to
.
length
;
double
[]
result
=
new
double
[
fromLength
+
toLength
];
int
index
=
0
;
for
(
int
i
=
0
;
i
<
fromLength
;
i
++)
{
result
[
i
]
=
from
[
i
];
index
++;
}
for
(
int
i
=
0
;
i
<
toLength
;
i
++)
{
result
[
i
+
index
]
=
to
[
i
];
}
return
result
;
}
private
void
processMetricItemConfig
(
MetricItemConfig
config
,
int
minute
,
String
product
,
ProductLine
productLine
)
{
if
((!
config
.
getAlarm
()
&&
!
config
.
isShowAvgDashboard
()
&&
!
config
.
isShowSumDashboard
()
&&
!
config
.
isShowCountDashboard
()))
{
return
;
}
Pair
<
Boolean
,
String
>
alert
=
null
;
if
(
config
.
isShowAvg
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
AVG
);
}
if
(
config
.
isShowCount
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
COUNT
);
}
if
(
config
.
isShowSum
())
{
alert
=
computeAlertInfo
(
minute
,
product
,
config
,
MetricType
.
SUM
);
}
if
(
alert
!=
null
&&
alert
.
getKey
())
{
config
.
setId
(
m_metricConfigManager
.
buildMetricKey
(
config
.
getDomain
(),
config
.
getType
(),
config
.
getMetricKey
()));
m_alertInfo
.
addMetric
(
config
,
new
Date
().
getTime
());
sendAlertInfo
(
productLine
,
config
,
alert
.
getValue
());
}
}
private
void
processProductLine
(
ProductLine
productLine
)
{
List
<
String
>
domains
=
m_productLineConfigManager
.
queryDomainsByProductLine
(
productLine
.
getId
());
List
<
MetricItemConfig
>
configs
=
m_metricConfigManager
.
queryMetricItemConfigs
(
new
HashSet
<
String
>(
domains
));
long
current
=
(
System
.
currentTimeMillis
())
/
1000
/
60
;
int
minute
=
(
int
)
(
current
%
(
60
))
-
DATA_AREADY_MINUTE
;
String
product
=
productLine
.
getId
();
for
(
MetricItemConfig
config
:
configs
)
{
processMetricItemConfig
(
config
,
minute
,
product
,
productLine
);
}
}
private
double
[]
queryBaseLine
(
int
start
,
int
end
,
String
baseLineKey
,
Date
date
,
MetricType
type
)
{
double
[]
baseline
=
m_baselineService
.
queryHourlyBaseline
(
MetricAnalyzer
.
ID
,
baseLineKey
+
":"
+
type
,
date
);
int
length
=
end
-
start
+
1
;
double
[]
result
=
new
double
[
length
];
System
.
arraycopy
(
baseline
,
start
,
result
,
0
,
length
);
return
result
;
}
private
double
[]
queryRealData
(
int
start
,
int
end
,
String
metricKey
,
MetricReport
report
,
MetricType
type
)
{
double
[]
all
=
new
double
[
60
];
Map
<
Integer
,
Segment
>
map
=
report
.
findOrCreateMetricItem
(
metricKey
).
getSegments
();
for
(
Entry
<
Integer
,
Segment
>
entry
:
map
.
entrySet
())
{
Integer
minute
=
entry
.
getKey
();
Segment
seg
=
entry
.
getValue
();
if
(
type
==
MetricType
.
AVG
)
{
all
[
minute
]
=
seg
.
getAvg
();
}
else
if
(
type
==
MetricType
.
COUNT
)
{
all
[
minute
]
=
(
double
)
seg
.
getCount
();
}
else
if
(
type
==
MetricType
.
SUM
)
{
all
[
minute
]
=
seg
.
getSum
();
}
}
int
length
=
end
-
start
+
1
;
double
[]
result
=
new
double
[
length
];
System
.
arraycopy
(
all
,
start
,
result
,
0
,
length
);
return
result
;
}
@Override
public
void
run
()
{
try
{
Thread
.
sleep
(
5000
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
boolean
active
=
true
;
while
(
active
)
{
int
minute
=
Calendar
.
getInstance
().
get
(
Calendar
.
MINUTE
);
String
minuteStr
=
String
.
valueOf
(
minute
);
if
(
minute
<
10
)
{
minuteStr
=
'0'
+
minuteStr
;
}
Transaction
t
=
Cat
.
newTransaction
(
"MetricAlert"
,
"M"
+
minuteStr
);
long
current
=
System
.
currentTimeMillis
();
m_currentReports
.
clear
();
m_lastReports
.
clear
();
try
{
Map
<
String
,
ProductLine
>
productLines
=
m_productLineConfigManager
.
getCompany
().
getProductLines
();
for
(
ProductLine
productLine
:
productLines
.
values
())
{
try
{
processProductLine
(
productLine
);
}
catch
(
Exception
e
)
{
Cat
.
logError
(
e
);
}
}
t
.
setStatus
(
Transaction
.
SUCCESS
);
}
catch
(
Exception
e
)
{
t
.
setStatus
(
e
);
}
finally
{
t
.
complete
();
}
long
duration
=
System
.
currentTimeMillis
()
-
current
;
try
{
if
(
duration
<
DURATION
)
{
Thread
.
sleep
(
DURATION
-
duration
);
}
}
catch
(
InterruptedException
e
)
{
active
=
false
;
}
}
}
private
void
sendAlertInfo
(
ProductLine
productLine
,
MetricItemConfig
config
,
String
content
)
{
List
<
String
>
emails
=
m_alertConfig
.
buildMailReceivers
(
productLine
);
List
<
String
>
phones
=
m_alertConfig
.
buildSMSReceivers
(
productLine
);
String
title
=
m_alertConfig
.
buildMailTitle
(
productLine
,
config
);
m_logger
.
info
(
title
+
" "
+
content
+
" "
+
emails
);
m_mailSms
.
sendEmail
(
title
,
content
,
emails
);
m_mailSms
.
sendSms
(
title
+
" "
+
content
,
content
,
phones
);
Cat
.
logEvent
(
"MetricAlert"
,
productLine
.
getId
(),
Event
.
SUCCESS
,
title
+
" "
+
content
);
}
@Override
public
void
shutdown
()
{
}
}
\ No newline at end of file
cat-home/src/main/java/com/dianping/cat/report/task/metric/SwitchAlertConfig.java
0 → 100644
浏览文件 @
30de9a29
package
com.dianping.cat.report.task.metric
;
import
java.text.DecimalFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
org.unidal.tuple.Pair
;
import
com.dianping.cat.advanced.metric.config.entity.MetricItemConfig
;
import
com.dianping.cat.consumer.company.model.entity.ProductLine
;
import
com.dianping.cat.core.dal.Project
;
import
com.dianping.cat.home.monitorrules.entity.Condition
;
import
com.dianping.cat.home.monitorrules.entity.Config
;
import
com.dianping.cat.home.monitorrules.entity.Subcondition
;
public
class
SwitchAlertConfig
{
private
DecimalFormat
m_df
=
new
DecimalFormat
(
"0.0"
);
private
static
final
Long
ONE_MINUTE_MILLSEC
=
60000L
;
private
static
final
int
JUDGE_DEFAULT_MINUTE
=
3
;
public
List
<
String
>
buildExceptionSMSReceivers
(
ProductLine
productLine
)
{
List
<
String
>
phones
=
new
ArrayList
<
String
>();
phones
.
add
(
"18662513308"
);
return
phones
;
}
public
List
<
String
>
buildMailReceivers
(
ProductLine
productLine
)
{
List
<
String
>
emails
=
new
ArrayList
<
String
>();
//String emailList = productLine.getEmail();
emails
.
add
(
"leon.li@dianping.com"
);
//emails.addAll(Splitters.by(",").noEmptyItem().split(emailList));
return
emails
;
}
public
List
<
String
>
buildMailReceivers
(
Project
project
)
{
List
<
String
>
emails
=
new
ArrayList
<
String
>();
//String emailList = project.getEmail();
emails
.
add
(
"leon.li@dianping.com"
);
//emails.addAll(Splitters.by(",").noEmptyItem().split(emailList));
return
emails
;
}
public
String
buildMailTitle
(
ProductLine
productLine
,
MetricItemConfig
config
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
"[业务告警] [产品线 "
).
append
(
productLine
.
getTitle
()).
append
(
"]"
);
sb
.
append
(
"[业务指标 "
).
append
(
config
.
getTitle
()).
append
(
"]"
);
return
sb
.
toString
();
}
public
List
<
String
>
buildSMSReceivers
(
ProductLine
productLine
)
{
List
<
String
>
phones
=
new
ArrayList
<
String
>();
//String phonesList = productLine.getPhone();
phones
.
add
(
"18662513308"
);
//phones.addAll(Splitters.by(",").noEmptyItem().split(phonesList));
return
phones
;
}
public
Pair
<
Boolean
,
String
>
checkData
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
)
{
int
listLength
=
value
.
length
;
int
length
=
JUDGE_DEFAULT_MINUTE
>
listLength
?
listLength
:
JUDGE_DEFAULT_MINUTE
;
double
[]
valueTrim
=
getLastMinutes
(
value
,
length
);
double
[]
baseLineTrim
=
getLastMinutes
(
baseline
,
length
);
StringBuilder
baselines
=
new
StringBuilder
();
StringBuilder
values
=
new
StringBuilder
();
double
decreasePercent
=
config
.
getDecreasePercentage
();
double
decreaseValue
=
config
.
getDecreaseValue
();
double
valueSum
=
0
;
double
baselineSum
=
0
;
DecimalFormat
df
=
new
DecimalFormat
(
"0.0"
);
if
(
decreasePercent
==
0
)
{
decreasePercent
=
50
;
}
if
(
decreaseValue
==
0
)
{
decreaseValue
=
100
;
}
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
baselines
.
append
(
df
.
format
(
baseLineTrim
[
i
])).
append
(
" "
);
values
.
append
(
df
.
format
(
valueTrim
[
i
])).
append
(
" "
);
valueSum
=
valueSum
+
valueTrim
[
i
];
baselineSum
=
baselineSum
+
baseLineTrim
[
i
];
if
(
baseLineTrim
[
i
]
<=
0
)
{
baseLineTrim
[
i
]
=
100
;
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
if
(
type
==
MetricType
.
COUNT
||
type
==
MetricType
.
SUM
)
{
if
(
valueTrim
[
i
]
/
baseLineTrim
[
i
]
>
(
1
-
decreasePercent
/
100
)
||
(
baseLineTrim
[
i
]
-
valueTrim
[
i
])
<
decreaseValue
)
{
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
}
}
double
percent
=
(
1
-
valueSum
/
baselineSum
)
*
100
;
StringBuilder
sb
=
new
StringBuilder
();
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
sb
.
append
(
"[基线值:"
).
append
(
baselines
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[实际值:"
).
append
(
values
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[下降:"
).
append
(
df
.
format
(
percent
)).
append
(
"%"
).
append
(
"]"
);
sb
.
append
(
"[告警时间:"
).
append
(
sdf
.
format
(
new
Date
())
+
"]"
);
return
new
Pair
<
Boolean
,
String
>(
true
,
sb
.
toString
());
}
public
Pair
<
Boolean
,
String
>
checkData
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
,
List
<
Config
>
configs
)
{
int
valLength
=
value
.
length
;
for
(
Config
con
:
configs
)
{
int
dataLength
=
getMaxMinute
(
con
);
if
(
dataLength
>
valLength
)
{
continue
;
}
double
[]
validVal
=
getLastMinutes
(
value
,
dataLength
);
double
[]
validBase
=
getLastMinutes
(
baseline
,
dataLength
);
Pair
<
Boolean
,
String
>
tmpResult
=
checkDataByConfig
(
config
,
validVal
,
validBase
,
type
,
con
);
if
(
tmpResult
.
getKey
()
==
true
)
{
return
tmpResult
;
}
}
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
private
int
getMaxMinute
(
Config
con
)
{
int
maxMinute
=
0
;
for
(
Condition
condition
:
con
.
getConditions
())
{
int
tmpMinute
=
condition
.
getMinute
();
if
(
tmpMinute
>
maxMinute
)
{
maxMinute
=
tmpMinute
;
}
}
return
maxMinute
;
}
private
Pair
<
Boolean
,
String
>
checkDataByConfig
(
MetricItemConfig
config
,
double
[]
value
,
double
[]
baseline
,
MetricType
type
,
Config
con
)
{
int
length
=
value
.
length
;
StringBuilder
baselines
=
new
StringBuilder
();
StringBuilder
values
=
new
StringBuilder
();
double
valueSum
=
0
;
double
baselineSum
=
0
;
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
baselines
.
append
(
m_df
.
format
(
baseline
[
i
])).
append
(
" "
);
values
.
append
(
m_df
.
format
(
value
[
i
])).
append
(
" "
);
valueSum
=
valueSum
+
value
[
i
];
baselineSum
=
baselineSum
+
baseline
[
i
];
if
(
baseline
[
i
]
<=
0
)
{
baseline
[
i
]
=
100
;
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
if
(
type
==
MetricType
.
COUNT
||
type
==
MetricType
.
SUM
)
{
if
(!
judgeByRule
(
con
,
value
[
i
],
baseline
[
i
],
i
,
length
))
{
return
new
Pair
<
Boolean
,
String
>(
false
,
""
);
}
}
}
double
percent
=
(
1
-
valueSum
/
baselineSum
)
*
100
;
StringBuilder
sb
=
new
StringBuilder
();
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
sb
.
append
(
"[基线值:"
).
append
(
baselines
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[实际值:"
).
append
(
values
.
toString
()).
append
(
"] "
);
sb
.
append
(
"[下降:"
).
append
(
m_df
.
format
(
percent
)).
append
(
"%"
).
append
(
"]"
);
sb
.
append
(
"[告警时间:"
).
append
(
sdf
.
format
(
new
Date
())
+
"]"
);
return
new
Pair
<
Boolean
,
String
>(
true
,
sb
.
toString
());
}
private
double
[]
getLastMinutes
(
double
[]
doubleList
,
int
remainCount
)
{
double
[]
result
=
new
double
[
remainCount
];
int
startIndex
=
doubleList
.
length
-
remainCount
;
for
(
int
i
=
0
;
i
<
remainCount
;
i
++)
{
result
[
i
]
=
doubleList
[
startIndex
+
i
];
}
return
result
;
}
private
Long
getMillsByString
(
String
time
)
throws
Exception
{
String
[]
times
=
time
.
split
(
":"
);
int
hour
=
Integer
.
parseInt
(
times
[
0
]);
int
minute
=
Integer
.
parseInt
(
times
[
1
]);
long
result
=
hour
*
60
*
60
*
1000
+
minute
*
60
*
1000
;
return
result
;
}
private
boolean
judgeByRule
(
Config
ruleConfig
,
double
value
,
double
baseline
,
int
index
,
int
length
)
{
boolean
isRuleTriggered
=
false
;
long
ruleStartTime
;
long
ruleEndTime
;
long
nowTime
=
(
System
.
currentTimeMillis
()
+
8
*
60
*
60
*
1000
)
%
(
24
*
60
*
60
*
1000
);
try
{
ruleStartTime
=
getMillsByString
(
ruleConfig
.
getStarttime
());
ruleEndTime
=
getMillsByString
(
ruleConfig
.
getEndtime
())
+
ONE_MINUTE_MILLSEC
;
}
catch
(
Exception
ex
)
{
ruleStartTime
=
0L
;
ruleEndTime
=
86400000L
;
}
if
(
nowTime
<
ruleStartTime
||
nowTime
>
ruleEndTime
)
{
return
false
;
}
for
(
Condition
condition
:
ruleConfig
.
getConditions
())
{
if
(
isRuleTriggered
)
{
break
;
}
int
minute
=
condition
.
getMinute
();
if
(
minute
==
0
)
{
minute
=
JUDGE_DEFAULT_MINUTE
;
}
if
(
index
<
length
-
minute
)
{
continue
;
}
boolean
isSubRuleTriggered
=
true
;
for
(
Subcondition
subCondition
:
condition
.
getSubconditions
())
{
if
(!
isSubRuleTriggered
)
{
break
;
}
String
ruleType
=
subCondition
.
getType
();
int
ruleValue
=
Integer
.
parseInt
(
subCondition
.
getText
());
RuleType
rule
=
RuleType
.
getByTypeId
(
ruleType
);
if
(
rule
==
null
)
{
continue
;
}
else
{
isSubRuleTriggered
=
rule
.
executeRule
(
value
,
baseline
,
ruleValue
);
}
}
if
(
isSubRuleTriggered
)
{
isRuleTriggered
=
true
;
}
}
return
isRuleTriggered
;
}
}
cat-home/src/main/java/com/dianping/cat/system/config/MetricRuleConfigManager.java
0 → 100644
浏览文件 @
30de9a29
package
com.dianping.cat.system.config
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable
;
import
org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException
;
import
org.unidal.dal.jdbc.DalNotFoundException
;
import
org.unidal.helper.Files
;
import
org.unidal.lookup.annotation.Inject
;
import
com.dianping.cat.Cat
;
import
com.dianping.cat.core.config.Config
;
import
com.dianping.cat.core.config.ConfigDao
;
import
com.dianping.cat.core.config.ConfigEntity
;
import
com.dianping.cat.home.monitorrules.entity.MetricItem
;
import
com.dianping.cat.home.monitorrules.entity.MonitorRules
;
import
com.dianping.cat.home.monitorrules.entity.Rule
;
import
com.dianping.cat.home.monitorrules.transform.DefaultSaxParser
;
public
class
MetricRuleConfigManager
implements
Initializable
{
@Inject
private
ConfigDao
m_configDao
;
private
int
m_configId
;
private
MonitorRules
m_config
;
private
static
final
String
CONFIG_NAME
=
"monitorRulesConfig"
;
public
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
getMetricIdRuleMap
()
{
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
map
=
new
HashMap
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>();
for
(
Rule
rule
:
m_config
.
getRules
())
{
for
(
MetricItem
metricItem
:
rule
.
getMetricItems
())
{
String
type
=
metricItem
.
getType
();
if
(
type
==
null
||
!
type
.
equals
(
"id"
))
{
continue
;
}
String
key
=
metricItem
.
getText
();
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>
configs
=
getOrBuildRuleList
(
map
,
key
);
configs
.
addAll
(
rule
.
getConfigs
());
}
}
return
map
;
}
public
MonitorRules
getMonitorRules
()
{
return
m_config
;
}
private
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>
getOrBuildRuleList
(
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
map
,
String
key
)
{
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>
configs
=
map
.
get
(
key
);
if
(
configs
==
null
)
{
configs
=
new
ArrayList
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>();
map
.
put
(
key
,
configs
);
}
return
configs
;
}
public
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>
getConfigs
(
String
product
,
String
domain
,
String
key
,
String
metricKey
)
{
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>
configs
=
new
ArrayList
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>();
for
(
Rule
rule
:
m_config
.
getRules
())
{
for
(
MetricItem
metricItem
:
rule
.
getMetricItems
())
{
String
type
=
metricItem
.
getType
();
if
(
type
==
null
)
{
continue
;
}
else
if
(
type
.
equals
(
"id"
))
{
String
context
=
metricItem
.
getText
();
if
(
context
!=
null
&&
context
.
equals
(
metricKey
))
{
configs
.
addAll
(
rule
.
getConfigs
());
break
;
}
}
else
if
(
type
.
equals
(
"regex"
))
{
String
[]
context
=
metricItem
.
getText
().
split
(
":"
);
Pattern
p
=
Pattern
.
compile
(
context
[
0
]);
Matcher
m
=
p
.
matcher
(
product
);
if
(!
m
.
find
())
{
continue
;
}
p
=
Pattern
.
compile
(
context
[
1
]);
m
=
p
.
matcher
(
domain
);
if
(!
m
.
find
())
{
continue
;
}
p
=
Pattern
.
compile
(
context
[
2
]);
m
=
p
.
matcher
(
key
);
if
(
m
.
find
())
{
configs
.
addAll
(
rule
.
getConfigs
());
break
;
}
}
}
}
return
configs
;
}
@Override
public
void
initialize
()
throws
InitializationException
{
try
{
Config
config
=
m_configDao
.
findByName
(
CONFIG_NAME
,
ConfigEntity
.
READSET_FULL
);
String
content
=
config
.
getContent
();
m_config
=
DefaultSaxParser
.
parse
(
content
);
m_configId
=
config
.
getId
();
}
catch
(
DalNotFoundException
e
)
{
try
{
String
content
=
Files
.
forIO
().
readFrom
(
this
.
getClass
().
getResourceAsStream
(
"/config/default-metric-rule-config.xml"
),
"utf-8"
);
Config
config
=
m_configDao
.
createLocal
();
config
.
setName
(
CONFIG_NAME
);
config
.
setContent
(
content
);
m_configDao
.
insert
(
config
);
m_config
=
DefaultSaxParser
.
parse
(
content
);
m_configId
=
config
.
getId
();
}
catch
(
Exception
ex
)
{
Cat
.
logError
(
ex
);
}
}
catch
(
Exception
e
)
{
Cat
.
logError
(
e
);
}
if
(
m_config
==
null
)
{
m_config
=
new
MonitorRules
();
}
}
public
boolean
insert
(
String
xml
)
{
try
{
m_config
=
DefaultSaxParser
.
parse
(
xml
);
return
storeConfig
();
}
catch
(
Exception
e
)
{
Cat
.
logError
(
e
);
return
false
;
}
}
private
boolean
storeConfig
()
{
synchronized
(
this
)
{
try
{
Config
config
=
m_configDao
.
createLocal
();
config
.
setId
(
m_configId
);
config
.
setKeyId
(
m_configId
);
config
.
setName
(
CONFIG_NAME
);
config
.
setContent
(
m_config
.
toString
());
m_configDao
.
updateByPK
(
config
,
ConfigEntity
.
UPDATESET_FULL
);
}
catch
(
Exception
e
)
{
Cat
.
logError
(
e
);
return
false
;
}
}
return
true
;
}
}
cat-home/src/main/java/com/dianping/cat/system/page/config/Action.java
浏览文件 @
30de9a29
...
...
@@ -46,6 +46,8 @@ public enum Action implements org.unidal.web.mvc.Action {
METRIC_CONFIG_ADD_OR_UPDATE_SUBMIT
(
"metricConfigAddSumbit"
),
METRIC_CONFIG_DELETE
(
"metricConfigDelete"
),
METRIC_RULE_CONFIG_UPDATE
(
"metricRuleConfigUpdate"
),
EXCEPTION_THRESHOLDS
(
"exceptionThresholds"
),
...
...
cat-home/src/main/java/com/dianping/cat/system/page/config/Handler.java
浏览文件 @
30de9a29
...
...
@@ -49,6 +49,7 @@ import com.dianping.cat.system.config.DomainGroupConfigManager;
import
com.dianping.cat.system.config.ExceptionThresholdConfigManager
;
import
com.dianping.cat.system.config.MetricAggregationConfigManager
;
import
com.dianping.cat.system.config.MetricGroupConfigManager
;
import
com.dianping.cat.system.config.MetricRuleConfigManager
;
import
com.dianping.cat.system.config.UtilizationConfigManager
;
public
class
Handler
implements
PageHandler
<
Context
>
{
...
...
@@ -88,6 +89,9 @@ public class Handler implements PageHandler<Context> {
@Inject
private
MetricAggregationConfigManager
m_metricAggregationConfigManager
;
@Inject
private
MetricRuleConfigManager
m_metricRuleConfigManager
;
@Inject
private
DomainNavManager
m_manager
;
...
...
@@ -285,6 +289,15 @@ public class Handler implements PageHandler<Context> {
payload
.
getDomain
(),
payload
.
getType
(),
payload
.
getMetricKey
())));
metricConfigList
(
payload
,
model
);
break
;
case
METRIC_RULE_CONFIG_UPDATE:
String
metricRuleConfig
=
payload
.
getContent
();
if
(!
StringUtils
.
isEmpty
(
metricRuleConfig
))
{
model
.
setOpState
(
m_metricRuleConfigManager
.
insert
(
metricRuleConfig
));
}
else
{
model
.
setOpState
(
true
);
}
model
.
setContent
(
m_metricRuleConfigManager
.
getMonitorRules
().
toString
());
break
;
case
EXCEPTION_THRESHOLDS:
model
.
setExceptionLimits
(
m_exceptionConfigManager
.
queryAllExceptionLimits
());
break
;
...
...
cat-home/src/main/java/com/dianping/cat/system/page/config/JspFile.java
浏览文件 @
30de9a29
...
...
@@ -26,6 +26,8 @@ public enum JspFile {
METRIC_CONFIG_ADD_OR_UPDATE_SUBMIT
(
"/jsp/system/metric/metricConfigs.jsp"
),
METRIC_CONFIG_LIST
(
"/jsp/system/metric/metricConfigs.jsp"
),
METRIC_RULE_CONFIG_UPDATE
(
"/jsp/system/metricRule/metricRuleConfig.jsp"
),
EXCEPTION_THRESHOLD
(
"/jsp/system/exception/exceptionThreshold.jsp"
),
...
...
cat-home/src/main/java/com/dianping/cat/system/page/config/JspViewer.java
浏览文件 @
30de9a29
...
...
@@ -60,6 +60,8 @@ public class JspViewer extends BaseJspViewer<SystemPage, Action, Context, Model>
return
JspFile
.
METRIC_CONFIG_LIST
.
getPath
();
case
METRIC_CONFIG_DELETE:
return
JspFile
.
METRIC_CONFIG_LIST
.
getPath
();
case
METRIC_RULE_CONFIG_UPDATE:
return
JspFile
.
METRIC_RULE_CONFIG_UPDATE
.
getPath
();
// Excepton Config
case
EXCEPTION_THRESHOLDS:
return
JspFile
.
EXCEPTION_THRESHOLD
.
getPath
();
...
...
cat-home/src/main/resources/META-INF/dal/model/monitor-rules-codegen.xml
0 → 100644
浏览文件 @
30de9a29
<?xml version="1.0" encoding="UTF-8"?>
<model>
<entity
name=
"monitor-rules"
root=
"true"
>
<entity-ref
name=
"rule"
type=
"list"
names=
"rules"
/>
</entity>
<entity
name=
"rule"
>
<attribute
name=
"id"
value-type=
"String"
/>
<entity-ref
name=
"metric-item"
type=
"list"
names=
"metric-items"
/>
<entity-ref
name=
"config"
type=
"list"
names=
"configs"
/>
</entity>
<entity
name=
"metric-item"
>
<attribute
name=
"type"
value-type=
"String"
/>
<element
name=
"text"
value-type=
"String"
text=
"true"
/>
</entity>
<entity
name=
"config"
>
<attribute
name=
"starttime"
value-type=
"String"
/>
<attribute
name=
"endtime"
value-type=
"String"
/>
<entity-ref
name=
"condition"
type=
"list"
names=
"conditions"
/>
</entity>
<entity
name=
"condition"
>
<attribute
name=
"title"
value-type=
"String"
/>
<entity-ref
name=
"subcondition"
type=
"list"
names=
"subconditions"
/>
</entity>
<entity
name=
"subcondition"
>
<attribute
name=
"type"
value-type=
"int"
/>
<element
name=
"text"
value-type=
"String"
text=
"true"
/>
</entity>
</model>
cat-home/src/main/resources/META-INF/dal/model/monitor-rules-manifest.xml
0 → 100644
浏览文件 @
30de9a29
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<file
path=
"monitor-rules-codegen.xml"
/>
<file
path=
"monitor-rules-model.xml"
/>
</manifest>
cat-home/src/main/resources/META-INF/dal/model/monitor-rules-model.xml
0 → 100644
浏览文件 @
30de9a29
<?xml version="1.0" encoding="UTF-8"?>
<model
model-package=
"com.dianping.cat.home.monitorrules"
enable-sax-parser=
"true"
enable-xml-parser=
"true"
enable-xml-builder=
"true"
>
<entity
name=
"monitor-rules"
root=
"true"
>
<entity-ref
name=
"rule"
type=
"list"
names=
"rules"
/>
</entity>
<entity
name=
"rule"
>
<attribute
name=
"id"
value-type=
"String"
/>
<entity-ref
name=
"metric-item"
type=
"list"
names=
"metric-items"
/>
<entity-ref
name=
"config"
type=
"list"
names=
"configs"
/>
</entity>
<entity
name=
"metric-item"
>
<attribute
name=
"type"
value-type=
"String"
/>
<element
name=
"text"
value-type=
"String"
text=
"true"
/>
</entity>
<entity
name=
"config"
>
<attribute
name=
"starttime"
value-type=
"String"
/>
<attribute
name=
"endtime"
value-type=
"String"
/>
<entity-ref
name=
"condition"
type=
"list"
names=
"conditions"
/>
</entity>
<entity
name=
"condition"
>
<attribute
name=
"title"
value-type=
"String"
/>
<attribute
name=
"minute"
value-type=
"int"
default-value=
"2"
/>
<entity-ref
name=
"subcondition"
type=
"list"
names=
"subconditions"
/>
</entity>
<entity
name=
"subcondition"
>
<attribute
name=
"type"
value-type=
"String"
/>
<element
name=
"text"
value-type=
"String"
text=
"true"
/>
</entity>
</model>
cat-home/src/main/resources/META-INF/plexus/components.xml
浏览文件 @
30de9a29
...
...
@@ -3471,6 +3471,9 @@
<requirement>
<role>
com.dianping.cat.system.config.MetricAggregationConfigManager
</role>
</requirement>
<requirement>
<role>
com.dianping.cat.system.config.MetricRuleConfigManager
</role>
</requirement>
<requirement>
<role>
com.dianping.cat.report.view.DomainNavManager
</role>
</requirement>
...
...
@@ -3506,6 +3509,15 @@
</requirement>
</requirements>
</component>
<component>
<role>
com.dianping.cat.system.config.MetricRuleConfigManager
</role>
<implementation>
com.dianping.cat.system.config.MetricRuleConfigManager
</implementation>
<requirements>
<requirement>
<role>
com.dianping.cat.core.config.ConfigDao
</role>
</requirement>
</requirements>
</component>
<component>
<role>
com.dianping.cat.system.page.plugin.Handler
</role>
<implementation>
com.dianping.cat.system.page.plugin.Handler
</implementation>
...
...
cat-home/src/main/resources/META-INF/wizard/model/wizard.xml
浏览文件 @
30de9a29
...
...
@@ -39,6 +39,9 @@
<model
package=
"com.dianping.cat.home.metricAggregation"
name=
"metric-aggregation-config"
>
<sample-model>
src/main/resources/config/default-metric-aggregation-config.xml
</sample-model>
</model>
<model
package=
"com.dianping.cat.home.monitor-rules"
name=
"monitor-rules"
>
<sample-model>
/Users/leon/Documents/GitRepo/cat/rule.xml
</sample-model>
</model>
<model
package=
"com.dianping.cat.home.netgraph"
name=
"netgraph"
>
<sample-model>
src/main/resources/config/default-nettopology-config.xml
</sample-model>
</model>
...
...
cat-home/src/main/resources/config/default-metric-rule-config.xml
0 → 100644
浏览文件 @
30de9a29
<monitor-rules>
<rule
id=
"switchErrorAndDiscard"
>
<metric-item
type=
"regex"
>
f5[^:]*:[^:]+:.*(?=errors$)
</metric-item>
<metric-item
type=
"regex"
>
f5[^:]*:[^:]+:.*(?=discards$)
</metric-item>
<metric-item
type=
"regex"
>
switch[^:]*:[^:]+:.*(?=errors$)
</metric-item>
<metric-item
type=
"regex"
>
switch[^:]*:[^:]+:.*(?=discards$)
</metric-item>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition
minute=
"3"
>
<subcondition
type=
"MaxVal"
>
3
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"switchInAndOut"
>
<metric-item
type=
"regex"
>
f5[^:]*:[^:]+:.*(?=in$)
</metric-item>
<metric-item
type=
"regex"
>
f5[^:]*:[^:]+:.*(?=out$)
</metric-item>
<metric-item
type=
"regex"
>
switch[^:]*:[^:]+:.*(?=in$)
</metric-item>
<metric-item
type=
"regex"
>
switch[^:]*:[^:]+:.*(?=out$)
</metric-item>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition
minute=
"2"
>
<subcondition
type=
"DescPer"
>
50
</subcondition>
</condition>
</config>
</rule>
</monitor-rules>
cat-home/src/main/webapp/images/rule.png
0 → 100644
浏览文件 @
30de9a29
263.3 KB
cat-home/src/main/webapp/jsp/report/alteration/alter_query.jsp
浏览文件 @
30de9a29
...
...
@@ -21,6 +21,10 @@
<a
id=
"refresh10"
class=
'btn btn-small btn-primary'
onclick=
"queryFrequency(10)"
>
10秒
</a>
<a
id=
"refresh20"
class=
'btn btn-small btn-primary'
onclick=
"queryFrequency(20)"
>
20秒
</a>
<a
id=
"refresh30"
class=
'btn btn-small btn-primary'
onclick=
"queryFrequency(30)"
>
30秒
</a>
类型
<input
type=
"checkbox"
checked=
"checked"
id=
"show_puppet"
class=
"typeCheckbox"
/>
puppet
<input
type=
"checkbox"
checked=
"checked"
id=
"show_workflow"
class=
"typeCheckbox"
/>
workflow
<input
type=
"checkbox"
checked=
"checked"
id=
"show_lazyman"
class=
"typeCheckbox"
/>
lazyman
<br>
<div
class=
"btn-group"
>
...
...
@@ -28,6 +32,19 @@
</div>
<script>
function
typeCheckStr
(){
var
result
=
""
;
if
(
!
document
.
getElementById
(
"
show_puppet
"
).
checked
){
result
+=
"
showPuppet=false&
"
;
}
if
(
!
document
.
getElementById
(
"
show_workflow
"
).
checked
){
result
+=
"
showWorkflow=false&
"
;
}
if
(
!
document
.
getElementById
(
"
show_lazyman
"
).
checked
){
result
+=
"
showLazyman=false&
"
;
}
return
result
;
}
function
queryNew
(){
var
startTime
=
$
(
"
#startTime
"
).
val
();
var
endTime
=
$
(
"
#endTime
"
).
val
();
...
...
@@ -36,14 +53,16 @@
window
.
location
.
href
=
"
?op=view&domain=
"
+
domain
+
"
&startTime=
"
+
startTime
+
"
&endTime=
"
+
endTime
+
"
&hostname=
"
+
hostname
;
}
function
queryFullScreen
(
isFullScreen
){
var
typeStatus
=
typeCheckStr
();
<c:if
test=
"
${
payload
.
refresh
}
"
>
window
.
location
.
href
=
"
?domain=${payload.domain}&hostname=${payload.hostname}&fullScreen=
"
+
isFullScreen
+
"
&refresh=${payload.refresh}&frequency=${payload.frequency}
"
;
window
.
location
.
href
=
"
?
"
+
typeStatus
+
"
domain=${payload.domain}&hostname=${payload.hostname}&fullScreen=
"
+
isFullScreen
+
"
&refresh=${payload.refresh}&frequency=${payload.frequency}
"
;
</c:if>
<c:if
test=
"
${
!
payload
.
refresh
}
"
>
window
.
location
.
href
=
"
?domain=${payload.domain}&hostname=${payload.hostname}&fullScreen=
"
+
isFullScreen
+
"
&refresh=${payload.refresh}&frequency=${payload.frequency}&startTime=
<fmt:formatDate
value=
"
${
payload
.
startTime
}
"
pattern=
"yyyy-MM-dd HH:mm:ss"
/>
&endTime=
<fmt:formatDate
value=
"
${
payload
.
endTime
}
"
pattern=
"yyyy-MM-dd HH:mm:ss"
/>
"
;
window
.
location
.
href
=
"
?
"
+
typeStatus
+
"
domain=${payload.domain}&hostname=${payload.hostname}&fullScreen=
"
+
isFullScreen
+
"
&refresh=${payload.refresh}&frequency=${payload.frequency}&startTime=
<fmt:formatDate
value=
"
${
payload
.
startTime
}
"
pattern=
"yyyy-MM-dd HH:mm:ss"
/>
&endTime=
<fmt:formatDate
value=
"
${
payload
.
endTime
}
"
pattern=
"yyyy-MM-dd HH:mm:ss"
/>
"
;
</c:if>
}
function
queryFrequency
(
frequency
){
window
.
location
.
href
=
"
?domain=${payload.domain}&hostname=${payload.hostname}&fullScreen=${payload.fullScreen}&refresh=true&frequency=
"
+
frequency
;
var
typeStatus
=
typeCheckStr
();
window
.
location
.
href
=
"
?
"
+
typeStatus
+
"
domain=${payload.domain}&hostname=${payload.hostname}&fullScreen=${payload.fullScreen}&refresh=true&frequency=
"
+
frequency
;
}
</script>
\ No newline at end of file
cat-home/src/main/webapp/jsp/report/alteration/alter_view.jsp
浏览文件 @
30de9a29
...
...
@@ -23,16 +23,16 @@
<th
width=
"12%"
>
机器名
</th>
</tr>
<c:forEach
var=
"item"
items=
"
${
model
.
alterations
}
"
varStatus=
"status"
>
<tr
class=
"
aleration_${item.type}
"
>
<tr
class=
"
content_${item.type}"
style=
"display:table-row
"
>
<td>
${w:format(item.date,'yyyy-MM-dd HH:mm:ss')}
</td>
<td>
${item.type}
</td>
<td
class=
"aleration_${item.type}"
>
${item.type}
</td>
<td
class=
"text-info"
>
<c:choose>
<c:when
test=
"
${
empty
item
.
url
}
"
>
<span
class=
"hreftip"
data-toggle=
"tooltip"
data-placement=
"top"
title=
""
data-original-title=
"${item.content}"
>
${item.title}
</span>
</c:when>
<c:otherwise>
<a
class=
"hreftip"
target=
"_blank"
href=
"${item.url}"
data-toggle=
"tooltip"
data-placement=
"top"
title=
""
data-original-title=
"${item.content}"
>
${item.title}
</a>
<a
class=
"hreftip
out_url
"
target=
"_blank"
href=
"${item.url}"
data-toggle=
"tooltip"
data-placement=
"top"
title=
""
data-original-title=
"${item.content}"
>
${item.title}
</a>
</c:otherwise>
</c:choose>
</td>
...
...
@@ -47,6 +47,11 @@
$
(
'
i[tips]
'
).
popover
();
$
(
'
.hreftip
'
).
tooltip
({
container
:
'
body
'
,
html
:
true
,
delay
:{
show
:
0
,
hide
:
0
}});
$
(
"
.out_url
"
).
each
(
function
(){
var
cur
=
$
(
this
);
cur
.
attr
(
"
href
"
,
decodeURIComponent
(
cur
.
attr
(
"
href
"
)));
});
<c:if
test=
"
${
payload
.
fullScreen
}
"
>
$
(
'
#fullScreen
'
).
addClass
(
'
btn-danger
'
);
$
(
'
.navbar
'
).
hide
();
...
...
@@ -58,14 +63,31 @@
$
(
'
.footer
'
).
show
();
</c:if>
$
(
"
.typeButton
"
).
click
(
function
(){
var
type
=
"
.
"
+
this
.
id
.
replace
(
"
Button
"
,
""
);
if
(
$
(
type
).
css
(
"
display
"
)
==
"
table-cell
"
){
$
(
this
).
removeClass
(
"
btn-primary
"
);
$
(
type
).
css
(
"
display
"
,
"
none
"
);
}
else
if
(
$
(
type
).
css
(
"
display
"
)
==
"
none
"
){
$
(
this
).
addClass
(
"
btn-primary
"
);
$
(
type
).
css
(
"
display
"
,
"
table-cell
"
);
<c:if
test=
"
${
!
payload
.
showPuppet
}
"
>
$
(
"
#show_puppet
"
).
attr
(
"
checked
"
,
false
);
$
(
"
.content_puppet
"
).
css
(
"
display
"
,
"
none
"
);
</c:if>
<c:if
test=
"
${
!
payload
.
showWorkflow
}
"
>
$
(
"
#show_workflow
"
).
attr
(
"
checked
"
,
false
);
$
(
"
.content_workflow
"
).
css
(
"
display
"
,
"
none
"
);
</c:if>
<c:if
test=
"
${
!
payload
.
showLazyman
}
"
>
$
(
"
#show_lazyman
"
).
attr
(
"
checked
"
,
false
);
$
(
"
.content_lazyman
"
).
css
(
"
display
"
,
"
none
"
);
</c:if>
$
(
"
.typeCheckbox
"
).
click
(
function
(){
var
typeContent
=
"
.content_
"
+
this
.
id
.
replace
(
"
show_
"
,
""
);
var
isChecked
=
document
.
getElementById
(
this
.
id
).
checked
;
if
(
!
isChecked
){
$
(
this
).
attr
(
"
checked
"
,
false
);
$
(
typeContent
).
css
(
"
display
"
,
"
none
"
);
}
else
{
$
(
this
).
attr
(
"
checked
"
,
true
);
$
(
typeContent
).
css
(
"
display
"
,
"
table-row
"
);
}
})
...
...
cat-home/src/main/webapp/jsp/report/home/home.jsp
浏览文件 @
30de9a29
...
...
@@ -21,6 +21,7 @@
<li
class=
"text-right"
><a
href=
"#tab1"
data-toggle=
"tab"
><strong>
版本说明
</strong></a></li>
<li
class=
"text-right"
><a
href=
"#tab2"
data-toggle=
"tab"
><strong>
集成文档
</strong></a></li>
<li
class=
"text-right"
><a
href=
"#tab3"
data-toggle=
"tab"
><strong>
业务监控
</strong></a></li>
<li
class=
"text-right"
><a
href=
"#tab12"
data-toggle=
"tab"
><strong>
规则设置
</strong></a></li>
<li
class=
"text-right"
><a
href=
"#tab4"
data-toggle=
"tab"
><strong>
变更监控
</strong></a></li>
<li
class=
"text-right"
><a
href=
"#tab5"
data-toggle=
"tab"
><strong>
网络监控
</strong></a></li>
<li
class=
"text-right"
><a
href=
"#tab6"
data-toggle=
"tab"
><strong>
异常监控
</strong></a></li>
...
...
@@ -43,6 +44,7 @@
<div
class=
"tab-pane"
id=
"tab9"
><%@ include
file=
"userDocument.jsp"
%></div>
<div
class=
"tab-pane"
id=
"tab10"
><%@ include
file=
"problem.jsp"
%></div>
<div
class=
"tab-pane"
id=
"tab11"
><%@ include
file=
"plugin.jsp"
%></div>
<div
class=
"tab-pane"
id=
"tab12"
><%@ include
file=
"monitorRule.jsp"
%></div>
</div>
</div>
</div>
...
...
cat-home/src/main/webapp/jsp/report/home/monitorRule.jsp
0 → 100644
浏览文件 @
30de9a29
<%@ page
session=
"false"
language=
"java"
pageEncoding=
"UTF-8"
%>
<h3
class=
"text-error"
>
监控规则配置文档
</h3>
</br>
<h4
class=
"text-info"
>
配置规则的要点
</h4>
<h5>
合理、灵活的监控规则可以帮助更快、更精确的发现业务线上故障。目前Cat的监控规则有五个要素,请按照以下五点要素制定规则:
</h5>
<h5>
a).时间段。同一项业务指标在每天不同的时段可能有不同的趋势。设定该项,可让Cat在每天不同的时间段执行不同的监控规则。
</h5>
<h5>
b).规则组合。在一个时间段中,可能指标触发了多个监控规则中的一个规则就要发出警报,也有可能指标要同时触发了多个监控规则才需要发出警报。这种关系好比电路图中的并联和串联。规则的组合合理有助于提高监控的准确度。
</h5>
<h5>
c).监控类型。通过以下六种类型对指标进行监控:下降百分比、下降数值、上升百分比、上升数值、最大值、最小值。
</h5>
<h5>
d).持续时间。设定时间后(单位为分钟),当指标在设定的时间长度内连续触发了监控规则,才会发出警报。
</h5>
<h5>
e).规则与指标的匹配。监控规则可以按照名称、正则表达式与监控的对象(指标)进行匹配。
</h5>
</br>
<h4
class=
"text-info"
>
监控规则的设定方法
</h4>
<h4
class=
"text-success"
>
第一步:进入配置页面
</h4>
<p>
点击导航栏右侧的"Config"选项
</p>
<p>
在新页面中点击左侧边栏下方的“业务告警配置”选项
</p>
<p>
右方的页面上会显示一个xml,对其进行下步的配置。
</p>
</br>
<h4
class=
"text-success"
>
第二步:更改配置信息
</h4>
<h5>
配置文件格式如下:
</h5>
<img
class=
"img-polaroid"
width=
'60%'
src=
"${model.webapp}/images/rule.png"
/>
<h5>
配置方式如下:
</h5>
<p>
1).每一个rule元素为规则的基本单位。请按照需求添加一个rule元素或者对某一个rule进行修改
</p>
<p>
2).rule元素由两个部分组成:监控对象与监控规则
</p>
<p>
a.监控对象:由metric-item元素匹配。metric-item元素可以有多个。metric-item支持两种匹配方式:
</p>
<p>
(1) 按照id匹配。此种方式适用于匹配一个具体的监控指标。此时type为id,内容为
<b>
产品线:项目名:指标
</b></p>
<p>
(2) 按照正则表达式匹配。此种情况适用于同时匹配多个监控对象。此时type为regex,内容仍形如
<b>
产品线:项目名:指标
</b>
,三者用冒号分割。三者每一项都可以写为正则表达式。
</p>
<p>
b.监控条件配置:由config元素组成,每个config代表一个时间段的规则,由starttime和endtime两个属性确定。时间的配置格式为:“hh:mm”,请注意hh为24小时制。
</p>
<p>
config元素由多个监控条件组成,条件由condition元素表示。一个config下的多个condition为并联关系,当一个condition被触发,conditon所在的整个rule就被触发。
</p>
<p>
condition元素中的minute属性表示该条件的持续时间。设定时间单位为分钟。当指标在设定的时间长度内连续触发了该条规则,才会出发该condition。
</p>
<p>
condition由subcondition组成。一个condition下的多个subcondition为串联关系,只有当一个condition下的全部subcondition被触发,该condition才被触发。
</p>
<p>
subcondition有六个类型,由type属性指定。subcondition的内容为对应的阈值,请注意阈值只能由数字组成,当阈值表达百分比时,不能在最后加上百分号。六种类型如下:
</p>
<table
style=
"width:50%"
class=
"table table-striped table-bordered table-condensed"
>
<tr><th
width=
"30%"
>
类型
</th><th>
说明
</th></tr>
<tr><td>
DescPer
</td><td>
下降百分比
</td></tr>
<tr><td>
DescVal
</td><td>
下降数值
</td></tr>
<tr><td>
AscPer
</td><td>
上升百分比
</td></tr>
<tr><td>
AscVal
</td><td>
上升数值
</td></tr>
<tr><td>
MaxVal
</td><td>
最大值
</td></tr>
<tr><td>
MinVal
</td><td>
最小值
</td></tr>
</table>
<p>
3).点击提交功能。如果标题“业务监控规则相关信息”上方出现“操作成功”的提示,代表规则添加成功,将会在下次执行时被应用
</p>
\ No newline at end of file
cat-home/src/main/webapp/jsp/system/configTree.jsp
浏览文件 @
30de9a29
...
...
@@ -10,6 +10,7 @@
<li
class=
"text-right"
id=
"exceptionConfigList"
><a
href=
"?op=exceptionThresholds"
><strong>
异常阀值配置
</strong></a></li>
<li
class=
'nav-header'
><h4>
其他配置
</h4></li>
<li
class=
"text-right"
id=
"metricConfigList"
><a
href=
"?op=metricConfigList"
><strong>
业务监控规则
</strong></a></li>
<li
class=
"text-right"
id=
"metricRuleConfigUpdate"
><a
href=
"?op=metricRuleConfigUpdate"
><strong>
业务告警配置
</strong></a></li>
<li
class=
"text-right"
id=
"metricGroupConfigUpdate"
><a
href=
"?op=metricGroupConfigUpdate"
><strong>
业务指标分组
</strong></a></li>
<li
class=
"text-right"
id=
"metricAggregationConfigUpdate"
><a
href=
"?op=metricAggregationConfigUpdate"
><strong>
业务指标汇总
</strong></a></li>
<li
class=
"text-right"
id=
"bugConfigUpdate"
><a
href=
"?op=bugConfigUpdate"
><strong>
异常规范配置
</strong></a></li>
...
...
cat-home/src/main/webapp/jsp/system/metricRule/metricRuleConfig.jsp
0 → 100644
浏览文件 @
30de9a29
<%@ page
contentType=
"text/html; charset=utf-8"
%>
<%@ taglib
prefix=
"a"
uri=
"/WEB-INF/app.tld"
%>
<%@ taglib
prefix=
"c"
uri=
"http://java.sun.com/jsp/jstl/core"
%>
<%@ taglib
prefix=
"res"
uri=
"http://www.unidal.org/webres"
%>
<%@ taglib
prefix=
"w"
uri=
"http://www.unidal.org/web/core"
%>
<a:body>
<res:useJs
value=
"
${
res
.
js
.
local
[
'jquery.validate.min.js'
]
}
"
target=
"head-js"
/>
<res:useJs
value=
"
${
res
.
js
.
local
[
'dependencyConfig.js'
]
}
"
target=
"head-js"
/>
<res:useJs
value=
"
${
res
.
js
.
local
[
'alarm_js'
]
}
"
target=
"head-js"
/>
<res:useCss
value=
"
${
res
.
css
.
local
[
'select2.css'
]
}
"
target=
"head-css"
/>
<res:useJs
value=
"
${
res
.
js
.
local
[
'select2.min.js'
]
}
"
target=
"head-js"
/>
<div
class=
"row-fluid"
>
<div
class=
"span2"
>
<%@include
file=
"../configTree.jsp"
%>
</div>
<div
class=
"span10"
>
<form
name=
"metricRuleConfigUpdate"
id=
"form"
method=
"post"
action=
"${model.pageUri}?op=metricRuleConfigUpdate"
>
<h4
class=
"text-center text-error"
id=
"state"
>
</h4>
<h4
class=
"text-center text-error"
>
业务监控规则相关信息
</h4>
<table
class=
"table table-striped table-bordered table-condensed table-hover"
>
<tr>
<td><textarea
name=
"content"
style=
"width:auto"
rows=
"20"
cols=
"150"
>
${model.content}
</textarea></td>
</tr>
<tr>
<td
style=
"text-align:center"
><input
class=
'btn btn-primary'
type=
"submit"
name=
"submit"
value=
"提交"
/></td>
</tr>
</table>
</form>
</div>
</div>
</a:body>
<script
type=
"text/javascript"
>
$
(
document
).
ready
(
function
()
{
$
(
'
#metricRuleConfigUpdate
'
).
addClass
(
'
active
'
);
var
state
=
'
${model.opState}
'
;
if
(
state
==
'
Success
'
){
$
(
'
#state
'
).
html
(
'
操作成功
'
);
}
else
{
$
(
'
#state
'
).
html
(
'
操作失败
'
);
}
setInterval
(
function
(){
$
(
'
#state
'
).
html
(
'
'
);
},
3000
);
});
</script>
\ No newline at end of file
cat-home/src/test/java/com/dianping/cat/demo/RuleConfigTest.java
0 → 100644
浏览文件 @
30de9a29
package
com.dianping.cat.demo
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
junit.framework.Assert
;
import
org.junit.Test
;
import
org.unidal.helper.Files
;
import
org.unidal.tuple.Pair
;
import
com.dianping.cat.Cat
;
import
com.dianping.cat.advanced.metric.config.entity.MetricItemConfig
;
import
com.dianping.cat.home.monitorrules.entity.MonitorRules
;
import
com.dianping.cat.home.monitorrules.entity.Rule
;
import
com.dianping.cat.home.monitorrules.transform.DefaultSaxParser
;
import
com.dianping.cat.report.task.metric.AlertConfig
;
import
com.dianping.cat.report.task.metric.MetricType
;
public
class
RuleConfigTest
{
private
MonitorRules
buildMonitorRuleFromFile
(
String
path
)
{
try
{
String
content
=
Files
.
forIO
().
readFrom
(
this
.
getClass
().
getResourceAsStream
(
path
),
"utf-8"
);
return
DefaultSaxParser
.
parse
(
content
);
}
catch
(
Exception
ex
)
{
Cat
.
logError
(
ex
);
return
null
;
}
}
private
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
buildConfigMap
(
MonitorRules
monitorRules
)
{
if
(
monitorRules
==
null
||
monitorRules
.
getRules
().
size
()
==
0
)
{
return
null
;
}
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
map
=
new
HashMap
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>();
for
(
Rule
rule
:
monitorRules
.
getRules
())
{
map
.
put
(
rule
.
getId
(),
rule
.
getConfigs
());
}
return
map
;
}
@Test
public
void
testRule
()
{
AlertConfig
alertConfig
=
new
AlertConfig
();
MetricItemConfig
config
=
new
MetricItemConfig
();
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
configMap
=
buildConfigMap
(
buildMonitorRuleFromFile
(
"/config/demo-rule-monitor.xml"
));
Assert
.
assertNotNull
(
configMap
);
double
baseline
[]
=
{
200
,
200
};
double
value
[]
=
{
100
,
100
};
Pair
<
Boolean
,
String
>
result
=
alertConfig
.
checkData
(
config
,
value
,
baseline
,
MetricType
.
COUNT
,
configMap
.
get
(
"demo1"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
}
@Test
public
void
testCondition
()
{
AlertConfig
alertConfig
=
new
AlertConfig
();
MetricItemConfig
config
=
new
MetricItemConfig
();
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
configMap
=
buildConfigMap
(
buildMonitorRuleFromFile
(
"/config/demo-rule-monitor.xml"
));
Pair
<
Boolean
,
String
>
result
;
Assert
.
assertNotNull
(
configMap
);
double
[]
baseline7
=
{
200
,
200
};
double
[]
value7
=
{
100
,
100
};
result
=
alertConfig
.
checkData
(
config
,
value7
,
baseline7
,
MetricType
.
COUNT
,
configMap
.
get
(
"conditionCombination"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline8
=
{
200
,
200
};
double
[]
value8
=
{
100
,
100
};
result
=
alertConfig
.
checkData
(
config
,
value8
,
baseline8
,
MetricType
.
COUNT
,
configMap
.
get
(
"subconditionCombination"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
false
);
}
@Test
public
void
testMinute
()
{
AlertConfig
alertConfig
=
new
AlertConfig
();
MetricItemConfig
config
=
new
MetricItemConfig
();
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
configMap
=
buildConfigMap
(
buildMonitorRuleFromFile
(
"/config/test-minute-monitor.xml"
));
Assert
.
assertNotNull
(
configMap
);
double
baseline
[]
=
{
50
,
200
,
200
};
double
value
[]
=
{
50
,
100
,
100
};
Pair
<
Boolean
,
String
>
result
=
alertConfig
.
checkData
(
config
,
value
,
baseline
,
MetricType
.
COUNT
,
configMap
.
get
(
"two-minute"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
}
}
cat-home/src/test/java/com/dianping/cat/report/task/metric/AlertConfigTest.java
浏览文件 @
30de9a29
package
com.dianping.cat.report.task.metric
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
junit.framework.Assert
;
import
org.junit.Test
;
import
org.unidal.helper.Files
;
import
org.unidal.tuple.Pair
;
import
com.dianping.cat.Cat
;
import
com.dianping.cat.advanced.metric.config.entity.MetricItemConfig
;
import
com.dianping.cat.home.monitorrules.entity.MonitorRules
;
import
com.dianping.cat.home.monitorrules.entity.Rule
;
import
com.dianping.cat.home.monitorrules.transform.DefaultSaxParser
;
public
class
AlertConfigTest
{
private
MonitorRules
buildMonitorRuleFromFile
(
String
path
)
{
try
{
String
content
=
Files
.
forIO
().
readFrom
(
this
.
getClass
().
getResourceAsStream
(
path
),
"utf-8"
);
return
DefaultSaxParser
.
parse
(
content
);
}
catch
(
Exception
ex
)
{
Cat
.
logError
(
ex
);
return
null
;
}
}
private
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
buildConfigMap
(
MonitorRules
monitorRules
)
{
if
(
monitorRules
==
null
||
monitorRules
.
getRules
().
size
()
==
0
)
{
return
null
;
}
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
map
=
new
HashMap
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>();
for
(
Rule
rule
:
monitorRules
.
getRules
())
{
map
.
put
(
rule
.
getId
(),
rule
.
getConfigs
());
}
return
map
;
}
@Test
public
void
test
()
{
AlertConfig
alertConfig
=
new
AlertConfig
();
...
...
@@ -48,17 +81,17 @@ public class AlertConfigTest {
config
.
setDecreasePercentage
(
79
);
result
=
alertConfig
.
checkData
(
config
,
value4
,
baseline4
,
MetricType
.
COUNT
);
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
config
.
setDecreaseValue
(
40
);
config
.
setDecreasePercentage
(
80
);
result
=
alertConfig
.
checkData
(
config
,
value4
,
baseline4
,
MetricType
.
COUNT
);
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
false
);
config
.
setDecreaseValue
(
40
);
config
.
setDecreasePercentage
(
80
);
result
=
alertConfig
.
checkData
(
config
,
value4
,
baseline4
,
MetricType
.
COUNT
);
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
false
);
double
[]
baseline5
=
{
117
,
118
};
double
[]
value5
=
{
43
,
48
};
config
.
setDecreasePercentage
(
50
);
...
...
@@ -66,4 +99,71 @@ public class AlertConfigTest {
result
=
alertConfig
.
checkData
(
config
,
value5
,
baseline5
,
MetricType
.
COUNT
);
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
}
@Test
public
void
testRule
()
{
AlertConfig
alertConfig
=
new
AlertConfig
();
MetricItemConfig
config
=
new
MetricItemConfig
();
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
configMap
=
buildConfigMap
(
buildMonitorRuleFromFile
(
"/config/test-rule-monitor.xml"
));
Assert
.
assertNotNull
(
configMap
);
double
baseline
[]
=
{
200
,
200
};
double
value
[]
=
{
100
,
100
};
Pair
<
Boolean
,
String
>
result
=
alertConfig
.
checkData
(
config
,
value
,
baseline
,
MetricType
.
COUNT
,
configMap
.
get
(
"decreasePercentage"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline2
=
{
200
,
300
};
double
[]
value2
=
{
100
,
100
};
result
=
alertConfig
.
checkData
(
config
,
value2
,
baseline2
,
MetricType
.
COUNT
,
configMap
.
get
(
"decreaseValue"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline3
=
{
200
,
50
};
double
[]
value3
=
{
400
,
100
};
result
=
alertConfig
.
checkData
(
config
,
value3
,
baseline3
,
MetricType
.
COUNT
,
configMap
.
get
(
"increasePercentage"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline4
=
{
200
,
50
};
double
[]
value4
=
{
400
,
100
};
result
=
alertConfig
.
checkData
(
config
,
value4
,
baseline4
,
MetricType
.
COUNT
,
configMap
.
get
(
"increaseValue"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline5
=
{
200
,
200
};
double
[]
value5
=
{
500
,
600
};
result
=
alertConfig
.
checkData
(
config
,
value5
,
baseline5
,
MetricType
.
COUNT
,
configMap
.
get
(
"absoluteMaxValue"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline6
=
{
200
,
200
};
double
[]
value6
=
{
50
,
40
};
result
=
alertConfig
.
checkData
(
config
,
value6
,
baseline6
,
MetricType
.
COUNT
,
configMap
.
get
(
"absoluteMinValue"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline7
=
{
200
,
200
};
double
[]
value7
=
{
100
,
100
};
result
=
alertConfig
.
checkData
(
config
,
value7
,
baseline7
,
MetricType
.
COUNT
,
configMap
.
get
(
"conditionCombination"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
double
[]
baseline8
=
{
200
,
200
};
double
[]
value8
=
{
100
,
100
};
result
=
alertConfig
.
checkData
(
config
,
value8
,
baseline8
,
MetricType
.
COUNT
,
configMap
.
get
(
"subconditionCombination"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
false
);
}
@Test
public
void
testMinute
()
{
AlertConfig
alertConfig
=
new
AlertConfig
();
MetricItemConfig
config
=
new
MetricItemConfig
();
Map
<
String
,
List
<
com
.
dianping
.
cat
.
home
.
monitorrules
.
entity
.
Config
>>
configMap
=
buildConfigMap
(
buildMonitorRuleFromFile
(
"/config/test-minute-monitor.xml"
));
Assert
.
assertNotNull
(
configMap
);
double
baseline
[]
=
{
50
,
200
,
200
};
double
value
[]
=
{
50
,
100
,
100
};
Pair
<
Boolean
,
String
>
result
=
alertConfig
.
checkData
(
config
,
value
,
baseline
,
MetricType
.
COUNT
,
configMap
.
get
(
"two-minute"
));
Assert
.
assertEquals
(
result
.
getKey
().
booleanValue
(),
true
);
}
}
cat-home/src/test/resources/config/demo-rule-monitor.xml
0 → 100644
浏览文件 @
30de9a29
<monitor-rules>
<rule
id=
"demo1"
>
<metric-item
type=
"id"
>
f5-2400-1-dianping-com:2400-1-dianping-com:1/1-1-in
</metric-item>
<metric-item
type=
"regex"
>
switch\w*:\w*:\w*in\w*
</metric-item>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"conditionCombination"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
400
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescPer"
>
400
</subcondition>
<subcondition
type=
"DescVal"
>
900
</subcondition>
</condition>
<condition>
<!-- trigger alert -->
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
100
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"subconditionCombination"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
80
</subcondition>
<!-- block alert -->
<subcondition
type=
"MinVal"
>
10
</subcondition>
</condition>
</config>
</rule>
</monitor-rules>
cat-home/src/test/resources/config/test-minute-monitor.xml
0 → 100644
浏览文件 @
30de9a29
<monitor-rules>
<rule
id=
"two-minute"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition
minute=
"2"
>
<subcondition
type=
"DescPer"
>
40
</subcondition>
</condition>
<condition
minute=
"2"
>
<subcondition
type=
"DescVal"
>
80
</subcondition>
</condition>
</config>
</rule>
</monitor-rules>
cat-home/src/test/resources/config/test-rule-monitor.xml
0 → 100644
浏览文件 @
30de9a29
<monitor-rules>
<rule
id=
"decreasePercentage"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"decreaseValue"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescVal"
>
95
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"increasePercentage"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
</condition>
<condition>
<subcondition
type=
"AscPer"
>
49
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"increaseValue"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
</condition>
<condition>
<subcondition
type=
"AscVal"
>
49
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"absoluteMaxValue"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
</condition>
<condition>
<subcondition
type=
"MaxVal"
>
450
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"absoluteMinValue"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
</condition>
<condition>
<subcondition
type=
"MinVal"
>
51
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"conditionCombination"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
400
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescPer"
>
400
</subcondition>
<subcondition
type=
"DescVal"
>
900
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
100
</subcondition>
</condition>
</config>
</rule>
<rule
id=
"subconditionCombination"
>
<config
starttime=
"00:00"
endtime=
"24:00"
>
<condition>
<subcondition
type=
"DescPer"
>
400
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescPer"
>
400
</subcondition>
<subcondition
type=
"DescVal"
>
900
</subcondition>
</condition>
<condition>
<subcondition
type=
"DescPer"
>
40
</subcondition>
<subcondition
type=
"DescVal"
>
200
</subcondition>
<subcondition
type=
"MinVal"
>
10
</subcondition>
</condition>
</config>
</rule>
</monitor-rules>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录