Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
阿信在这里
SkyWalking
提交
4e43f227
S
SkyWalking
项目概览
阿信在这里
/
SkyWalking
与 Fork 源项目一致
Fork自
山不在高_有仙则灵 / SkyWalking
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
SkyWalking
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
4e43f227
编写于
1月 18, 2021
作者:
H
HendSame
提交者:
GitHub
1月 18, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Support Alarm to feishu (#6193)
上级
9021e679
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
529 addition
and
5 deletion
+529
-5
CHANGES.md
CHANGES.md
+1
-0
docs/en/setup/backend/backend-alarm.md
docs/en/setup/backend/backend-alarm.md
+19
-0
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcher.java
...ing/oap/server/core/alarm/provider/AlarmRulesWatcher.java
+5
-0
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandler.java
...walking/oap/server/core/alarm/provider/NotifyHandler.java
+2
-0
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
...ache/skywalking/oap/server/core/alarm/provider/Rules.java
+2
-0
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java
...kywalking/oap/server/core/alarm/provider/RulesReader.java
+28
-5
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallback.java
...server/core/alarm/provider/feishu/FeishuHookCallback.java
+173
-0
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuSettings.java
...oap/server/core/alarm/provider/feishu/FeishuSettings.java
+50
-0
oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReaderTest.java
...lking/oap/server/core/alarm/provider/RulesReaderTest.java
+10
-0
oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallbackTest.java
...er/core/alarm/provider/feishu/FeishuHookCallbackTest.java
+211
-0
oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml
...server-alarm-plugin/src/test/resources/alarm-settings.yml
+14
-0
oap-server/server-bootstrap/src/main/resources/alarm-settings.yml
...er/server-bootstrap/src/main/resources/alarm-settings.yml
+14
-0
未找到文件。
CHANGES.md
浏览文件 @
4e43f227
...
...
@@ -67,6 +67,7 @@ Release Notes.
*
Fix bug endpoint name grouping not work due to setting service name and endpoint name out of order.
*
Fix receiver analysis error count metrics
*
Log collecting and query implementation
*
Support Alarm to feishu
#### UI
*
Fix un-removed tags in trace query.
...
...
docs/en/setup/backend/backend-alarm.md
浏览文件 @
4e43f227
...
...
@@ -237,6 +237,25 @@ dingtalkHooks:
secret
:
dummysecret
```
## Feishu Hook
To do this you need to follow the
[
Feishu Webhooks guide
](
https://www.feishu.cn/hc/zh-cn/articles/360024984973
)
and create new Webhooks.
For security issue, you can config optional secret for individual webhook url.
if you want to at someone, you can config
`ats`
which is the feishu's user_id and separated by "," .
The alarm message will send through HTTP post by
`application/json`
content type if you configured Feishu Webhooks as following:
```
yml
feishuHooks
:
textTemplate
:
|-
{
"msg_type": "text",
"content": {
"text": "Apache SkyWalking Alarm: \n %s."
},
"ats":"feishu_user_id_1,feishu_user_id_2"
}
webhooks
:
-
url
:
https://open.feishu.cn/open-apis/bot/v2/hook/dummy_token
secret
:
dummysecret
```
## Update the settings dynamically
Since 6.5.0, the alarm settings can be updated dynamically at runtime by
[
Dynamic Configuration
](
dynamic-config.md
)
,
...
...
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcher.java
浏览文件 @
4e43f227
...
...
@@ -31,6 +31,7 @@ import org.apache.skywalking.oap.server.core.alarm.AlarmModule;
import
org.apache.skywalking.oap.server.core.alarm.provider.dingtalk.DingtalkSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.expression.Expression
;
import
org.apache.skywalking.oap.server.core.alarm.provider.expression.ExpressionContext
;
import
org.apache.skywalking.oap.server.core.alarm.provider.feishu.FeishuSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCAlarmSetting
;
import
org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatSettings
;
...
...
@@ -134,4 +135,8 @@ public class AlarmRulesWatcher extends ConfigChangeWatcher {
return
this
.
rules
.
getDingtalks
();
}
public
FeishuSettings
getFeishuSettings
()
{
return
this
.
rules
.
getFeishus
();
}
}
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandler.java
浏览文件 @
4e43f227
...
...
@@ -32,6 +32,7 @@ import org.apache.skywalking.oap.server.core.alarm.MetricsNotify;
import
org.apache.skywalking.oap.server.core.alarm.ServiceInstanceMetaInAlarm
;
import
org.apache.skywalking.oap.server.core.alarm.ServiceMetaInAlarm
;
import
org.apache.skywalking.oap.server.core.alarm.provider.dingtalk.DingtalkHookCallback
;
import
org.apache.skywalking.oap.server.core.alarm.provider.feishu.FeishuHookCallback
;
import
org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCCallback
;
import
org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackhookCallback
;
import
org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatHookCallback
;
...
...
@@ -164,6 +165,7 @@ public class NotifyHandler implements MetricsNotify {
allCallbacks
.
add
(
new
SlackhookCallback
(
alarmRulesWatcher
));
allCallbacks
.
add
(
new
WechatHookCallback
(
alarmRulesWatcher
));
allCallbacks
.
add
(
new
DingtalkHookCallback
(
alarmRulesWatcher
));
allCallbacks
.
add
(
new
FeishuHookCallback
(
alarmRulesWatcher
));
core
.
start
(
allCallbacks
);
}
}
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
浏览文件 @
4e43f227
...
...
@@ -24,6 +24,7 @@ import lombok.Getter;
import
lombok.Setter
;
import
lombok.ToString
;
import
org.apache.skywalking.oap.server.core.alarm.provider.dingtalk.DingtalkSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.feishu.FeishuSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCAlarmSetting
;
import
org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatSettings
;
...
...
@@ -39,6 +40,7 @@ public class Rules {
private
WechatSettings
wecchats
;
private
List
<
CompositeAlarmRule
>
compositeRules
;
private
DingtalkSettings
dingtalks
;
private
FeishuSettings
feishus
;
public
Rules
()
{
this
.
rules
=
new
ArrayList
<>();
...
...
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java
浏览文件 @
4e43f227
...
...
@@ -25,6 +25,7 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Objects
;
import
org.apache.skywalking.oap.server.core.alarm.provider.dingtalk.DingtalkSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.feishu.FeishuSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCAlarmSetting
;
import
org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatSettings
;
...
...
@@ -61,6 +62,7 @@ public class RulesReader {
readWechatConfig
(
rules
);
readCompositeRuleConfig
(
rules
);
readDingtalkConfig
(
rules
);
readFeishuConfig
(
rules
);
}
return
rules
;
}
...
...
@@ -90,9 +92,9 @@ public class RulesReader {
alarmRule
.
setIncludeNamesRegex
((
String
)
settings
.
getOrDefault
(
"include-names-regex"
,
""
));
alarmRule
.
setExcludeNamesRegex
((
String
)
settings
.
getOrDefault
(
"exclude-names-regex"
,
""
));
alarmRule
.
setIncludeLabels
(
(
ArrayList
)
settings
.
getOrDefault
(
"include-labels"
,
new
ArrayList
(
0
)));
(
ArrayList
)
settings
.
getOrDefault
(
"include-labels"
,
new
ArrayList
(
0
)));
alarmRule
.
setExcludeLabels
(
(
ArrayList
)
settings
.
getOrDefault
(
"exclude-labels"
,
new
ArrayList
(
0
)));
(
ArrayList
)
settings
.
getOrDefault
(
"exclude-labels"
,
new
ArrayList
(
0
)));
alarmRule
.
setIncludeLabelsRegex
((
String
)
settings
.
getOrDefault
(
"include-labels-regex"
,
""
));
alarmRule
.
setExcludeLabelsRegex
((
String
)
settings
.
getOrDefault
(
"exclude-labels-regex"
,
""
));
alarmRule
.
setThreshold
(
settings
.
get
(
"threshold"
).
toString
());
...
...
@@ -103,8 +105,8 @@ public class RulesReader {
alarmRule
.
setSilencePeriod
((
Integer
)
settings
.
getOrDefault
(
"silence-period"
,
alarmRule
.
getPeriod
()));
alarmRule
.
setOnlyAsCondition
((
Boolean
)
settings
.
getOrDefault
(
"only-as-condition"
,
false
));
alarmRule
.
setMessage
(
(
String
)
settings
.
getOrDefault
(
"message"
,
"Alarm caused by Rule "
+
alarmRule
.
getAlarmRuleName
()));
(
String
)
settings
.
getOrDefault
(
"message"
,
"Alarm caused by Rule "
+
alarmRule
.
getAlarmRuleName
()));
rules
.
getRules
().
add
(
alarmRule
);
}
...
...
@@ -200,7 +202,7 @@ public class RulesReader {
}
compositeAlarmRule
.
setExpression
(
expression
);
compositeAlarmRule
.
setMessage
(
(
String
)
settings
.
getOrDefault
(
"message"
,
"Alarm caused by Rule "
+
ruleName
));
(
String
)
settings
.
getOrDefault
(
"message"
,
"Alarm caused by Rule "
+
ruleName
));
rules
.
getCompositeRules
().
add
(
compositeAlarmRule
);
}
});
...
...
@@ -226,4 +228,25 @@ public class RulesReader {
rules
.
setDingtalks
(
dingtalkSettings
);
}
}
/**
* Read feishu hook config into {@link FeishuSettings}
*/
private
void
readFeishuConfig
(
Rules
rules
)
{
Map
feishuConfig
=
(
Map
)
yamlData
.
get
(
"feishuHooks"
);
if
(
feishuConfig
!=
null
)
{
FeishuSettings
feishuSettings
=
new
FeishuSettings
();
Object
textTemplate
=
feishuConfig
.
getOrDefault
(
"textTemplate"
,
""
);
feishuSettings
.
setTextTemplate
((
String
)
textTemplate
);
List
<
Map
<
String
,
Object
>>
wechatWebhooks
=
(
List
<
Map
<
String
,
Object
>>)
feishuConfig
.
get
(
"webhooks"
);
if
(
wechatWebhooks
!=
null
)
{
wechatWebhooks
.
forEach
(
wechatWebhook
->
{
Object
secret
=
wechatWebhook
.
getOrDefault
(
"secret"
,
""
);
Object
url
=
wechatWebhook
.
getOrDefault
(
"url"
,
""
);
feishuSettings
.
getWebhooks
().
add
(
new
FeishuSettings
.
WebHookUrl
((
String
)
secret
,
(
String
)
url
));
});
}
rules
.
setFeishus
(
feishuSettings
);
}
}
}
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallback.java
0 → 100644
浏览文件 @
4e43f227
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package
org.apache.skywalking.oap.server.core.alarm.provider.feishu
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonObject
;
import
io.netty.handler.codec.http.HttpHeaderValues
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.http.HttpHeaders
;
import
org.apache.http.HttpStatus
;
import
org.apache.http.StatusLine
;
import
org.apache.http.client.config.RequestConfig
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.entity.ContentType
;
import
org.apache.http.entity.StringEntity
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.impl.client.HttpClients
;
import
org.apache.http.util.EntityUtils
;
import
org.apache.skywalking.apm.util.StringUtil
;
import
org.apache.skywalking.oap.server.core.alarm.AlarmCallback
;
import
org.apache.skywalking.oap.server.core.alarm.AlarmMessage
;
import
org.apache.skywalking.oap.server.core.alarm.provider.AlarmRulesWatcher
;
import
javax.crypto.Mac
;
import
javax.crypto.spec.SecretKeySpec
;
import
java.io.IOException
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
* Use SkyWalking alarm feishu webhook API.
*/
@Slf4j
public
class
FeishuHookCallback
implements
AlarmCallback
{
private
static
final
int
HTTP_CONNECT_TIMEOUT
=
1000
;
private
static
final
int
HTTP_CONNECTION_REQUEST_TIMEOUT
=
1000
;
private
static
final
int
HTTP_SOCKET_TIMEOUT
=
10000
;
private
AlarmRulesWatcher
alarmRulesWatcher
;
private
RequestConfig
requestConfig
;
public
FeishuHookCallback
(
final
AlarmRulesWatcher
alarmRulesWatcher
)
{
this
.
alarmRulesWatcher
=
alarmRulesWatcher
;
this
.
requestConfig
=
RequestConfig
.
custom
()
.
setConnectTimeout
(
HTTP_CONNECT_TIMEOUT
)
.
setConnectionRequestTimeout
(
HTTP_CONNECTION_REQUEST_TIMEOUT
)
.
setSocketTimeout
(
HTTP_SOCKET_TIMEOUT
)
.
build
();
}
/**
* Send alarm message if the settings not empty
*/
@Override
public
void
doAlarm
(
List
<
AlarmMessage
>
alarmMessages
)
{
if
(
this
.
alarmRulesWatcher
.
getFeishuSettings
()
==
null
||
this
.
alarmRulesWatcher
.
getFeishuSettings
().
getWebhooks
().
isEmpty
())
{
return
;
}
CloseableHttpClient
httpClient
=
HttpClients
.
custom
().
build
();
try
{
FeishuSettings
feishuSettings
=
this
.
alarmRulesWatcher
.
getFeishuSettings
();
feishuSettings
.
getWebhooks
().
forEach
(
webHookUrl
->
{
alarmMessages
.
forEach
(
alarmMessage
->
{
String
requestBody
=
getRequestBody
(
webHookUrl
,
alarmMessage
);
sendAlarmMessage
(
httpClient
,
webHookUrl
.
getUrl
(),
requestBody
);
});
});
}
finally
{
try
{
httpClient
.
close
();
}
catch
(
IOException
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
}
}
}
/**
* deal requestBody,if has sign set the sign
*/
private
String
getRequestBody
(
FeishuSettings
.
WebHookUrl
webHookUrl
,
AlarmMessage
alarmMessage
)
{
String
requestBody
=
String
.
format
(
this
.
alarmRulesWatcher
.
getFeishuSettings
().
getTextTemplate
(),
alarmMessage
.
getAlarmMessage
()
);
Gson
gson
=
new
Gson
();
JsonObject
jsonObject
=
gson
.
fromJson
(
requestBody
,
JsonObject
.
class
);
Map
<
String
,
Object
>
content
=
buildContent
(
jsonObject
);
if
(!
StringUtil
.
isBlank
(
webHookUrl
.
getSecret
()))
{
Long
timestamp
=
System
.
currentTimeMillis
()
/
1000
;
content
.
put
(
"timestamp"
,
timestamp
);
try
{
content
.
put
(
"sign"
,
sign
(
timestamp
,
webHookUrl
.
getSecret
()));
}
catch
(
NoSuchAlgorithmException
|
InvalidKeyException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
return
gson
.
toJson
(
content
);
}
/**
* build content,if has ats someone set the ats
*/
private
Map
<
String
,
Object
>
buildContent
(
JsonObject
jsonObject
)
{
Map
<
String
,
Object
>
content
=
new
HashMap
<>();
content
.
put
(
"msg_type"
,
jsonObject
.
get
(
"msg_type"
).
getAsString
());
if
(
jsonObject
.
get
(
"ats"
)
!=
null
)
{
String
ats
=
jsonObject
.
get
(
"ats"
).
getAsString
();
String
text
=
jsonObject
.
get
(
"content"
).
getAsJsonObject
().
get
(
"text"
).
getAsString
();
List
<
String
>
collect
=
Arrays
.
stream
(
ats
.
split
(
","
))
.
map
(
String:
:
trim
).
collect
(
Collectors
.
toList
());
for
(
String
userId
:
collect
)
{
text
+=
"<at user_id=\""
+
userId
+
"\"></at>"
;
}
jsonObject
.
get
(
"content"
).
getAsJsonObject
().
addProperty
(
"text"
,
text
);
}
content
.
put
(
"content"
,
jsonObject
.
get
(
"content"
).
getAsJsonObject
());
return
content
;
}
/**
* Sign webhook url using HmacSHA256 algorithm
*/
private
String
sign
(
final
Long
timestamp
,
String
secret
)
throws
NoSuchAlgorithmException
,
InvalidKeyException
{
String
stringToSign
=
timestamp
+
"\n"
+
secret
;
Mac
mac
=
Mac
.
getInstance
(
"HmacSHA256"
);
mac
.
init
(
new
SecretKeySpec
(
stringToSign
.
getBytes
(),
"HmacSHA256"
));
byte
[]
signData
=
mac
.
doFinal
();
return
Base64
.
encodeBase64String
(
signData
);
}
/**
* Send alarm message to remote endpoint
*/
private
void
sendAlarmMessage
(
CloseableHttpClient
httpClient
,
String
url
,
String
requestBody
)
{
try
{
HttpPost
post
=
new
HttpPost
(
url
);
post
.
setConfig
(
requestConfig
);
post
.
setHeader
(
HttpHeaders
.
ACCEPT
,
HttpHeaderValues
.
APPLICATION_JSON
.
toString
());
post
.
setHeader
(
HttpHeaders
.
CONTENT_TYPE
,
HttpHeaderValues
.
APPLICATION_JSON
.
toString
());
StringEntity
entity
=
new
StringEntity
(
requestBody
,
ContentType
.
APPLICATION_JSON
);
post
.
setEntity
(
entity
);
CloseableHttpResponse
httpResponse
=
httpClient
.
execute
(
post
);
StatusLine
statusLine
=
httpResponse
.
getStatusLine
();
if
(
statusLine
!=
null
&&
statusLine
.
getStatusCode
()
!=
HttpStatus
.
SC_OK
)
{
log
.
error
(
"send feishu alarm to {} failure. Response code: {}, Response content: {}"
,
url
,
statusLine
.
getStatusCode
(),
EntityUtils
.
toString
(
httpResponse
.
getEntity
()));
}
}
catch
(
Throwable
e
)
{
log
.
error
(
"send feishu alarm to {} failure."
,
url
,
e
);
}
}
}
oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuSettings.java
0 → 100644
浏览文件 @
4e43f227
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package
org.apache.skywalking.oap.server.core.alarm.provider.feishu
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Getter
;
import
lombok.NoArgsConstructor
;
import
lombok.Setter
;
import
lombok.ToString
;
import
java.util.ArrayList
;
import
java.util.List
;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@ToString
public
class
FeishuSettings
{
private
String
textTemplate
;
@Builder
.
Default
private
List
<
WebHookUrl
>
webhooks
=
new
ArrayList
<>();
@AllArgsConstructor
@Setter
@Getter
@ToString
public
static
class
WebHookUrl
{
private
final
String
secret
;
private
final
String
url
;
}
}
oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReaderTest.java
浏览文件 @
4e43f227
...
...
@@ -19,6 +19,7 @@
package
org.apache.skywalking.oap.server.core.alarm.provider
;
import
org.apache.skywalking.oap.server.core.alarm.provider.dingtalk.DingtalkSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.feishu.FeishuSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCAlarmSetting
;
import
org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackSettings
;
import
org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatSettings
;
...
...
@@ -86,5 +87,14 @@ public class RulesReaderTest {
assertThat
(
webHookUrls
.
get
(
0
).
getSecret
(),
is
(
"dummysecret"
));
assertThat
(
webHookUrls
.
get
(
1
).
getUrl
(),
is
(
"https://oapi.dingtalk.com/robot/send?access_token=dummy_token2"
));
assertNull
(
webHookUrls
.
get
(
1
).
getSecret
());
FeishuSettings
feishuSettings
=
rules
.
getFeishus
();
assertThat
(
feishuSettings
.
getTextTemplate
(),
any
(
String
.
class
));
List
<
FeishuSettings
.
WebHookUrl
>
feishuSettingsWebhooks
=
feishuSettings
.
getWebhooks
();
assertThat
(
feishuSettingsWebhooks
.
size
(),
is
(
2
));
assertThat
(
feishuSettingsWebhooks
.
get
(
0
).
getUrl
(),
is
(
"https://open.feishu.cn/open-apis/bot/v2/hook/dummy_token"
));
assertThat
(
feishuSettingsWebhooks
.
get
(
0
).
getSecret
(),
is
(
"dummysecret"
));
assertThat
(
feishuSettingsWebhooks
.
get
(
1
).
getUrl
(),
is
(
"https://open.feishu.cn/open-apis/bot/v2/hook/dummy_token2"
));
assertNull
(
feishuSettingsWebhooks
.
get
(
1
).
getSecret
());
}
}
oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallbackTest.java
0 → 100644
浏览文件 @
4e43f227
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package
org.apache.skywalking.oap.server.core.alarm.provider.feishu
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonObject
;
import
org.apache.skywalking.apm.util.StringUtil
;
import
org.apache.skywalking.oap.server.core.alarm.AlarmMessage
;
import
org.apache.skywalking.oap.server.core.alarm.provider.AlarmRulesWatcher
;
import
org.apache.skywalking.oap.server.core.alarm.provider.Rules
;
import
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine
;
import
org.eclipse.jetty.server.Server
;
import
org.eclipse.jetty.servlet.ServletContextHandler
;
import
org.eclipse.jetty.servlet.ServletHolder
;
import
org.junit.After
;
import
org.junit.Assert
;
import
org.junit.Before
;
import
org.junit.Test
;
import
javax.servlet.Servlet
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.net.InetSocketAddress
;
import
java.util.ArrayList
;
import
java.util.List
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
class
FeishuHookCallbackTest
implements
Servlet
{
private
Server
server
;
private
int
port
;
private
volatile
boolean
isSuccess
=
false
;
private
int
count
;
private
volatile
boolean
checkSign
=
false
;
private
final
String
secret
=
"dummy-secret"
;
@Before
public
void
init
()
throws
Exception
{
server
=
new
Server
(
new
InetSocketAddress
(
"127.0.0.1"
,
0
));
ServletContextHandler
servletContextHandler
=
new
ServletContextHandler
(
ServletContextHandler
.
NO_SESSIONS
);
servletContextHandler
.
setContextPath
(
"/feishuhook"
);
server
.
setHandler
(
servletContextHandler
);
ServletHolder
servletHolder
=
new
ServletHolder
();
servletHolder
.
setServlet
(
this
);
servletContextHandler
.
addServlet
(
servletHolder
,
"/receiveAlarm"
);
server
.
start
();
port
=
server
.
getURI
().
getPort
();
assertTrue
(
port
>
0
);
}
@Test
public
void
testFeishuWebhookWithoutSign
()
{
List
<
FeishuSettings
.
WebHookUrl
>
webHooks
=
new
ArrayList
<>();
webHooks
.
add
(
new
FeishuSettings
.
WebHookUrl
(
""
,
"http://127.0.0.1:"
+
port
+
"/feishuhook/receiveAlarm?token=dummy_token"
));
Rules
rules
=
new
Rules
();
String
template
=
"{\"msg_type\":\"text\",\"content\":{\"text\":\"Skywaling alarm: %s\"}}"
;
rules
.
setFeishus
(
FeishuSettings
.
builder
().
webhooks
(
webHooks
).
textTemplate
(
template
).
build
());
AlarmRulesWatcher
alarmRulesWatcher
=
new
AlarmRulesWatcher
(
rules
,
null
);
FeishuHookCallback
feishuHookCallback
=
new
FeishuHookCallback
(
alarmRulesWatcher
);
List
<
AlarmMessage
>
alarmMessages
=
new
ArrayList
<>(
2
);
AlarmMessage
alarmMessage
=
new
AlarmMessage
();
alarmMessage
.
setScopeId
(
DefaultScopeDefine
.
ALL
);
alarmMessage
.
setRuleName
(
"service_resp_time_rule"
);
alarmMessage
.
setAlarmMessage
(
"alarmMessage with [DefaultScopeDefine.All]"
);
alarmMessages
.
add
(
alarmMessage
);
AlarmMessage
anotherAlarmMessage
=
new
AlarmMessage
();
anotherAlarmMessage
.
setRuleName
(
"service_resp_time_rule_2"
);
anotherAlarmMessage
.
setScopeId
(
DefaultScopeDefine
.
ENDPOINT
);
anotherAlarmMessage
.
setAlarmMessage
(
"anotherAlarmMessage with [DefaultScopeDefine.Endpoint]"
);
alarmMessages
.
add
(
anotherAlarmMessage
);
feishuHookCallback
.
doAlarm
(
alarmMessages
);
Assert
.
assertTrue
(
isSuccess
);
}
@Test
public
void
testFeishuWebhookWithSign
()
{
checkSign
=
true
;
List
<
FeishuSettings
.
WebHookUrl
>
webHooks
=
new
ArrayList
<>();
webHooks
.
add
(
new
FeishuSettings
.
WebHookUrl
(
secret
,
"http://127.0.0.1:"
+
port
+
"/feishuhook/receiveAlarm?token=dummy_token"
));
Rules
rules
=
new
Rules
();
String
template
=
"{\"msg_type\":\"text\",\"content\":{\"text\":\"Skywaling alarm: %s\"}}"
;
rules
.
setFeishus
(
FeishuSettings
.
builder
().
webhooks
(
webHooks
).
textTemplate
(
template
).
build
());
AlarmRulesWatcher
alarmRulesWatcher
=
new
AlarmRulesWatcher
(
rules
,
null
);
FeishuHookCallback
feishuHookCallback
=
new
FeishuHookCallback
(
alarmRulesWatcher
);
List
<
AlarmMessage
>
alarmMessages
=
new
ArrayList
<>(
2
);
AlarmMessage
alarmMessage
=
new
AlarmMessage
();
alarmMessage
.
setScopeId
(
DefaultScopeDefine
.
ALL
);
alarmMessage
.
setRuleName
(
"service_resp_time_rule"
);
alarmMessage
.
setAlarmMessage
(
"alarmMessage with [DefaultScopeDefine.All]"
);
alarmMessages
.
add
(
alarmMessage
);
AlarmMessage
anotherAlarmMessage
=
new
AlarmMessage
();
anotherAlarmMessage
.
setRuleName
(
"service_resp_time_rule_2"
);
anotherAlarmMessage
.
setScopeId
(
DefaultScopeDefine
.
ENDPOINT
);
anotherAlarmMessage
.
setAlarmMessage
(
"anotherAlarmMessage with [DefaultScopeDefine.Endpoint]"
);
alarmMessages
.
add
(
anotherAlarmMessage
);
feishuHookCallback
.
doAlarm
(
alarmMessages
);
Assert
.
assertTrue
(
isSuccess
);
}
@Test
public
void
testFeishuWebhookWithSignAndAt
()
{
checkSign
=
true
;
List
<
FeishuSettings
.
WebHookUrl
>
webHooks
=
new
ArrayList
<>();
webHooks
.
add
(
new
FeishuSettings
.
WebHookUrl
(
secret
,
"http://127.0.0.1:"
+
port
+
"/feishuhook/receiveAlarm?token=dummy_token"
));
Rules
rules
=
new
Rules
();
String
template
=
"{\"msg_type\":\"text\",\"content\":{\"text\":\"Skywaling alarm: %s\"},\"ats\":\"123\"}"
;
rules
.
setFeishus
(
FeishuSettings
.
builder
().
webhooks
(
webHooks
).
textTemplate
(
template
).
build
());
AlarmRulesWatcher
alarmRulesWatcher
=
new
AlarmRulesWatcher
(
rules
,
null
);
FeishuHookCallback
feishuHookCallback
=
new
FeishuHookCallback
(
alarmRulesWatcher
);
List
<
AlarmMessage
>
alarmMessages
=
new
ArrayList
<>(
2
);
AlarmMessage
alarmMessage
=
new
AlarmMessage
();
alarmMessage
.
setScopeId
(
DefaultScopeDefine
.
ALL
);
alarmMessage
.
setRuleName
(
"service_resp_time_rule"
);
alarmMessage
.
setAlarmMessage
(
"alarmMessage with [DefaultScopeDefine.All]"
);
alarmMessages
.
add
(
alarmMessage
);
AlarmMessage
anotherAlarmMessage
=
new
AlarmMessage
();
anotherAlarmMessage
.
setRuleName
(
"service_resp_time_rule_2"
);
anotherAlarmMessage
.
setScopeId
(
DefaultScopeDefine
.
ENDPOINT
);
anotherAlarmMessage
.
setAlarmMessage
(
"anotherAlarmMessage with [DefaultScopeDefine.Endpoint]"
);
alarmMessages
.
add
(
anotherAlarmMessage
);
feishuHookCallback
.
doAlarm
(
alarmMessages
);
Assert
.
assertTrue
(
isSuccess
);
}
@After
public
void
stop
()
throws
Exception
{
server
.
stop
();
}
@Override
public
void
init
(
ServletConfig
servletConfig
)
throws
ServletException
{
}
@Override
public
ServletConfig
getServletConfig
()
{
return
null
;
}
@Override
public
void
service
(
ServletRequest
request
,
ServletResponse
response
)
throws
ServletException
,
IOException
{
HttpServletRequest
httpServletRequest
=
(
HttpServletRequest
)
request
;
if
(
httpServletRequest
.
getContentType
().
equals
(
"application/json"
))
{
InputStream
inputStream
=
request
.
getInputStream
();
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
byte
[]
buffer
=
new
byte
[
2048
];
int
readCntOnce
;
while
((
readCntOnce
=
inputStream
.
read
(
buffer
))
>=
0
)
{
out
.
write
(
buffer
,
0
,
readCntOnce
);
}
JsonObject
jsonObject
=
new
Gson
().
fromJson
(
new
String
(
out
.
toByteArray
()),
JsonObject
.
class
);
String
type
=
jsonObject
.
get
(
"msg_type"
).
getAsString
();
if
(
checkSign
)
{
String
timestamp
=
jsonObject
.
get
(
"timestamp"
).
getAsString
();
String
sign
=
jsonObject
.
get
(
"sign"
).
getAsString
();
if
(
StringUtil
.
isEmpty
(
timestamp
)
||
StringUtil
.
isEmpty
(
sign
))
{
((
HttpServletResponse
)
response
).
setStatus
(
500
);
return
;
}
}
if
(
type
.
equalsIgnoreCase
(
"text"
))
{
((
HttpServletResponse
)
response
).
setStatus
(
200
);
count
=
count
+
1
;
if
(
count
==
2
)
{
isSuccess
=
true
;
}
return
;
}
((
HttpServletResponse
)
response
).
setStatus
(
500
);
}
}
@Override
public
String
getServletInfo
()
{
return
null
;
}
@Override
public
void
destroy
()
{
}
}
oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml
浏览文件 @
4e43f227
...
...
@@ -107,3 +107,17 @@ dingtalkHooks:
secret
:
dummysecret
-
url
:
https://oapi.dingtalk.com/robot/send?access_token=dummy_token2
secret
:
feishuHooks
:
textTemplate
:
|-
{
"msg_type": "text",
"content": {
"text": "Apache SkyWalking Alarm: \n %s."
}
}
webhooks
:
-
url
:
https://open.feishu.cn/open-apis/bot/v2/hook/dummy_token
secret
:
dummysecret
-
url
:
https://open.feishu.cn/open-apis/bot/v2/hook/dummy_token2
secret
:
oap-server/server-bootstrap/src/main/resources/alarm-settings.yml
浏览文件 @
4e43f227
...
...
@@ -81,3 +81,17 @@ dingtalkHooks:
webhooks
:
# - url: https://oapi.dingtalk.com/robot/send?access_token=dummy_token
# secret: dummysecret
feishuHooks
:
textTemplate
:
|-
{
"msg_type": "text",
# at someone with feishu_user_ids
# "ats": "feishu_user_id_1,feishu_user_id_2",
"content": {
"text": "Apache SkyWalking Alarm: \n %s."
}
}
webhooks
:
# - url: https://open.feishu.cn/open-apis/bot/v2/hook/dummy_token
# secret: dummysecret
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录