springboot项目编写发送异常日志到企微工具包

本文主要是介绍springboot项目编写发送异常日志到企微工具包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.创建基础Bean

public final class ThreadFactory implements java.util.concurrent.ThreadFactory {private static final AtomicInteger poolNumber = new AtomicInteger(1);private final ThreadGroup group;private final AtomicInteger threadNumber = new AtomicInteger(1);private final String namePrefix;public ThreadFactory(String groupFlag, String functionName) {SecurityManager s = System.getSecurityManager();this.group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();this.namePrefix = this.buildPrefix(groupFlag, functionName, poolNumber);}private String buildPrefix(String vendorFlag, String functionName, final AtomicInteger poolNumber) {StringBuffer sb = (new StringBuffer("pool-")).append(poolNumber.getAndIncrement()).append("-thread-");String connChar = "-";if (null != vendorFlag && !"".equals(vendorFlag)) {sb.append(vendorFlag).append(connChar);}if (null != functionName && !"".equals(functionName)) {sb.append(functionName).append(connChar);}return sb.toString();}public Thread newThread(Runnable r) {String threadName = this.namePrefix + this.threadNumber.getAndIncrement();Thread t = new Thread(this.group, r, threadName, 0L);if (t.isDaemon()) {t.setDaemon(false);}if (t.getPriority() != 5) {t.setPriority(5);}return t;}
}
public class QiWeiMarkDownMessage<T> {private String msgtype;private T markdown;public QiWeiMarkDownMessage() {}public String getMsgtype() {return this.msgtype;}public T getMarkdown() {return this.markdown;}public void setMsgtype(final String msgtype) {this.msgtype = msgtype;}public void setMarkdown(final T markdown) {this.markdown = markdown;}public boolean equals(final Object o) {if (o == this) {return true;} else if (!(o instanceof QiWeiMarkDownMessage)) {return false;} else {QiWeiMarkDownMessage<?> other = (QiWeiMarkDownMessage)o;if (!other.canEqual(this)) {return false;} else {Object this$msgtype = this.getMsgtype();Object other$msgtype = other.getMsgtype();if (this$msgtype == null) {if (other$msgtype != null) {return false;}} else if (!this$msgtype.equals(other$msgtype)) {return false;}Object this$markdown = this.getMarkdown();Object other$markdown = other.getMarkdown();if (this$markdown == null) {if (other$markdown != null) {return false;}} else if (!this$markdown.equals(other$markdown)) {return false;}return true;}}}protected boolean canEqual(final Object other) {return other instanceof QiWeiMarkDownMessage;}public int hashCode() {int result = 1;Object $msgtype = this.getMsgtype();result = result * 59 + ($msgtype == null ? 43 : $msgtype.hashCode());Object $markdown = this.getMarkdown();result = result * 59 + ($markdown == null ? 43 : $markdown.hashCode());return result;}public String toString() {return "QiWeiMarkDownMessage(msgtype=" + this.getMsgtype() + ", markdown=" + this.getMarkdown() + ")";}
}
public class QiWeiMessageContext {private String content;private String mentioned_list;private String mentioned_mobile_list;public QiWeiMessageContext() {}public String getContent() {return this.content;}public String getMentioned_list() {return this.mentioned_list;}public String getMentioned_mobile_list() {return this.mentioned_mobile_list;}public void setContent(final String content) {this.content = content;}public void setMentioned_list(final String mentioned_list) {this.mentioned_list = mentioned_list;}public void setMentioned_mobile_list(final String mentioned_mobile_list) {this.mentioned_mobile_list = mentioned_mobile_list;}public boolean equals(final Object o) {if (o == this) {return true;} else if (!(o instanceof QiWeiMessageContext)) {return false;} else {QiWeiMessageContext other = (QiWeiMessageContext)o;if (!other.canEqual(this)) {return false;} else {label47: {Object this$content = this.getContent();Object other$content = other.getContent();if (this$content == null) {if (other$content == null) {break label47;}} else if (this$content.equals(other$content)) {break label47;}return false;}Object this$mentioned_list = this.getMentioned_list();Object other$mentioned_list = other.getMentioned_list();if (this$mentioned_list == null) {if (other$mentioned_list != null) {return false;}} else if (!this$mentioned_list.equals(other$mentioned_list)) {return false;}Object this$mentioned_mobile_list = this.getMentioned_mobile_list();Object other$mentioned_mobile_list = other.getMentioned_mobile_list();if (this$mentioned_mobile_list == null) {if (other$mentioned_mobile_list != null) {return false;}} else if (!this$mentioned_mobile_list.equals(other$mentioned_mobile_list)) {return false;}return true;}}}protected boolean canEqual(final Object other) {return other instanceof QiWeiMessageContext;}public int hashCode() {int result = 1;Object $content = this.getContent();result = result * 59 + ($content == null ? 43 : $content.hashCode());Object $mentioned_list = this.getMentioned_list();result = result * 59 + ($mentioned_list == null ? 43 : $mentioned_list.hashCode());Object $mentioned_mobile_list = this.getMentioned_mobile_list();result = result * 59 + ($mentioned_mobile_list == null ? 43 : $mentioned_mobile_list.hashCode());return result;}public String toString() {return "QiWeiMessageContext(content=" + this.getContent() + ", mentioned_list=" + this.getMentioned_list() + ", mentioned_mobile_list=" + this.getMentioned_mobile_list() + ")";}
}
public class MachineUtils {public MachineUtils() {}public static String getHostIpFromDockerContainer() {String ip = null;try {Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();while(networkInterfaces.hasMoreElements()) {NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();if (!"docker0".equals(networkInterface.getDisplayName()) && !"lo".equals(networkInterface.getDisplayName())) {Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();StringJoiner ipJoiner = new StringJoiner("/", "(", ")");while(inetAddresses.hasMoreElements()) {InetAddress inetAddress = (InetAddress)inetAddresses.nextElement();ipJoiner.add(inetAddress.getHostAddress());}ip = ipJoiner.toString();break;}}} catch (Exception var6) {System.out.println("获取容器ip信息失败:" + var6);ip = "未获取到容器对应宿主机ip信息";}return ip;}public static MachineUtils.Machine getMachineInfo() {MachineUtils.Machine machine = new MachineUtils.Machine();try {InetAddress address = getLocalHostLANAddress();String ip = address.getHostAddress();String hostName = address.getHostName();machine.ip = ip;machine.hostName = hostName;} catch (Exception var4) {machine.hostName = "localhost";machine.ip = "127.0.0.1";}return machine;}private static InetAddress getLocalHostLANAddress() throws UnknownHostException {try {InetAddress candidateAddress = null;Enumeration ifaces = NetworkInterface.getNetworkInterfaces();while(ifaces.hasMoreElements()) {NetworkInterface iface = (NetworkInterface)ifaces.nextElement();Enumeration inetAddrs = iface.getInetAddresses();while(inetAddrs.hasMoreElements()) {InetAddress inetAddr = (InetAddress)inetAddrs.nextElement();if (!inetAddr.isLoopbackAddress()) {if (inetAddr.isSiteLocalAddress()) {return inetAddr;}if (candidateAddress == null) {candidateAddress = inetAddr;}}}}if (candidateAddress != null) {return candidateAddress;} else {InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();if (jdkSuppliedAddress == null) {throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");} else {return jdkSuppliedAddress;}}} catch (Exception var5) {UnknownHostException unknownHostException = new UnknownHostException("Failed to determine LAN address: " + var5);unknownHostException.initCause(var5);throw unknownHostException;}}public static class Machine {public String ip = "";public String hostName = "";public Machine() {}}
}
public class ThrowableUtils {public ThrowableUtils() {}public static String getThrowableStackTrace(Throwable t) {StringWriter sw = new StringWriter();t.printStackTrace(new PrintWriter(sw, true));String result = sw.getBuffer().toString();return result.length() > 3700 ? result.substring(0, 3700) + "\n..." : result;}
}
public class OKHttpUtil {private static final Logger log = LoggerFactory.getLogger(OKHttpUtil.class);private static volatile OkHttpClient okHttpClient = null;private static volatile Semaphore semaphore = null;private static final String CONTENT_TYPE = "Content-Type";private OKHttpUtil() {if (okHttpClient == null) {Class var1 = OKHttpUtil.class;synchronized(OKHttpUtil.class) {if (okHttpClient == null) {TrustManager[] trustManagers = buildTrustManagers();okHttpClient = (new Builder()).connectTimeout(15L, TimeUnit.SECONDS).writeTimeout(20L, TimeUnit.SECONDS).readTimeout(20L, TimeUnit.SECONDS).sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager)trustManagers[0]).hostnameVerifier((hostName, session) -> {return true;}).retryOnConnectionFailure(true).build();}}}}public static OKHttpUtil builder() {return new OKHttpUtil();}private static Semaphore getSemaphoreInstance() {Class var0 = OKHttpUtil.class;synchronized(OKHttpUtil.class) {if (semaphore == null) {semaphore = new Semaphore(0);}}return semaphore;}private static okhttp3.Request.Builder addHeaders(Map<String, Object> headerMap, okhttp3.Request.Builder builder) {if (headerMap != null && !headerMap.isEmpty()) {headerMap.forEach((key, value) -> {builder.addHeader(key, String.valueOf(value));});}return builder;}private RequestBody setRequestBody(Map<String, Object> bodyParams, Map<String, Object> headerMap) throws Exception {if (headerMap != null && headerMap.containsKey("Content-Type")) {String contentType = String.valueOf(headerMap.get("Content-Type"));if ("application/x-www-form-urlencoded".equals(contentType)) {Map<String, String> strBodyParamMap = new HashMap();if (bodyParams != null && !bodyParams.isEmpty()) {bodyParams.forEach((key, value) -> {if (value != null) {strBodyParamMap.put(key, (String)value);}});}return this.buildRequestBodyByMap(strBodyParamMap);} else {throw new RuntimeException("未知请求类型");}} else {throw new Exception("请求头信息配置中无 Content-Type配置,请先配置");}}private RequestBody buildRequestBodyByMap(Map<String, String> bodyParams) {RequestBody body = null;okhttp3.FormBody.Builder formEncodingBuilder = new okhttp3.FormBody.Builder();if (bodyParams != null) {Iterator<String> iterator = bodyParams.keySet().iterator();String key = "";while(iterator.hasNext()) {key = (String)iterator.next();formEncodingBuilder.add(key, (String)bodyParams.get(key));log.info("okClient post表单提交请求参数:{},请求值:{} ", key, bodyParams.get(key));}}body = formEncodingBuilder.build();return body;}public String get(String url, Map<String, Object> headerMap) {String responseStr = null;try {okhttp3.Request.Builder builder = (new okhttp3.Request.Builder()).get().url(url);addHeaders(headerMap, builder);Request request = builder.build();Response response = okHttpClient.newCall(request).execute();responseStr = response.body().string();} catch (Exception var7) {log.error("httpUtil 请求出错:{}", var7.getMessage(), var7);}return responseStr;}public String postByJson(String url, String body, Map<String, Object> headerMap) {String responseStr = null;try {RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), body);okhttp3.Request.Builder requestBuilder = (new okhttp3.Request.Builder()).post(requestBody).url(url);addHeaders(headerMap, requestBuilder);Request request = requestBuilder.build();Call call = okHttpClient.newCall(request);Response response = call.execute();responseStr = response.body().string();} catch (Exception var10) {log.error("httpUtil 请求出错:{}", var10.getMessage(), var10);}return responseStr;}public String postByForm(String url, Map<String, Object> bodyMap, Map<String, Object> headerMap) {String responseStr = null;try {RequestBody body = this.setRequestBody(bodyMap, headerMap);okhttp3.Request.Builder requestBuilder = (new okhttp3.Request.Builder()).post(body).url(url);addHeaders(headerMap, requestBuilder);Request request = requestBuilder.build();Call call = okHttpClient.newCall(request);Response response = call.execute();responseStr = response.body().string();} catch (Exception var10) {log.error("httpUtil 请求出错:{}", var10.getMessage(), var10);}return responseStr;}public void postJsonAsync(String url, String json, final OKHttpUtil.MyNetCall myNetCall) throws IOException {RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();Request request = requestBuilder.post(body).url(url).build();Call call = okHttpClient.newCall(request);call.enqueue(new Callback() {public void onFailure(Call call, IOException e) {myNetCall.failed(call, e);}public void onResponse(Call call, Response response) throws IOException {myNetCall.success(call, response);OKHttpUtil.getSemaphoreInstance().release();}});try {getSemaphoreInstance().acquire();} catch (InterruptedException var9) {var9.printStackTrace();}}private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {SSLSocketFactory ssfFactory = null;try {SSLContext sc = SSLContext.getInstance("TLS");sc.init((KeyManager[])null, trustAllCerts, new SecureRandom());ssfFactory = sc.getSocketFactory();} catch (Exception var3) {var3.printStackTrace();}return ssfFactory;}private static TrustManager[] buildTrustManagers() {return new TrustManager[]{new X509TrustManager() {public void checkClientTrusted(X509Certificate[] chain, String authType) {}public void checkServerTrusted(X509Certificate[] chain, String authType) {}public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}}};}public interface MyNetCall {void success(Call call, Response response) throws IOException;void failed(Call call, IOException e);}
}

 

