diff --git a/collector/pom.xml b/collector/pom.xml
index 5b1eacb..63b99cc 100644
--- a/collector/pom.xml
+++ b/collector/pom.xml
@@ -51,6 +51,11 @@
httpclient
4.5.13
+
+ commons-io
+ commons-io
+ 2.0.1
+
commons-net
diff --git a/collector/src/main/java/com/usthe/collector/collect/common/http/HttpUtils.java b/collector/src/main/java/com/usthe/collector/collect/common/http/HttpUtils.java
new file mode 100644
index 0000000..d552847
--- /dev/null
+++ b/collector/src/main/java/com/usthe/collector/collect/common/http/HttpUtils.java
@@ -0,0 +1,473 @@
+package com.usthe.collector.collect.common.http;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.*;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.*;
+import org.apache.http.client.utils.URIBuilder;
+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.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Http各种请求方法的实现
+ *
+ * @author 花城
+ * @version 1.0
+ * @date 2022/2/21 7:16 下午
+ * @Description
+ */
+@Slf4j
+public class HttpUtils {
+ private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
+
+ private CloseableHttpClient httpClient;
+ //连接超时时间为30s
+ private int connectionTimeout = 30000;
+ //读取超时时间为300s
+ private int socketTimeout = 300000;
+ private int MAX_TOTAL = 3000;
+ //单路由的最大并发连接数
+ private int MAX_PER_ROUTE = 1000;
+ //设置从链接池中获取连接时间为无限大
+ private int CONNECTION_REQUEST_TIMEOUT = 0;
+
+ private static ObjectMapper objectMapper;
+
+ static {
+ objectMapper = new ObjectMapper();
+ // asr返回格式为命名用下划线格式,java为驼峰式,json需要转换
+// objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
+ objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
+
+ objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
+ objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+ objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+
+ }
+
+ public void init() {
+ RequestConfig config = RequestConfig.custom().setConnectTimeout(connectionTimeout).
+ setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT).setSocketTimeout(socketTimeout).build();
+ PoolingHttpClientConnectionManager pccm = new PoolingHttpClientConnectionManager();
+ pccm.setMaxTotal(MAX_TOTAL);
+ pccm.setDefaultMaxPerRoute(MAX_PER_ROUTE);
+ httpClient = HttpClients.custom().setConnectionManager(pccm).setDefaultRequestConfig(config).build();
+ }
+
+ public HttpResult doGet(String url, Map params) {
+ try {
+ URIBuilder uriBuilder = new URIBuilder(url);
+ for (Map.Entry entry : params.entrySet()) {
+ uriBuilder.addParameter(entry.getKey(), entry.getValue());
+ }
+ HttpGet httpget = new HttpGet(uriBuilder.build());
+ httpget.addHeader("contentEncoding", "UTF-8");
+ return doExecuteHttpRqeuestBase(httpget);
+ } catch (Exception e) {
+ LOGGER.error("Error when doGet : " + url, e);
+ return failHttp(e.getMessage());
+ }
+ }
+
+ public HttpResult doGetWithHeaders(String url, Map params, Map headers) {
+ try {
+ URIBuilder uriBuilder = new URIBuilder(url);
+ params.forEach(uriBuilder::addParameter);
+ HttpGet httpget = new HttpGet(uriBuilder.build());
+ httpget.addHeader("contentEncoding", "UTF-8");
+ headers.forEach(httpget::addHeader);
+ return doExecuteHttpRqeuestBase(httpget);
+ } catch (Exception e) {
+ LOGGER.error("Error when doGet : " + url, e);
+ return failHttp(e.getMessage());
+ }
+ }
+
+ public HttpResult doPutWithHeaders(String url, Map params, Map headers) {
+ try {
+ URIBuilder uriBuilder = new URIBuilder(url);
+ params.forEach(uriBuilder::addParameter);
+ HttpPut httpget = new HttpPut(uriBuilder.build());
+ httpget.addHeader("contentEncoding", "UTF-8");
+ headers.forEach(httpget::addHeader);
+ return doExecuteHttpRqeuestBase(httpget);
+ } catch (Exception e) {
+ LOGGER.error("Error when doPut : " + url, e);
+ return failHttp(e.getMessage());
+ }
+ }
+
+ public HttpResult doPost(String url, Map formParams) {
+ // 创建httppost
+ HttpPost httpPost = new HttpPost(url);
+ // 设置参数
+ RequestConfig.Builder customReqConf = RequestConfig.custom();
+ customReqConf.setConnectTimeout(connectionTimeout);
+ customReqConf.setSocketTimeout(socketTimeout);
+ httpPost.setConfig(customReqConf.build());
+
+ List formparams = new ArrayList();
+ for (Map.Entry entry : formParams.entrySet()) {
+ formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+ }
+ UrlEncodedFormEntity entity = null;
+ try {
+ entity = new UrlEncodedFormEntity(formparams, "UTF-8");
+ entity.setChunked(true);
+ } catch (UnsupportedEncodingException e) {
+ LOGGER.error("UrlEncode error : " + url, e);
+ }
+ httpPost.setEntity(entity);
+ return doExecuteHttpRqeuestBase(httpPost);
+ }
+
+ public HttpResult doPostWithHeader(String url, String bodyJsonString, Map headers) {
+ // 创建httppost
+ HttpPost httpPost = new HttpPost(url);
+
+ // 设置参数
+ RequestConfig.Builder customReqConf = RequestConfig.custom();
+ customReqConf.setConnectTimeout(connectionTimeout);
+ customReqConf.setSocketTimeout(socketTimeout);
+ httpPost.setConfig(customReqConf.build());
+ headers.forEach(httpPost::addHeader);
+ StringEntity entity = new StringEntity(bodyJsonString, "UTF-8");//解决中文乱码问题
+ entity.setContentEncoding("UTF-8");
+ entity.setContentType(ContentType.APPLICATION_JSON.toString());
+ httpPost.setEntity(entity);
+ return doExecuteHttpRqeuestBase(httpPost);
+ }
+
+ public HttpResponse doPostWithOriginalResponse(String url, List nvpList, String charset) {
+ HttpResponse response = null;
+ try{
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.setHeader(HttpHeaders.CONNECTION, "close");
+ httpPost.setEntity(new UrlEncodedFormEntity(nvpList,charset));
+ response = httpClient.execute(httpPost);
+ }catch (Exception e){
+ LOGGER.error("doPostWithOriginalResponse error : ", e);
+ }
+ return response;
+ }
+
+ public HttpResult doPost(String url, String bodyJsonString) {
+ // 创建httppost
+ HttpPost httpPost = new HttpPost(url);
+
+ // 设置参数
+ RequestConfig.Builder customReqConf = RequestConfig.custom();
+ customReqConf.setConnectTimeout(connectionTimeout);
+ customReqConf.setSocketTimeout(socketTimeout);
+ httpPost.setConfig(customReqConf.build());
+
+ StringEntity entity = new StringEntity(bodyJsonString, "UTF-8");//解决中文乱码问题
+ entity.setContentEncoding("UTF-8");
+ entity.setContentType(ContentType.APPLICATION_JSON.toString());
+ httpPost.setEntity(entity);
+ return doExecuteHttpRqeuestBase(httpPost);
+ }
+
+ public HttpResult doPostWithEntity(String url, HttpEntity entity) {
+ // 创建httppost
+ HttpPost httpPost = new HttpPost(url);
+
+ // 设置参数
+ RequestConfig.Builder customReqConf = RequestConfig.custom();
+ customReqConf.setConnectTimeout(connectionTimeout);
+ customReqConf.setSocketTimeout(socketTimeout);
+ httpPost.setConfig(customReqConf.build());
+
+ httpPost.setEntity(entity);
+ return doExecuteHttpRqeuestBase(httpPost);
+ }
+
+ public HttpResult doDeleteWithHeaders(String url, Map params, Map headers) {
+ try {
+ URIBuilder uriBuilder = new URIBuilder(url);
+ params.forEach(uriBuilder::addParameter);
+ HttpDelete httpDelete = new HttpDelete(uriBuilder.build());
+ httpDelete.addHeader("contentEncoding", "UTF-8");
+ headers.forEach(httpDelete::addHeader);
+ return doExecuteHttpRqeuestBase(httpDelete);
+
+ } catch (Exception e) {
+ LOGGER.error("Error when doDelete : " + url, e);
+ return failHttp(e.getMessage());
+ }
+ }
+
+ private HttpResult doExecuteHttpRqeuestBase(HttpRequestBase httpRequestBase) {
+ try {
+ HttpResultResponseHandler sph = new HttpResultResponseHandler();
+ return httpClient.execute(httpRequestBase, sph);
+ } catch (Exception e) {
+ LOGGER.error("Error when " + httpRequestBase.getMethod() + " : " + httpRequestBase.getURI(), e);
+ return failHttp(e.getMessage());
+ } finally {
+ if (httpRequestBase != null) {
+ httpRequestBase.abort();
+ }
+ }
+ }
+
+ /**
+ * 请求体为json格式对象
+ *
+ * @param path
+ * @param form
+ * @return
+ */
+ public static HttpPost newJsonBodyPostRequest(String path, Map form) {
+ HttpPost post = new HttpPost(path);
+ String json = toJsonString(form);
+ HttpEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
+ post.setEntity(entity);
+ post.addHeader(HttpHeaders.ACCEPT, CONTENT_TYPE);
+ post.addHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE);
+ return post;
+ }
+ static final String CONTENT_TYPE = "application/json";
+
+
+ public static String toJsonString(Object val) {
+ try {
+ byte[] bytes = objectMapper.writeValueAsBytes(val);
+ return new String(bytes, Charsets.UTF_8);
+ } catch (IOException e) {
+ throw new RuntimeException("toJsonString error", e);
+ }
+ }
+
+ public static T parseHttpResponseObject(String json, TypeReference type) throws IOException {
+ if (Strings.isNullOrEmpty(json)) {
+ return null;
+ }
+ return objectMapper.readValue(json, type);
+ }
+
+ public static String toRequestString(HttpRequestBase r) {
+ if (r == null) {
+ return "null";
+ }
+ return r.getMethod() + " " + r.getURI();
+ }
+
+ private class HttpResultResponseHandler implements ResponseHandler {
+ @Override
+ public HttpResult handleResponse(HttpResponse response) throws IOException {
+ HttpResult result = new HttpResult();
+ HttpEntity entity = response.getEntity();
+ Header[] headers = response.getAllHeaders();
+ if (isNotEmpty(headers)) {
+ HashMap headerMap = new HashMap();
+ for (Header h : headers) {
+ headerMap.put(h.getName(), h.getValue());
+ }
+ result.setHeader(headerMap);
+ }
+
+ InputStream i = entity.getContent();
+ String res = IOUtils.toString(new InputStreamReader(i, "UTF-8"));
+ result.setCode(response.getStatusLine().getStatusCode());
+ result.setBody(res);
+
+ i.close();
+
+ return result;
+ }
+ }
+
+ private boolean isNotEmpty(Object[] array) {
+ return array != null && array.length > 0;
+ }
+
+ private HttpResult failHttp(String message) {
+ HttpResult result = new HttpResult();
+ result.setCode(500);
+ result.setBody(message);
+ return result;
+ }
+
+ public static class HttpResult {
+ private String body;
+ private Map header;
+ private int code;
+
+ public String getBody() {
+ return body;
+ }
+
+ void setBody(String body) {
+ this.body = body;
+ }
+
+ public Map getHeader() {
+ return header;
+ }
+
+ void setHeader(Map header) {
+ this.header = header;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ void setCode(int code) {
+ this.code = code;
+ }
+
+ public boolean is200() {
+ return this.code == 200;
+ }
+
+ public boolean isNot200() {
+ return !this.is200();
+ }
+
+ public HttpResult checkHttpCode() {
+ if (isNot200()) {
+ throw new RuntimeException("执行http方法出错,返回值非200,body=" + body);
+ }
+ return this;
+ }
+
+ }
+
+ public void setConnectionTimeout(int connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ public void setSocketTimeout(int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+ }
+
+ public void setMAX_PER_ROUTE(int MAX_PER_ROUTE) {
+ this.MAX_PER_ROUTE = MAX_PER_ROUTE;
+ }
+
+ public void setMAX_TOTAL(int MAX_TOTAL) {
+ this.MAX_TOTAL = MAX_TOTAL;
+ }
+
+ public void setCONNECTION_REQUEST_TIMEOUT(int CONNECTION_REQUEST_TIMEOUT) {
+ this.CONNECTION_REQUEST_TIMEOUT = CONNECTION_REQUEST_TIMEOUT;
+ }
+ /**
+ * 发送post请求
+ *
+ * @param url 请求的url
+ * @param body json串
+ * @return
+ */
+ public static String sendPostJsonBody(String url, String body) {
+ log.debug("[HttpClientUtil][sendPostJsonBody] 入参 url={} body={}", url, body);
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json;charset=utf-8");
+ StringEntity entity = new StringEntity(body, "utf-8");
+ entity.setContentEncoding("UTF-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+ try {
+ HttpClient client = httpClientBuilder.build();
+ HttpResponse response = client.execute(httpPost);
+ if (response.getStatusLine() != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+ String result = EntityUtils.toString(response.getEntity(), "utf-8");
+ log.debug("[HttpClientUtil][sendPostJsonBody] 结果 url={} result={}", url, result);
+ return result;
+ }
+ log.warn("[HttpClientUtil][sendPostJsonBody] 请求失败 response={}", url, response.toString());
+ return "";
+ } catch (IOException ex) {
+ log.error("[HttpClientUtil][sendPostJsonBody] 请求异常 ex={}", url, ex);
+ return "";
+ }
+ }
+
+ /**
+ * 发送post请求
+ *
+ * @param url 请求的url
+ * @param body json串
+ * @return
+ */
+ public static String sendPostJsonBodyNoEncoding(String url, String body) {
+ log.debug("[HttpClientUtil][sendPostJsonBody] 入参 url={} body={}", url, body);
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json;charset=utf-8");
+ StringEntity entity = new StringEntity(body, "utf-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+ try {
+ HttpClient client = httpClientBuilder.build();
+ HttpResponse response = client.execute(httpPost);
+ if (response.getStatusLine() != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+ String result = EntityUtils.toString(response.getEntity(), "utf-8");
+ log.debug("[HttpClientUtil][sendPostJsonBody] 结果 url={} result={}", url, result);
+ return result;
+ }
+ log.warn("[HttpClientUtil][sendPostJsonBody] 请求失败 response={}", url, response.toString());
+ return "";
+ } catch (IOException ex) {
+ log.error("[HttpClientUtil][sendPostJsonBody] 请求异常 ex={}", url, ex);
+ return "";
+ }
+ }
+
+ public static String sendGet(String url) {
+ log.debug("[HttpClientUtil][sendPostJsonBody] 入参 url={} ", url);
+ HttpGet httpPost = new HttpGet(url);
+ HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+ try {
+ HttpClient client = httpClientBuilder.build();
+ HttpResponse response = client.execute(httpPost);
+ if (response.getStatusLine() != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+ String result = EntityUtils.toString(response.getEntity(), "utf-8");
+ log.debug("[HttpClientUtil][sendPostJsonBody] 结果 url={} result={}", url, result);
+ return result;
+ }
+ log.warn("[HttpClientUtil][sendPostJsonBody] 请求失败 response={}", url, response.toString());
+ return "";
+ } catch (IOException ex) {
+ log.error("[HttpClientUtil][sendPostJsonBody] 请求异常 ex={}", url, ex);
+ return "";
+ }
+ }
+
+}
diff --git a/common/src/main/java/com/usthe/common/entity/dto/WeChatWebHookDTO.java b/common/src/main/java/com/usthe/common/entity/dto/WeChatWebHookDTO.java
new file mode 100644
index 0000000..edfbd95
--- /dev/null
+++ b/common/src/main/java/com/usthe/common/entity/dto/WeChatWebHookDTO.java
@@ -0,0 +1,54 @@
+package com.usthe.common.entity.dto;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author 花城
+ * @version 1.0
+ * @date 2022/2/21 6:55 下午
+ * @Description
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@ApiModel(description = "企业微信WebHook模版")
+public class WeChatWebHookDTO {
+ /**
+ * 消息类型
+ */
+ private String msgtype;
+
+ private TextDTO text;
+
+ private MarkdownDTO markdown;
+
+ @Data
+ public static class TextDTO{
+ /**
+ * 消息内容
+ */
+ private String content;
+
+ /**
+ * @人的名称英文拼写列表
+ */
+ private List mentioned_list;
+
+ }
+
+ @Data
+ public static class MarkdownDTO{
+ /**
+ * 消息内容
+ */
+ private String content;
+ }
+
+}
diff --git a/common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java b/common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java
new file mode 100644
index 0000000..cbc2b8c
--- /dev/null
+++ b/common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java
@@ -0,0 +1,24 @@
+package com.usthe.common.util;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author 花城
+ * @version 1.0
+ * @date 2022/2/21 7:07 下午
+ * @Description
+ */
+@AllArgsConstructor
+@Getter
+public enum PriorityLevelEnum {
+
+ EMERGENCY(0,"紧急告警"),
+ CRITICAL(1,"严重告警"),
+ WARNING(2,"警告告警"),
+ ;
+ private Integer level;
+ private String message;
+}
diff --git a/manager/src/main/java/com/usthe/manager/component/alerter/DispatchAlarm.java b/manager/src/main/java/com/usthe/manager/component/alerter/DispatchAlarm.java
index 5c563b3..b8446d3 100644
--- a/manager/src/main/java/com/usthe/manager/component/alerter/DispatchAlarm.java
+++ b/manager/src/main/java/com/usthe/manager/component/alerter/DispatchAlarm.java
@@ -1,9 +1,14 @@
package com.usthe.manager.component.alerter;
+import com.alibaba.fastjson.JSON;
import com.usthe.alert.AlerterDataQueue;
import com.usthe.alert.AlerterWorkerPool;
+import com.usthe.collector.collect.common.http.HttpUtils;
+import com.usthe.common.util.CommonUtil;
+import com.usthe.common.util.PriorityLevelEnum;
import com.usthe.common.entity.alerter.Alert;
import com.usthe.alert.service.AlertService;
+import com.usthe.common.entity.dto.WeChatWebHookDTO;
import com.usthe.common.util.CommonConstants;
import com.usthe.common.entity.manager.Monitor;
import com.usthe.common.entity.manager.NoticeReceiver;
@@ -121,11 +126,39 @@ public class DispatchAlarm {
case 1: sendEmailAlert(receiver, alert); break;
case 2: sendWebHookAlert(receiver, alert); break;
case 3: sendWeChatAlert(receiver, alert); break;
+ case 4: sendWeChatWebHookAlert(receiver, alert);break;
default: break;
}
}
}
+ /**
+ * 通过企业微信发送告警信息
+ * @param receiver 通知配置信息
+ * @param alert 告警信息
+ */
+ private void sendWeChatWebHookAlert(NoticeReceiver receiver, Alert alert) {
+ WeChatWebHookDTO weChatWebHookDTO = new WeChatWebHookDTO();
+ weChatWebHookDTO.setMsgtype("markdown");
+ WeChatWebHookDTO.MarkdownDTO markdownDTO = new WeChatWebHookDTO.MarkdownDTO();
+ StringBuilder content = new StringBuilder();
+ content.append("\t\t\t\t[TanCloud探云告警]\n" +
+ "告警目标对象 : " + alert.getTarget() + "\n" +
+ "所属监控ID : " + alert.getMonitorId() + "\n" +
+ "所属监控名称 : " + alert.getMonitorName() + "\n");
+ if (alert.getPriority() < PriorityLevelEnum.WARNING.getLevel()){
+ content.append("告警级别 : " + CommonUtil.transferAlertPriority(alert.getPriority()) + "\n");
+ }else {
+ content.append("告警级别 : " + CommonUtil.transferAlertPriority(alert.getPriority()) + "\n");
+ }
+ content.append("内容详情 : " + alert.getContent());
+ markdownDTO.setContent(content.toString());
+ weChatWebHookDTO.setMarkdown(markdownDTO);
+ //TODO 以后转移到实体类中
+ String webHookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=fcf9ddxxx-ebaf-48a2-810c-404xxxxxxd3bf";
+ HttpUtils.sendPostJsonBody(webHookUrl, JSON.toJSONString(weChatWebHookDTO));
+ }
+
private void sendWeChatAlert(NoticeReceiver receiver, Alert alert) {
}