From c0fa28399317bc5fe86773ab9879d1fe414e471b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=A6=E4=B9=A0=E4=BB=A3=E7=A0=81=E7=9A=84=E5=B0=8F?= =?UTF-8?q?=E7=99=BD?= <8145789+learning-code@user.noreply.gitee.com> Date: Mon, 21 Feb 2022 13:03:38 +0000 Subject: [PATCH 1/4] =?UTF-8?q?!8=20feat:=20=E5=AE=9E=E7=8E=B0=E4=BC=81?= =?UTF-8?q?=E4=B8=9A=E5=BE=AE=E4=BF=A1WebHook=E5=91=8A=E8=AD=A6=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E6=8E=A8=E9=80=81=20*=20feat:=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1WebHook=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E5=91=8A=E8=AD=A6=E4=BF=A1=E6=81=AF=20#I4U9BT=20*=20Merge=20re?= =?UTF-8?q?mote-tracking=20branch=20'origin/master'=20*=20feature:=20?= =?UTF-8?q?=E9=82=AE=E4=BB=B6=E9=99=84=E5=8A=A0=E6=8E=A2=E4=BA=91logo?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E7=A4=BE=E5=8C=BAlogo=20#I4U9BT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- collector/pom.xml | 5 + .../collect/common/http/HttpUtils.java | 473 ++++++++++++++++++ .../common/entity/dto/WeChatWebHookDTO.java | 54 ++ .../usthe/common/util/PriorityLevelEnum.java | 24 + .../component/alerter/DispatchAlarm.java | 33 ++ 5 files changed, 589 insertions(+) create mode 100644 collector/src/main/java/com/usthe/collector/collect/common/http/HttpUtils.java create mode 100644 common/src/main/java/com/usthe/common/entity/dto/WeChatWebHookDTO.java create mode 100644 common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java 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) { } From c1010da2fec8a1393d729def68266a2bee1b1498 Mon Sep 17 00:00:00 2001 From: tomsun28 Date: Tue, 22 Feb 2022 10:01:15 +0800 Subject: [PATCH 2/4] =?UTF-8?q?[manager,common]=E4=BC=81=E4=B8=9A=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=91=8A=E8=AD=A6=E9=80=9A=E7=9F=A5=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- collector/pom.xml | 5 - .../collect/common/http/HttpUtils.java | 473 ------------------ .../common/entity/dto/WeChatWebHookDTO.java | 54 -- .../common/entity/manager/NoticeReceiver.java | 12 +- .../usthe/common/util/PriorityLevelEnum.java | 24 - .../component/alerter/DispatchAlarm.java | 51 +- .../manager/pojo/dto/WeWorkWebHookDTO.java | 41 ++ script/sql/schema.sql | 7 +- 8 files changed, 83 insertions(+), 584 deletions(-) delete mode 100644 collector/src/main/java/com/usthe/collector/collect/common/http/HttpUtils.java delete mode 100644 common/src/main/java/com/usthe/common/entity/dto/WeChatWebHookDTO.java delete mode 100644 common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java create mode 100644 manager/src/main/java/com/usthe/manager/pojo/dto/WeWorkWebHookDTO.java diff --git a/collector/pom.xml b/collector/pom.xml index 63b99cc..5b1eacb 100644 --- a/collector/pom.xml +++ b/collector/pom.xml @@ -51,11 +51,6 @@ 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 deleted file mode 100644 index d552847..0000000 --- a/collector/src/main/java/com/usthe/collector/collect/common/http/HttpUtils.java +++ /dev/null @@ -1,473 +0,0 @@ -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 deleted file mode 100644 index edfbd95..0000000 --- a/common/src/main/java/com/usthe/common/entity/dto/WeChatWebHookDTO.java +++ /dev/null @@ -1,54 +0,0 @@ -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/entity/manager/NoticeReceiver.java b/common/src/main/java/com/usthe/common/entity/manager/NoticeReceiver.java index d5353d4..9293a60 100644 --- a/common/src/main/java/com/usthe/common/entity/manager/NoticeReceiver.java +++ b/common/src/main/java/com/usthe/common/entity/manager/NoticeReceiver.java @@ -46,7 +46,7 @@ public class NoticeReceiver { @NotNull private String name; - @ApiModelProperty(value = "通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号", accessMode = READ_WRITE, position = 2) + @ApiModelProperty(value = "通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人", accessMode = READ_WRITE, position = 2) @Min(0) @Max(3) @NotNull @@ -61,13 +61,17 @@ public class NoticeReceiver { private String email; @ApiModelProperty(value = "URL地址, 通知方式为webhook有效", example = "https://www.tancloud.cn", accessMode = READ_WRITE, position = 5) - @Length(max = 100) + @Length(max = 300) private String hookUrl; - @ApiModelProperty(value = "wechat用户openId, 通知方式为微信公众号有效", example = "343432", accessMode = READ_WRITE, position = 6) - @Length(max = 100) + @ApiModelProperty(value = "openId, 通知方式为微信公众号或企业微信机器人有效", example = "343432", accessMode = READ_WRITE, position = 6) + @Length(max = 300) private String wechatId; + @ApiModelProperty(value = "访问token, 通知方式为钉钉机器人有效", example = "34823984635647", accessMode = READ_WRITE, position = 7) + @Length(max = 300) + private String accessToken; + @ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 7) private String creator; diff --git a/common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java b/common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java deleted file mode 100644 index cbc2b8c..0000000 --- a/common/src/main/java/com/usthe/common/util/PriorityLevelEnum.java +++ /dev/null @@ -1,24 +0,0 @@ -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 b8446d3..9e833f5 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,14 +1,11 @@ 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.manager.pojo.dto.WeWorkWebHookDTO; import com.usthe.common.util.CommonConstants; import com.usthe.common.entity.manager.Monitor; import com.usthe.common.entity.manager.NoticeReceiver; @@ -120,13 +117,14 @@ public class DispatchAlarm { List receivers = matchReceiverByNoticeRules(alert); // todo 发送通知这里暂时单线程 for (NoticeReceiver receiver : receivers) { + sendWeWorkRobotAlert(receiver, alert); switch (receiver.getType()) { // todo 短信通知 case 0: break; case 1: sendEmailAlert(receiver, alert); break; case 2: sendWebHookAlert(receiver, alert); break; case 3: sendWeChatAlert(receiver, alert); break; - case 4: sendWeChatWebHookAlert(receiver, alert);break; + case 4: sendWeWorkRobotAlert(receiver, alert);break; default: break; } } @@ -137,26 +135,37 @@ public class DispatchAlarm { * @param receiver 通知配置信息 * @param alert 告警信息 */ - private void sendWeChatWebHookAlert(NoticeReceiver receiver, Alert alert) { - WeChatWebHookDTO weChatWebHookDTO = new WeChatWebHookDTO(); - weChatWebHookDTO.setMsgtype("markdown"); - WeChatWebHookDTO.MarkdownDTO markdownDTO = new WeChatWebHookDTO.MarkdownDTO(); + private void sendWeWorkRobotAlert(NoticeReceiver receiver, Alert alert) { + WeWorkWebHookDTO weWorkWebHookDTO = new WeWorkWebHookDTO(); + WeWorkWebHookDTO.MarkdownDTO markdownDTO = new WeWorkWebHookDTO.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"); + content.append("[TanCloud探云告警通知]\n告警目标对象 : ") + .append(alert.getTarget()).append("\n") + .append("所属监控ID : ").append(alert.getMonitorId()).append("\n") + .append("所属监控名称 : ").append(alert.getMonitorName()).append("\n"); + if (alert.getPriority() < CommonConstants.ALERT_PRIORITY_CODE_WARNING) { + content.append("告警级别 : ") + .append(CommonUtil.transferAlertPriority(alert.getPriority())).append("\n"); }else { - content.append("告警级别 : " + CommonUtil.transferAlertPriority(alert.getPriority()) + "\n"); + content.append("告警级别 : ") + .append(CommonUtil.transferAlertPriority(alert.getPriority())).append("\n"); } - content.append("内容详情 : " + alert.getContent()); + content.append("内容详情 : ").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)); + weWorkWebHookDTO.setMarkdown(markdownDTO); + String webHookUrl = WeWorkWebHookDTO.WEBHOOK_URL + receiver.getWechatId(); + try { + ResponseEntity entity = restTemplate.postForEntity(webHookUrl, weWorkWebHookDTO, String.class); + if (entity.getStatusCode() == HttpStatus.OK) { + log.debug("Send weWork webHook: {} Success", webHookUrl); + } else { + log.warn("Send weWork webHook: {} Failed: {}", webHookUrl, entity.getBody()); + } + } catch (ResourceAccessException e) { + log.warn("Send WebHook: {} Failed: {}.", receiver.getHookUrl(), e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage(), e); + } } private void sendWeChatAlert(NoticeReceiver receiver, Alert alert) { diff --git a/manager/src/main/java/com/usthe/manager/pojo/dto/WeWorkWebHookDTO.java b/manager/src/main/java/com/usthe/manager/pojo/dto/WeWorkWebHookDTO.java new file mode 100644 index 0000000..4cd6738 --- /dev/null +++ b/manager/src/main/java/com/usthe/manager/pojo/dto/WeWorkWebHookDTO.java @@ -0,0 +1,41 @@ +package com.usthe.manager.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 企业微信机器人请求消息体 + * @author 花城 + * @version 1.0 + * @date 2022/2/21 6:55 下午 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class WeWorkWebHookDTO { + + public static final String WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key="; + private static final String MARKDOWN = "markdown"; + + /** + * 消息类型 + */ + private String msgtype = MARKDOWN; + + /** + * markdown消息 + */ + private MarkdownDTO markdown; + + @Data + public static class MarkdownDTO { + /** + * 消息内容 + */ + private String content; + } + +} diff --git a/script/sql/schema.sql b/script/sql/schema.sql index ccf5e4a..7b85496 100644 --- a/script/sql/schema.sql +++ b/script/sql/schema.sql @@ -148,11 +148,12 @@ CREATE TABLE notice_receiver ( id bigint not null auto_increment comment '消息接收人ID', name varchar(100) not null comment '消息接收人姓名', - type tinyint not null comment '通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号', + type tinyint not null comment '通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人', phone varchar(100) comment '手机号, 通知方式为手机短信时有效', email varchar(100) comment '邮箱账号, 通知方式为邮箱时有效', - hook_url varchar(100) comment 'URL地址, 通知方式为webhook有效', - wechat_id varchar(100) comment 'wechat用户openId, 通知方式为微信公众号有效', + hook_url varchar(255) comment 'URL地址, 通知方式为webhook有效', + wechat_id varchar(255) comment 'openId, 通知方式为微信公众号或企业微信机器人有效', + access_token varchar(255) comment '访问token, 通知方式为钉钉机器人有效', creator varchar(100) comment '创建者', modifier varchar(100) comment '最新修改者', gmt_create timestamp default current_timestamp comment 'create time', From e54ba2b058feaaf98c4e2b065b6f83080ce04f2e Mon Sep 17 00:00:00 2001 From: tomsun28 Date: Tue, 22 Feb 2022 10:10:30 +0800 Subject: [PATCH 3/4] =?UTF-8?q?[manager]fix=20=E9=87=8D=E5=A4=8D=E5=8F=91?= =?UTF-8?q?=E9=80=81=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/usthe/manager/component/alerter/DispatchAlarm.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 9e833f5..e0713be 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 @@ -117,7 +117,6 @@ public class DispatchAlarm { List receivers = matchReceiverByNoticeRules(alert); // todo 发送通知这里暂时单线程 for (NoticeReceiver receiver : receivers) { - sendWeWorkRobotAlert(receiver, alert); switch (receiver.getType()) { // todo 短信通知 case 0: break; @@ -162,7 +161,7 @@ public class DispatchAlarm { log.warn("Send weWork webHook: {} Failed: {}", webHookUrl, entity.getBody()); } } catch (ResourceAccessException e) { - log.warn("Send WebHook: {} Failed: {}.", receiver.getHookUrl(), e.getMessage()); + log.warn("Send WebHook: {} Failed: {}.", webHookUrl, e.getMessage()); } catch (Exception e) { log.error(e.getMessage(), e); } From ac66499bf3dcb2cfda72f3111077a29d4368ab09 Mon Sep 17 00:00:00 2001 From: tomsun28 Date: Tue, 22 Feb 2022 11:08:50 +0800 Subject: [PATCH 4/4] =?UTF-8?q?[web-app]=E5=89=8D=E7=AB=AF=E5=BC=80?= =?UTF-8?q?=E6=94=BE=E8=AE=BE=E7=BD=AE=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E6=9C=BA=E5=99=A8=E4=BA=BA=E5=91=8A=E8=AD=A6=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/entity/manager/NoticeReceiver.java | 2 +- web-app/src/app/pojo/NoticeReceiver.ts | 1 + .../alert-notice/alert-notice.component.html | 26 ++++++++++++++----- .../alert-notice/alert-notice.component.ts | 2 ++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/com/usthe/common/entity/manager/NoticeReceiver.java b/common/src/main/java/com/usthe/common/entity/manager/NoticeReceiver.java index 9293a60..7f91223 100644 --- a/common/src/main/java/com/usthe/common/entity/manager/NoticeReceiver.java +++ b/common/src/main/java/com/usthe/common/entity/manager/NoticeReceiver.java @@ -48,7 +48,7 @@ public class NoticeReceiver { @ApiModelProperty(value = "通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人", accessMode = READ_WRITE, position = 2) @Min(0) - @Max(3) + @Max(8) @NotNull private Byte type; diff --git a/web-app/src/app/pojo/NoticeReceiver.ts b/web-app/src/app/pojo/NoticeReceiver.ts index 0742ff1..67d2bc1 100644 --- a/web-app/src/app/pojo/NoticeReceiver.ts +++ b/web-app/src/app/pojo/NoticeReceiver.ts @@ -7,6 +7,7 @@ export class NoticeReceiver { email!: string; hookUrl!: string; wechatId!: string; + accessToken!: string; creator!: string; modifier!: string; gmtCreate!: number; diff --git a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html index 0561ba5..d0f0fab 100644 --- a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html +++ b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html @@ -60,12 +60,17 @@ 微信公众号 + + + 企业微信机器人 + {{ data.phone }} {{ data.email }} {{ data.hookUrl }} {{ data.wechatId }} + {{ data.wechatId }} {{ data.gmtUpdate ? data.gmtUpdate : data.gmtCreate }} @@ -158,24 +163,25 @@
接收人名称 - + 通知方式 - + + 手机号 - + 邮箱 - + URL地址 - + 微信OPENID - - + + + + + + 企业微信机器人KEY + + diff --git a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.ts b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.ts index 1523ed1..6ecca0a 100644 --- a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.ts +++ b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.ts @@ -259,6 +259,8 @@ export class AlertNoticeComponent implements OnInit { case 3: label = `${label}WeChat`; break; + case 4: + label = `${label}WeWorkRobot`; } this.receiversOption.push({ value: item.id,