public final class ThreadPoolFactory {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolFactory.class);private static int SEND_MESSAGE_CORESIZE = 1;private static int SEND_MESSAGE_MAXSIZE = 1;private static int SEND_MESSAGE_KEEPALIVE = 120;private static int SEND_MESSAGE_QUEUESIZE = 120;public static ExecutorService createExecutorService(int coreNum, int maxNum) {return new ThreadPoolExecutor(coreNum, maxNum, (long)SEND_MESSAGE_KEEPALIVE, TimeUnit.SECONDS, new ArrayBlockingQueue(SEND_MESSAGE_QUEUESIZE), new ThreadFactory("robotMessage", "SendErrorMessage"), new DiscardOldestPolicy());}private ThreadPoolFactory() {}static class MonitorRejectedExecutionHandler implements RejectedExecutionHandler {MonitorRejectedExecutionHandler() {}public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {if (!executor.isShutdown()) {try {executor.getQueue().put(r);} catch (InterruptedException var4) {ThreadPoolFactory.LOGGER.error("When task queue is full, some bad things happened! Message is {}", var4);}}}}
}
public abstract class AbstraceSendErrorMsgAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {private String appName;private String messageChannel;private String env;private String sendEnabled;public AbstraceSendErrorMsgAppender() {}public void append(ILoggingEvent event) {if (event.getLevel() == Level.ERROR && "true".equals(this.sendEnabled)) {try {String userLogeErrorMessage = event.getFormattedMessage();String stackTraceInfo = "";IThrowableProxy proxy = event.getThrowableProxy();if (null != proxy) {Throwable t = ((ThrowableProxy)proxy).getThrowable();stackTraceInfo = ThrowableUtils.getThrowableStackTrace(t);}String ip = MachineUtils.getHostIpFromDockerContainer();if (stackTraceInfo.contains("OmsException") || stackTraceInfo.contains("WmsException") || stackTraceInfo.contains("BmsException")) {return;}LocalDateTime dateTime = LocalDateTime.now();DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");String mesText = "服务名称:<font color=\"warning\">[" + this.appName + "]</font>,发生错误异常\n>ip:[" + ip + "]\n>环境信息:[" + this.env + "]\n>异常信息:[" + userLogeErrorMessage + "]\n>time:[" + dateTime.format(formatter) + "]\n堆栈信息:[\n" + stackTraceInfo + "]";this.sendAlarmMessage("markdown", mesText);} catch (Exception var9) {System.out.println(String.format("日志报警异常,异常原因:{} last=%s", var9.getMessage()));}}}public String getAppName() {return this.appName;}public void setAppName(String appName) {this.appName = appName;}public String getMessageChannel() {return this.messageChannel;}public void setMessageChannel(String messageChannel) {this.messageChannel = messageChannel;}public String getEnv() {return this.env;}public void setEnv(String env) {this.env = env;}public String getSendEnabled() {return this.sendEnabled;}public void setSendEnabled(String sendEnabled) {this.sendEnabled = sendEnabled;}protected abstract void sendAlarmMessage(String messageType, String messageContent);
}
public class SendQiWeiAlarmErrorMessageAppender extends AbstraceSendErrorMsgAppender {private static final Logger log = LoggerFactory.getLogger(SendQiWeiAlarmErrorMessageAppender.class);private String webhookUrl;private AlarmService alarmService;public SendQiWeiAlarmErrorMessageAppender() {}protected void sendAlarmMessage(String messageType, String messageContent) {Assert.hasText(this.webhookUrl, "机器人webHook地址不能为空");if (null == this.alarmService) {synchronized(this) {if (null == this.alarmService) {this.alarmService = new WechatAlarmServiceImpl(this.webhookUrl);}}}this.alarmService.alarmHandler(messageType, messageContent);}public String getWebhookUrl() {return this.webhookUrl;}public void setWebhookUrl(String webhookUrl) {this.webhookUrl = webhookUrl;}
}

