未验证 提交 117afff3 编写于 作者: X xbkaishui 提交者: GitHub

Support Alarm to dingtalk (#5628)

* Add dingtalk webhook
Co-authored-by: wu-sheng's avatar吴晟 Wu Sheng <wu.sheng@foxmail.com>
上级 c9b6a78c
......@@ -219,6 +219,24 @@ wechatHooks:
- https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy_key
```
## Dingtalk Hook
To do this you need to follow the [Dingtalk Webhooks guide](https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq/uKPlK) and create new Webhooks.
For security issue, you can config optional secret for individual webhook url.
The alarm message will send through HTTP post by `application/json` content type if you configured Dingtalk Webhooks as following:
```yml
dingtalkHooks:
textTemplate: |-
{
"msgtype": "text",
"text": {
"content": "Apache SkyWalking Alarm: \n %s."
}
}
webhooks:
- url: https://oapi.dingtalk.com/robot/send?access_token=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),
......
......@@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
import org.apache.skywalking.oap.server.core.Const;
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.grpc.GRPCAlarmSetting;
......@@ -128,4 +129,9 @@ public class AlarmRulesWatcher extends ConfigChangeWatcher {
public WechatSettings getWechatSettings() {
return this.rules.getWecchats();
}
public DingtalkSettings getDingtalkSettings() {
return this.rules.getDingtalks();
}
}
......@@ -31,6 +31,7 @@ import org.apache.skywalking.oap.server.core.alarm.MetaInAlarm;
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.grpc.GRPCCallback;
import org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackhookCallback;
import org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatHookCallback;
......@@ -162,6 +163,7 @@ public class NotifyHandler implements MetricsNotify {
allCallbacks.add(new GRPCCallback(alarmRulesWatcher));
allCallbacks.add(new SlackhookCallback(alarmRulesWatcher));
allCallbacks.add(new WechatHookCallback(alarmRulesWatcher));
allCallbacks.add(new DingtalkHookCallback(alarmRulesWatcher));
core.start(allCallbacks);
}
}
......@@ -23,6 +23,7 @@ import java.util.List;
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.grpc.GRPCAlarmSetting;
import org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackSettings;
import org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatSettings;
......@@ -37,6 +38,7 @@ public class Rules {
private SlackSettings slacks;
private WechatSettings wecchats;
private List<CompositeAlarmRule> compositeRules;
private DingtalkSettings dingtalks;
public Rules() {
this.rules = new ArrayList<>();
......
......@@ -18,6 +18,12 @@
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.grpc.GRPCAlarmSetting;
import org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackSettings;
import org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatSettings;
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
......@@ -25,11 +31,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
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;
import org.yaml.snakeyaml.Yaml;
/**
* Rule Reader parses the given `alarm-settings.yml` config file, to the target {@link Rules}.
*/
......@@ -59,10 +60,12 @@ public class RulesReader {
readSlackConfig(rules);
readWechatConfig(rules);
readCompositeRuleConfig(rules);
readDingtalkConfig(rules);
}
return rules;
}
/**
* Read rule config into {@link AlarmRule}
*/
......@@ -203,4 +206,25 @@ public class RulesReader {
}
});
}
/**
* Read dingtalk hook config into {@link DingtalkSettings}
*/
private void readDingtalkConfig(Rules rules) {
Map dingtalkConfig = (Map) yamlData.get("dingtalkHooks");
if (dingtalkConfig != null) {
DingtalkSettings dingtalkSettings = new DingtalkSettings();
Object textTemplate = dingtalkConfig.getOrDefault("textTemplate", "");
dingtalkSettings.setTextTemplate((String) textTemplate);
List<Map<String, Object>> wechatWebhooks = (List<Map<String, Object>>) dingtalkConfig.get("webhooks");
if (wechatWebhooks != null) {
wechatWebhooks.forEach(wechatWebhook -> {
Object secret = wechatWebhook.getOrDefault("secret", "");
Object url = wechatWebhook.getOrDefault("url", "");
dingtalkSettings.getWebhooks().add(new DingtalkSettings.WebHookUrl((String) secret, (String) url));
});
}
rules.setDingtalks(dingtalkSettings);
}
}
}
/*
* 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.dingtalk;
import io.netty.handler.codec.http.HttpHeaderValues;
import lombok.extern.slf4j.Slf4j;
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.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.List;
/**
* Use SkyWalking alarm dingtalk webhook API.
*/
@Slf4j
public class DingtalkHookCallback 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 DingtalkHookCallback(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.getDingtalkSettings() == null || this.alarmRulesWatcher.getDingtalkSettings().getWebhooks().isEmpty()) {
return;
}
CloseableHttpClient httpClient = HttpClients.custom().build();
try {
DingtalkSettings dingtalkSettings = this.alarmRulesWatcher.getDingtalkSettings();
dingtalkSettings.getWebhooks().forEach(webHookUrl -> {
alarmMessages.forEach(alarmMessage -> {
String url = getUrl(webHookUrl);
String requestBody = String.format(
this.alarmRulesWatcher.getDingtalkSettings().getTextTemplate(), alarmMessage.getAlarmMessage()
);
sendAlarmMessage(httpClient, url, requestBody);
});
});
} finally {
try {
httpClient.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
/**
* Get webhook url, sign the url when secret is not empty.
*/
private String getUrl(DingtalkSettings.WebHookUrl webHookUrl) {
if (StringUtil.isEmpty(webHookUrl.getSecret())) {
return webHookUrl.getUrl();
}
return getSignUrl(webHookUrl);
}
/**
* Sign webhook url using secret and timestamp
*/
private String getSignUrl(DingtalkSettings.WebHookUrl webHookUrl) {
try {
Long timestamp = System.currentTimeMillis();
return String.format("%s&timestamp=%s&sign=%s", webHookUrl.getUrl(), timestamp, sign(timestamp, webHookUrl.getSecret()));
} catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
throw new RuntimeException(e);
}
}
/**
* Sign webhook url using HmacSHA256 algorithm
*/
private String sign(final Long timestamp, String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
return URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), StandardCharsets.UTF_8.name());
}
/**
* 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 dingtalk alarm to {} failure. Response code: {}, Response content: {}", url, statusLine.getStatusCode(),
EntityUtils.toString(httpResponse.getEntity()));
}
} catch (Throwable e) {
log.error("send dingtalk alarm to {} failure.", url, e);
}
}
}
/*
* 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.dingtalk;
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 DingtalkSettings {
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;
}
}
......@@ -82,6 +82,9 @@ public class AlarmRulesWatcherTest {
assertNotNull(alarmRulesWatcher.getGrpchookSetting());
assertEquals(9888, alarmRulesWatcher.getGrpchookSetting().getTargetPort());
assertEquals(2, alarmRulesWatcher.getRunningContext().size());
assertNotNull(alarmRulesWatcher.getDingtalkSettings());
assertNotNull(alarmRulesWatcher.getWechatSettings());
assertNotNull(alarmRulesWatcher.getSlackSettings());
}
@Test
......
......@@ -18,16 +18,27 @@
package org.apache.skywalking.oap.server.core.alarm.provider;
import java.util.List;
import org.apache.skywalking.oap.server.core.alarm.provider.dingtalk.DingtalkSettings;
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;
import org.junit.Assert;
import org.junit.Test;
public class AlarmRuleInitTest {
import java.util.List;
import static org.hamcrest.CoreMatchers.any;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
public class RulesReaderTest {
@Test
public void testInit() {
public void testReadRules() {
RulesReader reader = new RulesReader(this.getClass()
.getClassLoader()
.getResourceAsStream("alarm-settings.yml"));
.getClassLoader()
.getResourceAsStream("alarm-settings.yml"));
Rules rules = reader.readRules();
List<AlarmRule> ruleList = rules.getRules();
......@@ -46,8 +57,34 @@ public class AlarmRuleInitTest {
Assert.assertEquals(2, rulesWebhooks.size());
Assert.assertEquals("http://127.0.0.1/go-wechat/", rulesWebhooks.get(1));
GRPCAlarmSetting grpcAlarmSetting = rules.getGrpchookSetting();
assertNotNull(grpcAlarmSetting);
assertThat(grpcAlarmSetting.getTargetHost(), is("127.0.0.1"));
assertThat(grpcAlarmSetting.getTargetPort(), is(9888));
SlackSettings slackSettings = rules.getSlacks();
assertNotNull(slackSettings);
assertThat(slackSettings.getWebhooks().size(), is(1));
assertThat(slackSettings.getWebhooks().get(0), is("https://hooks.slack.com/services/x/y/zssss"));
assertThat(slackSettings.getTextTemplate(), any(String.class));
WechatSettings wechatSettings = rules.getWecchats();
assertNotNull(wechatSettings);
assertThat(wechatSettings.getWebhooks().size(), is(1));
assertThat(wechatSettings.getWebhooks().get(0), is("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy_key"));
assertThat(slackSettings.getTextTemplate(), any(String.class));
List<CompositeAlarmRule> compositeRules = rules.getCompositeRules();
Assert.assertEquals(1, compositeRules.size());
Assert.assertEquals("endpoint_percent_more_rule && endpoint_percent_rule", compositeRules.get(0).getExpression());
DingtalkSettings dingtalkSettings = rules.getDingtalks();
assertThat(dingtalkSettings.getTextTemplate(), any(String.class));
List<DingtalkSettings.WebHookUrl> webHookUrls = dingtalkSettings.getWebhooks();
assertThat(webHookUrls.size(), is(2));
assertThat(webHookUrls.get(0).getUrl(), is("https://oapi.dingtalk.com/robot/send?access_token=dummy_token"));
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());
}
}
/*
* 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.dingtalk;
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 DingtalkHookCallbackTest 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("/dingtalkhook");
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 testDingtalkWebhookWithoutSign() {
List<DingtalkSettings.WebHookUrl> webHooks = new ArrayList<>();
webHooks.add(new DingtalkSettings.WebHookUrl("", "http://127.0.0.1:" + port + "/dingtalkhook/receiveAlarm?token=dummy_token"));
Rules rules = new Rules();
String template = "{\"msgtype\":\"text\",\"text\":{\"content\":\"Skywaling alarm: %s\"}}";
rules.setDingtalks(DingtalkSettings.builder().webhooks(webHooks).textTemplate(template).build());
AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
DingtalkHookCallback dingtalkCallBack = new DingtalkHookCallback(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);
dingtalkCallBack.doAlarm(alarmMessages);
Assert.assertTrue(isSuccess);
}
@Test
public void testDingtalkWebhookWithSign() {
checkSign = true;
List<DingtalkSettings.WebHookUrl> webHooks = new ArrayList<>();
webHooks.add(new DingtalkSettings.WebHookUrl(secret, "http://127.0.0.1:" + port + "/dingtalkhook/receiveAlarm?token=dummy_token"));
Rules rules = new Rules();
String template = "{\"msgtype\":\"text\",\"text\":{\"content\":\"Skywaling alarm: %s\"}}";
rules.setDingtalks(DingtalkSettings.builder().webhooks(webHooks).textTemplate(template).build());
AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
DingtalkHookCallback dingtalkCallBack = new DingtalkHookCallback(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);
dingtalkCallBack.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("msgtype").getAsString();
if (checkSign) {
String timestamp = request.getParameter("timestamp");
String sign = request.getParameter("sign");
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() {
}
}
......@@ -71,3 +71,39 @@ gRPCHook:
target_host: 127.0.0.1
target_port: 9888
slackHooks:
textTemplate: |-
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":alarm_clock: *Apache Skywalking Alarm* \n **%s**."
}
}
webhooks:
- https://hooks.slack.com/services/x/y/zssss
wechatHooks:
textTemplate: |-
{
"msgtype": "text",
"text": {
"content": "Apache SkyWalking Alarm: \n %s."
}
}
webhooks:
- https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy_key
dingtalkHooks:
textTemplate: |-
{
"msgtype": "text",
"text": {
"content": "Apache SkyWalking Alarm: \n %s."
}
}
webhooks:
- url: https://oapi.dingtalk.com/robot/send?access_token=dummy_token
secret: dummysecret
- url: https://oapi.dingtalk.com/robot/send?access_token=dummy_token2
secret:
......@@ -69,3 +69,15 @@ wechatHooks:
}
webhooks:
# - https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy_key
dingtalkHooks:
textTemplate: |-
{
"msgtype": "text",
"text": {
"content": "Apache SkyWalking Alarm: \n %s."
}
}
webhooks:
# - url: https://oapi.dingtalk.com/robot/send?access_token=dummy_token
# secret: dummysecret
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册