From eb37ffb51cb38ebec20854eff0d7742b5a1b0b3c Mon Sep 17 00:00:00 2001 From: jianjun Date: Wed, 15 Sep 2021 18:13:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5dinger=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF=E5=8F=91=E5=88=B0=E9=92=89?= =?UTF-8?q?=E9=92=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 + tduck-api/pom.xml | 4 + .../api/web/controller/CommonController.java | 22 ++ .../api/web/filter/LogMsgSendFilter.java | 207 ++++++++++++++++++ .../src/main/resources/application-dev.yml | 7 + .../src/main/resources/application-prod.yml | 7 + .../src/main/resources/application-test.yml | 7 + .../src/main/resources/logback-spring.xml | 14 +- 8 files changed, 266 insertions(+), 8 deletions(-) create mode 100644 tduck-api/src/main/java/com/tduck/cloud/api/web/filter/LogMsgSendFilter.java diff --git a/pom.xml b/pom.xml index c0edb9c..a8536c5 100644 --- a/pom.xml +++ b/pom.xml @@ -168,6 +168,12 @@ java-sdk ${upyun.version} + + com.github.answerail + dinger-spring-boot-starter + 1.2.0-beta1 + + diff --git a/tduck-api/pom.xml b/tduck-api/pom.xml index 6d3a427..8a2c523 100644 --- a/tduck-api/pom.xml +++ b/tduck-api/pom.xml @@ -69,6 +69,10 @@ org.apache.poi poi-ooxml + + com.github.answerail + dinger-spring-boot-starter + diff --git a/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/CommonController.java b/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/CommonController.java index 216fd4e..35a223e 100644 --- a/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/CommonController.java +++ b/tduck-api/src/main/java/com/tduck/cloud/api/web/controller/CommonController.java @@ -1,7 +1,10 @@ package com.tduck.cloud.api.web.controller; +import com.github.jaemon.dinger.DingerSender; import com.tduck.cloud.common.util.AsyncProcessUtils; import com.tduck.cloud.common.util.Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -12,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController; * @description : 通用 * @create : 2021/06/08 15:32 **/ +@Slf4j @RestController @RequestMapping("/common/") public class CommonController { @@ -24,4 +28,22 @@ public class CommonController { public Result getProcess(@RequestParam String key) { return Result.success(AsyncProcessUtils.getProcess(key)); } + + @Autowired + private DingerSender dingerSender; + + @GetMapping("/process2") + public void afterPropertiesSet() throws Exception { + /* // 发送text类型消息 + dingerSender.send( + MessageSubType.TEXT, + DingerRequest.request("Hello World, Hello Dinger") + );*/ + int n = 1/0; + /* // 发送markdown类型消息 + dingerSender.send( + MessageSubType.MARKDOWN, + DingerRequest.request("Hello World, Hello Dinger", "启动通知") + );*/ + } } diff --git a/tduck-api/src/main/java/com/tduck/cloud/api/web/filter/LogMsgSendFilter.java b/tduck-api/src/main/java/com/tduck/cloud/api/web/filter/LogMsgSendFilter.java new file mode 100644 index 0000000..74f5158 --- /dev/null +++ b/tduck-api/src/main/java/com/tduck/cloud/api/web/filter/LogMsgSendFilter.java @@ -0,0 +1,207 @@ +package com.tduck.cloud.api.web.filter; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.filter.LevelFilter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.core.spi.FilterReply; +import cn.hutool.core.date.DateUtil; +import com.github.jaemon.dinger.DingerSender; +import com.github.jaemon.dinger.core.entity.DingerRequest; +import com.github.jaemon.dinger.core.entity.enums.MessageSubType; +import com.tduck.cloud.common.util.EnvEnum; +import com.tduck.cloud.common.util.SpringContextUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * desc: 发送日志消息 + * + * @date: 2020/6/24 17:47 + * @author: jianjun liu + */ +public class LogMsgSendFilter extends LevelFilter { + private static final Logger logger = LoggerFactory.getLogger(LogMsgSendFilter.class); + private DingerSender msgSender; + + private String appName; + + private String activeEnv; + private String serverIp; + private String baseProjectPackage = "com.tduck"; + public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + + + @Override + public FilterReply decide(ILoggingEvent event) { + //如果日志级别等于设置的日志级别 则发送消息 + if (event.getLevel().isGreaterOrEqual(Level.ERROR)) { + try { + getServerInfo(); + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("\n\n"); + if (StringUtils.isNotBlank(appName)) { + stringBuilder.append("> 服务名称:").append(appName); + stringBuilder.append("\n\n"); + } + + if (StringUtils.isNotBlank(activeEnv)) { + stringBuilder.append("> 告警环境:").append(activeEnv); + stringBuilder.append("\n\n"); + } + + if (StringUtils.isNotBlank(serverIp)) { + stringBuilder.append("> IP地址:").append(serverIp); + stringBuilder.append("\n\n"); + } + + stringBuilder.append("> 故障时间:").append(DateUtil.format(new Date(event.getTimeStamp()),DATE_TIME_PATTERN)); + stringBuilder.append("\n\n"); + stringBuilder.append("> TraceId:").append(Thread.currentThread().getName()); + stringBuilder.append("\n\n"); + + HttpServletRequest request = getRequest(); + if (request != null) { + String requestURI = request.getRequestURI(); + stringBuilder.append("> 请求路径:").append(requestURI); + stringBuilder.append("\n\n"); + + //stringBuilder.append("请求参数:").append(ThreadLocalConstant.requestParam.get()); + //stringBuilder.append("\n\n"); + } + + String formattedMessage = event.getFormattedMessage(); + IThrowableProxy throwableProxy = event.getThrowableProxy(); + if (throwableProxy == null && formattedMessage.length() > 1000) { + formattedMessage = formattedMessage.substring(0, getCharacterPosition(formattedMessage, baseProjectPackage, 5)); + } + stringBuilder.append("> 告警信息:").append(formattedMessage); + stringBuilder.append("\n\n"); + + + //异常信息处理 暂时处理一级的5行数据 + apendStackInfo(stringBuilder, throwableProxy); + if (msgSender == null){ + msgSender = SpringContextUtils.getBean(DingerSender.class); + } + msgSender.send(MessageSubType.MARKDOWN, + DingerRequest.request(stringBuilder.toString(), "日志告警")); + + } catch (Exception e) { + logger.warn("decide exception", e); + } + } + //交给其他filter继续向下处理 + return super.decide(event); + + } + + /** + * desc:获取服务 ip及profile信息 + */ + private void getServerInfo() { + try { + if (serverIp == null) { + InetUtils inetUtils = SpringContextUtils.getBean(InetUtils.class); + if (inetUtils == null || inetUtils.findFirstNonLoopbackHostInfo() == null){ + return; + } + serverIp = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); + } + } catch (Exception e) { + logger.warn("getServerInfo get bean InetUtils exception", e); + return; + } + try { + if (activeEnv == null) { + EnvEnum currentEnv = EnvEnum.getCurrentEnv(); + activeEnv = currentEnv.getName(); + } + } catch (Exception e) { + logger.warn("getServerInfo get bean Environment exception", e); + } + } + + private void apendStackInfo(StringBuilder stringBuilder, IThrowableProxy throwableProxy) { + int defaultRowLine = 5; + if (throwableProxy != null) { + stringBuilder.append("> 异常信息:") + .append(throwableProxy.getClassName()) + .append(" : ") + .append(throwableProxy.getMessage()) + .append("\n\n"); + + StackTraceElementProxy[] stackTraceElementProxyArray = throwableProxy.getStackTraceElementProxyArray(); + StackTraceElementProxy stackTraceElementProxy = null; + + if (stackTraceElementProxyArray.length < defaultRowLine) { + defaultRowLine = stackTraceElementProxyArray.length; + } + for (int i = 0; i < defaultRowLine; i++) { + stackTraceElementProxy = stackTraceElementProxyArray[i]; + StackTraceElement stackTraceElement = stackTraceElementProxy.getStackTraceElement(); + stringBuilder.append("\t\tat "); + stringBuilder.append(stackTraceElement.getClassName()); + stringBuilder.append("."); + stringBuilder.append(stackTraceElement.getMethodName()); + stringBuilder.append("("); + stringBuilder.append(stackTraceElement.getFileName()); + stringBuilder.append(":"); + stringBuilder.append(stackTraceElement.getLineNumber()); + stringBuilder.append(")"); + stringBuilder.append("\n\n"); + } + } + } + + /** + * 获取Request对象 + * + * @return + */ + private HttpServletRequest getRequest() { + RequestAttributes ra = RequestContextHolder.getRequestAttributes(); + ServletRequestAttributes sra = (ServletRequestAttributes) ra; + if (sra == null){ + return null; + } + return sra.getRequest(); + + } + + + public static int getCharacterPosition(String string, String findStr, int time) { + Matcher slashMatcher = null; + try { + slashMatcher = Pattern.compile(findStr).matcher(string); + int mIdx = 0; + while (slashMatcher.find()) { + mIdx++; + if (mIdx == time) { + break; + } + } + return slashMatcher.start(); + } catch (Exception e) { + logger.warn("getCharacterPosition no matche"); + return string.length(); + } + } + + public void setAppName(String appName) { + this.appName = appName; + } + +} diff --git a/tduck-api/src/main/resources/application-dev.yml b/tduck-api/src/main/resources/application-dev.yml index c54b631..afe927f 100644 --- a/tduck-api/src/main/resources/application-dev.yml +++ b/tduck-api/src/main/resources/application-dev.yml @@ -29,6 +29,13 @@ spring: host: smtp.exmail.qq.com username: mpw:9jwi2HILb4x+eVy2fA0SYeits0G3qlm/YajJdX0OKQU= password: mpw:kLAEhMW75jvbXovAGdf4gEoe2/j6OJMaK2GYhTD8b8A= + dinger: + project-id: ${spring.application.name} + dingers: + # 使用钉钉机器人, 请根据自己机器人配置信息进行修改 + dingtalk: + tokenId: 09841218241814985bb3b63bc2a55f6116595f07b2d79ad7fd044f185254d596 + secret: SEC1dce5c64c5aaf086776052d0c4f6e785ae07b5e1fbfa4f4c261a57260cafcc68 logging: level: diff --git a/tduck-api/src/main/resources/application-prod.yml b/tduck-api/src/main/resources/application-prod.yml index c3be1f9..7eb5fb0 100644 --- a/tduck-api/src/main/resources/application-prod.yml +++ b/tduck-api/src/main/resources/application-prod.yml @@ -29,6 +29,13 @@ spring: host: smtp.163.com username: test@163.com # 邮箱账号 password: DSXFPX24XOBURMDY #邮箱授权码 + dinger: + project-id: ${spring.application.name} + dingers: + # 使用钉钉机器人, 请根据自己机器人配置信息进行修改 + dingtalk: + tokenId: a5f66c3374b1642fe2142dbf56d5997e280172d4e8f2b546c9423a68c82ece6c + secret: SEC95f4f40b533ad379ea6a6d1af6dd37029383cfe1b7cd96dfac2678be2c1c3ed1 logging: level: diff --git a/tduck-api/src/main/resources/application-test.yml b/tduck-api/src/main/resources/application-test.yml index 0dca42e..b8cc823 100644 --- a/tduck-api/src/main/resources/application-test.yml +++ b/tduck-api/src/main/resources/application-test.yml @@ -29,6 +29,13 @@ spring: host: smtp.exmail.qq.com username: mpw:9jwi2HILb4x+eVy2fA0SYeits0G3qlm/YajJdX0OKQU= password: mpw:kLAEhMW75jvbXovAGdf4gEoe2/j6OJMaK2GYhTD8b8A= + dinger: + project-id: ${spring.application.name} + dingers: + # 使用钉钉机器人, 请根据自己机器人配置信息进行修改 + dingtalk: + tokenId: 09841218241814985bb3b63bc2a55f6116595f07b2d79ad7fd044f185254d596 + secret: SEC1dce5c64c5aaf086776052d0c4f6e785ae07b5e1fbfa4f4c261a57260cafcc68 logging: level: diff --git a/tduck-api/src/main/resources/logback-spring.xml b/tduck-api/src/main/resources/logback-spring.xml index 2112bd4..8f7057a 100644 --- a/tduck-api/src/main/resources/logback-spring.xml +++ b/tduck-api/src/main/resources/logback-spring.xml @@ -4,7 +4,7 @@ - + tduck-api @@ -131,19 +131,17 @@ 15 - + + ERROR ACCEPT DENY - ${webHook} - ${secret} - %contextName - --> + ${appname} +