2.创建配置类

@ConfigurationProperties(prefix = "message.robot"
)
public class RobotMessageAlarmMessageProperties {private String enable;public RobotMessageAlarmMessageProperties() {}public String getEnable() {return this.enable;}public void setEnable(final String enable) {this.enable = enable;}public boolean equals(final Object o) {if (o == this) {return true;} else if (!(o instanceof RobotMessageAlarmMessageProperties)) {return false;} else {RobotMessageAlarmMessageProperties other = (RobotMessageAlarmMessageProperties)o;if (!other.canEqual(this)) {return false;} else {Object this$enable = this.getEnable();Object other$enable = other.getEnable();if (this$enable == null) {if (other$enable != null) {return false;}} else if (!this$enable.equals(other$enable)) {return false;}return true;}}}protected boolean canEqual(final Object other) {return other instanceof RobotMessageAlarmMessageProperties;}public int hashCode() {int result = 1;Object $enable = this.getEnable();result = result * 59 + ($enable == null ? 43 : $enable.hashCode());return result;}public String toString() {return "RobotMessageAlarmMessageProperties(enable=" + this.getEnable() + ")";}
}
@Configuration
@ConditionalOnProperty(prefix = "message.robot",name = {"enable"},havingValue = "true",matchIfMissing = false
)
@ConditionalOnClass(name = {"ch.qos.logback.classic.LoggerContext"}
)
@EnableConfigurationProperties({RobotMessageAlarmMessageProperties.class})
@ComponentScan({"com.xrtframework.logback.alarm"})
public class LogbackAlarmAutoConfiguration {private final RobotMessageAlarmMessageProperties robotMessageAlarmMessageProperties;public LogbackAlarmAutoConfiguration(RobotMessageAlarmMessageProperties robotMessageAlarmMessageProperties) {this.robotMessageAlarmMessageProperties = robotMessageAlarmMessageProperties;}
}
public interface AlarmService {void alarmHandler(String messageType, String messageContent);
}
public class WechatAlarmServiceImpl implements AlarmService {private static final Logger log = LoggerFactory.getLogger(WechatAlarmServiceImpl.class);private String webhookUrl;private ExecutorService executorService;private static final int coreThreadNum = 3;private static final int maxThreadNum = 10;private RateLimiter rateLimiter;private static final Double rateLimiterPermitsPerSecond = 0.2857D;public WechatAlarmServiceImpl(String webhookUrl) {this.webhookUrl = webhookUrl;this.executorService = ThreadPoolFactory.createExecutorService(3, 10);this.rateLimiter = RateLimiter.create(rateLimiterPermitsPerSecond);}public void alarmHandler(String messageType, String messageContent) {try {this.rateLimiter.acquire();this.executorService.execute(() -> {QiWeiMessageContext qiWeiMessage = new QiWeiMessageContext();qiWeiMessage.setContent(messageContent);qiWeiMessage.setMentioned_list("@all");QiWeiMarkDownMessage<QiWeiMessageContext> qiWeiMessageContextQiWeiMarkDownMessage = new QiWeiMarkDownMessage();qiWeiMessageContextQiWeiMarkDownMessage.setMsgtype(messageType);qiWeiMessageContextQiWeiMarkDownMessage.setMarkdown(qiWeiMessage);if (log.isDebugEnabled()) {log.debug("【企业微信机器人告警】消息请求入参:{}", JSON.toJSONString(qiWeiMessageContextQiWeiMarkDownMessage));}String response = OKHttpUtil.builder().postByJson(this.webhookUrl, JSON.toJSONString(qiWeiMessageContextQiWeiMarkDownMessage), (Map)null);if (log.isDebugEnabled()) {log.debug("【企业微信机器人告警】消息请出参:{}", response);}});} catch (Exception var4) {System.out.println(String.format("send wechat error last=%s", var4.getMessage()));}}
}
pom.properties
version=1.0-SNAPSHOT
groupId=com.xxframework
artifactId=xxframe-logback-alarm

 

