Browse Source

[Improvement-8284][Alert] Dingtalk alert plugin supports markdown message type (#8285)

* add msgtype in the dingtalk alert plugin

* update markdown msgtype 'at persion'
Kerwin 3 years ago
parent
commit
36d526d3a8

+ 12 - 1
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java

@@ -64,6 +64,17 @@ public final class DingTalkAlertChannelFactory implements AlertChannelFactory {
                         .setRequired(false)
                         .build())
                 .build();
+
+        RadioParam msgTypeParam = RadioParam
+                .newBuilder(DingTalkParamsConstants.NAME_DING_TALK_MSG_TYPE, DingTalkParamsConstants.DING_TALK_MSG_TYPE)
+                .addParamsOptions(new ParamsOptions(DingTalkParamsConstants.DING_TALK_MSG_TYPE_TEXT, DingTalkParamsConstants.DING_TALK_MSG_TYPE_TEXT, false))
+                .addParamsOptions(new ParamsOptions(DingTalkParamsConstants.DING_TALK_MSG_TYPE_MARKDOWN, DingTalkParamsConstants.DING_TALK_MSG_TYPE_MARKDOWN, false))
+                .setValue(DingTalkParamsConstants.DING_TALK_MSG_TYPE_TEXT)
+                .addValidate(Validate.newBuilder()
+                        .setRequired(false)
+                        .build())
+                .build();
+
         InputParam atMobilesParam = InputParam
                 .newBuilder(DingTalkParamsConstants.NAME_DING_TALK_AT_MOBILES, DingTalkParamsConstants.DING_TALK_AT_MOBILES)
                 .addValidate(Validate.newBuilder()
@@ -120,7 +131,7 @@ public final class DingTalkAlertChannelFactory implements AlertChannelFactory {
                 .setPlaceholder("if enable use authentication, you need input password")
                 .build();
 
-        return Arrays.asList(webHookParam, keywordParam, secretParam, atMobilesParam, atUserIdsParam, isAtAll, isEnableProxy, proxyParam, portParam, userParam, passwordParam);
+        return Arrays.asList(webHookParam, keywordParam, secretParam, msgTypeParam, atMobilesParam, atUserIdsParam, isAtAll, isEnableProxy, proxyParam, portParam, userParam, passwordParam);
     }
 
     @Override

+ 6 - 0
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java

@@ -30,6 +30,12 @@ public final class DingTalkParamsConstants {
     static final String DING_TALK_SECRET = "$t('secret')";
     static final String NAME_DING_TALK_SECRET = "Secret";
 
+    static final String DING_TALK_MSG_TYPE = "$t('msgType')";
+    static final String NAME_DING_TALK_MSG_TYPE = "MsgType";
+
+    static final String DING_TALK_MSG_TYPE_TEXT = "text";
+    static final String DING_TALK_MSG_TYPE_MARKDOWN = "markdown";
+
     static final String DING_TALK_AT_MOBILES = "$t('atMobiles')";
     static final String NAME_DING_TALK_AT_MOBILES = "AtMobiles";
 

+ 121 - 41
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java

@@ -39,10 +39,8 @@ import org.apache.http.util.EntityUtils;
 import java.io.IOException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -64,6 +62,7 @@ public final class DingTalkSender {
     private final String url;
     private final String keyword;
     private final String secret;
+    private String msgType;
 
     private final String atMobiles;
     private final String atUserIds;
@@ -83,6 +82,7 @@ public final class DingTalkSender {
         url = config.get(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK);
         keyword = config.get(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD);
         secret = config.get(DingTalkParamsConstants.NAME_DING_TALK_SECRET);
+        msgType = config.get(DingTalkParamsConstants.NAME_DING_TALK_MSG_TYPE);
 
         atMobiles = config.get(DingTalkParamsConstants.NAME_DING_TALK_AT_MOBILES);
         atUserIds = config.get(DingTalkParamsConstants.NAME_DING_TALK_AT_USERIDS);
@@ -121,33 +121,6 @@ public final class DingTalkSender {
         return RequestConfig.custom().setProxy(httpProxy).build();
     }
 
-    private String textToJsonString(String text) {
-        Map<String, Object> items = new HashMap<>();
-        items.put("msgtype", "text");
-        Map<String, String> textContent = new HashMap<>();
-        byte[] byt = StringUtils.getBytesUtf8(text);
-        String txt = StringUtils.newStringUtf8(byt);
-        textContent.put("content", txt);
-        items.put("text", textContent);
-
-        setMsgAt(items);
-        return JSONUtils.toJsonString(items);
-    }
-
-    private void setMsgAt(Map<String, Object> items) {
-        Map<String, Object> at = new HashMap<>();
-
-        String[] atMobileArray = org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(atMobiles) ? atMobiles.split(",") : new String[0];
-        String[] atUserArray = org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(atUserIds) ? atUserIds.split(",") : new String[0];
-        boolean isAtAll = Objects.isNull(atAll) ? false : atAll;
-
-        at.put("atMobiles", atMobileArray);
-        at.put("atUserIds", atUserArray);
-        at.put("isAtAll", isAtAll);
-
-        items.put("at", at);
-    }
-
     private AlertResult checkSendDingTalkSendMsgResult(String result) {
         AlertResult alertResult = new AlertResult();
         alertResult.setStatus("false");
@@ -173,6 +146,13 @@ public final class DingTalkSender {
         return alertResult;
     }
 
+    /**
+     * send dingtalk msg handler
+     *
+     * @param title title
+     * @param content content
+     * @return
+     */
     public AlertResult sendDingTalkMsg(String title, String content) {
         AlertResult alertResult;
         try {
@@ -189,18 +169,9 @@ public final class DingTalkSender {
 
     private String sendMsg(String title, String content) throws IOException {
 
-        StringBuilder text = new StringBuilder();
-        if (org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(keyword)) {
-            text.append(keyword);
-            text.append(":");
-        }
-        text.append(title);
-        text.append("\n");
-        text.append(content);
-
-        String msgToJson = textToJsonString(text.toString());
+        String msg = generateMsgJson(title, content);
 
-        HttpPost httpPost = constructHttpPost(org.apache.dolphinscheduler.spi.utils.StringUtils.isBlank(secret) ? url : generateSignedUrl(), msgToJson);
+        HttpPost httpPost = constructHttpPost(org.apache.dolphinscheduler.spi.utils.StringUtils.isBlank(secret) ? url : generateSignedUrl(), msg);
 
         CloseableHttpClient httpClient;
         if (Boolean.TRUE.equals(enableProxy)) {
@@ -221,13 +192,119 @@ public final class DingTalkSender {
             } finally {
                 response.close();
             }
-            logger.info("Ding Talk send title :{},content : {}, resp: {}", title, content, resp);
+            logger.info("Ding Talk send msg :{}, resp: {}", msg, resp);
             return resp;
         } finally {
             httpClient.close();
         }
     }
 
+    /**
+     * generate msg json
+     *
+     * @param title title
+     * @param content content
+     * @return msg
+     */
+    private String generateMsgJson(String title, String content) {
+        if (org.apache.dolphinscheduler.spi.utils.StringUtils.isBlank(msgType)) {
+            msgType = DingTalkParamsConstants.DING_TALK_MSG_TYPE_TEXT;
+        }
+        Map<String, Object> items = new HashMap<>();
+        items.put("msgtype", msgType);
+        Map<String, Object> text = new HashMap<>();
+        items.put(msgType, text);
+
+        if (DingTalkParamsConstants.DING_TALK_MSG_TYPE_MARKDOWN.equals(msgType)) {
+            generateMarkdownMsg(title, content, text);
+        } else {
+            generateTextMsg(title, content, text);
+        }
+
+        setMsgAt(items);
+        return JSONUtils.toJsonString(items);
+
+    }
+
+    /**
+     * generate text msg
+     *
+     * @param title title
+     * @param content content
+     * @param text text
+     */
+    private void generateTextMsg(String title, String content, Map<String, Object> text) {
+        StringBuilder builder = new StringBuilder(title);
+        builder.append("\n");
+        builder.append(content);
+        if (org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(keyword)) {
+            builder.append(" ");
+            builder.append(keyword);
+        }
+        byte[] byt = StringUtils.getBytesUtf8(builder.toString());
+        String txt = StringUtils.newStringUtf8(byt);
+        text.put("content", txt);
+    }
+
+    /**
+     * generate markdown msg
+     *
+     * @param title title
+     * @param content content
+     * @param text text
+     */
+    private void generateMarkdownMsg(String title, String content, Map<String, Object> text) {
+        StringBuilder builder = new StringBuilder(content);
+        if (org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(keyword)) {
+            builder.append(" ");
+            builder.append(keyword);
+        }
+        builder.append("\n\n");
+        if (org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(atMobiles)) {
+            Arrays.stream(atMobiles.split(",")).forEach(value -> {
+                builder.append("@");
+                builder.append(value);
+                builder.append(" ");
+            });
+        }
+        if (org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(atUserIds)) {
+            Arrays.stream(atUserIds.split(",")).forEach(value -> {
+                builder.append("@");
+                builder.append(value);
+                builder.append(" ");
+            });
+        }
+
+        byte[] byt = StringUtils.getBytesUtf8(builder.toString());
+        String txt = StringUtils.newStringUtf8(byt);
+        text.put("title", title);
+        text.put("text", txt);
+    }
+
+    /**
+     * configure msg @person
+     *
+     * @param items items
+     */
+    private void setMsgAt(Map<String, Object> items) {
+        Map<String, Object> at = new HashMap<>();
+
+        String[] atMobileArray = org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(atMobiles) ? atMobiles.split(",") : new String[0];
+        String[] atUserArray = org.apache.dolphinscheduler.spi.utils.StringUtils.isNotBlank(atUserIds) ? atUserIds.split(",") : new String[0];
+        boolean isAtAll = Objects.isNull(atAll) ? false : atAll;
+
+        at.put("atMobiles", atMobileArray);
+        at.put("atUserIds", atUserArray);
+        at.put("isAtAll", isAtAll);
+
+        items.put("at", at);
+    }
+
+    /**
+     * generate sign url
+     *
+     * @return sign url
+     */
     private String generateSignedUrl() {
         Long timestamp = System.currentTimeMillis();
         String stringToSign = timestamp + "\n" + secret;
@@ -266,6 +343,7 @@ public final class DingTalkSender {
             this.errmsg = errmsg;
         }
 
+        @Override
         public boolean equals(final Object o) {
             if (o == this) {
                 return true;
@@ -287,6 +365,7 @@ public final class DingTalkSender {
             return true;
         }
 
+        @Override
         public int hashCode() {
             final int PRIME = 59;
             int result = 1;
@@ -297,6 +376,7 @@ public final class DingTalkSender {
             return result;
         }
 
+        @Override
         public String toString() {
             return "DingTalkSender.DingTalkSendMsgResponse(errcode=" + this.getErrcode() + ", errmsg=" + this.getErrmsg() + ")";
         }

+ 1 - 1
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java

@@ -32,7 +32,7 @@ public class DingTalkAlertChannelFactoryTest {
         DingTalkAlertChannelFactory dingTalkAlertChannelFactory = new DingTalkAlertChannelFactory();
         List<PluginParams> params = dingTalkAlertChannelFactory.params();
         JSONUtils.toJsonString(params);
-        Assert.assertEquals(11, params.size());
+        Assert.assertEquals(12, params.size());
     }
 
     @Test

+ 3 - 1
dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java

@@ -33,8 +33,10 @@ public class DingTalkSenderTest {
     @Before
     public void initDingTalkConfig() {
 
-        dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD, "keyWord");
+        dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD, "keyword");
         dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK, "url");
+        dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_MSG_TYPE, DingTalkParamsConstants.DING_TALK_MSG_TYPE_MARKDOWN);
+
         dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, "false");
         dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD, "password");
         dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PORT, "9988");

+ 1 - 0
dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js

@@ -755,6 +755,7 @@ export default {
   webHook: 'WebHook',
   Keyword: 'Keyword',
   Secret: 'Secret',
+  MsgType: 'MsgType',
   AtMobiles: '@Mobiles',
   AtUserIds: '@UserIds',
   IsAtAll: '@All',

+ 1 - 0
dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js

@@ -755,6 +755,7 @@ export default {
   webHook: 'Web钩子',
   Keyword: '关键词',
   Secret: '密钥',
+  MsgType: '消息类型',
   AtMobiles: '@手机号',
   AtUserIds: '@用户ID',
   IsAtAll: '@所有人',