spring-configuration-metadata.json{"groups": [{"name": "message.robot","type": "com.xxframework.logback.alarm.config.RobotMessageAlarmMessageProperties","sourceType": "com.xxframework.logback.alarm.config.RobotMessageAlarmMessageProperties"}],"properties": [{"name": "message.robot.enable","type": "java.lang.String","sourceType": "com.xxframework.logback.alarm.config.RobotMessageAlarmMessageProperties"}],"hints": []
}

3.pom依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><exclusion><artifactId>spring-boot-starter-logging</artifactId><groupId>org.springframework.boot</groupId></exclusion></exclusions></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--用来解决未配置spring boot 配置注解处理器IDEA告警--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>com.xrtframework</groupId><artifactId>xrtframe-common-util</artifactId><version>${project.version}</version><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><scope>provided</scope></dependency></dependencies><!--    <build>--><!--        <plugins>--><!--            <plugin>--><!--                <groupId>org.springframework.boot</groupId>--><!--                <artifactId>spring-boot-maven-plugin</artifactId>--><!--            </plugin>--><!--        </plugins>--><!--        --><!--    </build>--><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><testFailureIgnore>true</testFailureIgnore></configuration></plugin></plugins><resources><resource><directory>src/main/resources</directory><includes><include>**/*</include></includes></resource></resources></build>

4.主工程引入工具包 pom依赖

<dependency><groupId>com.xxframework</groupId><artifactId>xxframe-logback-alarm</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--micrometer桥接prometheus--><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency>

5.主工程logback-spring.xml引入配置

 <!--添加的内容--><springProperty scope="context" name="robotMessageChannel" source="message.robot.channel" defaultValue="QI_WEI"/><springProperty scope="context" name="robotMessageEnv" source="message.robot.env" defaultValue=""/><springProperty scope="context" name="robotMessageWebHookUrl" source="message.robot.webhookUrl" defaultValue=""/><!--添加的内容--><appender name="sendErrorMsg" class="com.xrtframework.logback.alarm.core.SendQiWeiAlarmErrorMessageAppender"><!--使用该组件的应用名称 --><appName>${springAppName}</appName><messageChannel>${robotMessageChannel}</messageChannel><env>${robotMessageEnv}</env><webhookUrl>${robotMessageWebHookUrl}</webhookUrl></appender>

6.nacos配置

#应用日志监控
message.robot.sendEnabled=true
message.robot.channel=QI_WEI
message.robot.env=测试环境
message.robot.webhookUrl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=XXX

这篇关于springboot项目编写发送异常日志到企微工具包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145814

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory