SpringBoot实战基于异常日志的邮件报警

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 相信所有奋斗在一线的小伙伴,会很关心自己的系统的运行情况,一般来说,基础设施齐全一点的公司都会有完善的报警方案,那么如果我们是一个小公司呢,不能因为基础设施没有,就失去对象的感知能力吧;如果我们的系统大量异常却不能实时的触达给我们,那么也就只会有一个结果--杀个程序猿祭天本文简单的介绍一种实现思路,基于error日志来实现邮件的报警方案

image.png


相信所有奋斗在一线的小伙伴,会很关心自己的系统的运行情况,一般来说,基础设施齐全一点的公司都会有完善的报警方案,那么如果我们是一个小公司呢,不能因为基础设施没有,就失去对象的感知能力吧;如果我们的系统大量异常却不能实时的触达给我们,那么也就只会有一个结果--杀个程序猿祭天


本文简单的介绍一种实现思路,基于error日志来实现邮件的报警方案


I. 项目环境



1. 项目依赖


本项目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA进行开发

开一个web服务用于测试


<dependencies>
    <!-- 邮件发送的核心依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
</dependencies>
复制代码


2. 配置


邮件相关配置如下,注意使用自己的用户名 + 授权码填充下面缺失的配置


spring:
  #邮箱配置
  mail:
    host: smtp.163.com
    from: xhhuiblog@163.com
    # 使用自己的发送方用户名 + 授权码填充
    username:
    password:
    default-encoding: UTF-8
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
复制代码


II. 异常日志的邮件预警



1. 设计思路


接下来这个方案的主要出发点在于,当程序出现大量的异常,表明应用多半出现了问题,需要立马发送给项目owner


要实现这个方案,关键点就在于异常出现的感知与上报


  • 异常的捕获,并输出日志(这个感觉属于标配了吧,别告诉我现在还有应用不输出日志文件的...)
  • 对于这个感知,借助logback的扩展机制,可以实现,后面介绍
  • 异常上报:邮件发送


关于email的使用姿势,推荐参考博文 SpringBoot 系列之邮件发送姿势介绍


2. 自定义appender


定义一个用于错误发送的Appender,如下


public class MailUtil extends AppenderBase<ILoggingEvent> {
    public static void sendMail(String title, String context) {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        //邮件发送人
        simpleMailMessage.setFrom(ContextUtil.getEnvironment().getProperty("spring.mail.from", "bangzewu@126.com"));
        //邮件接收人,可以是多个
        simpleMailMessage.setTo("bangzewu@126.com");
        //邮件主题
        simpleMailMessage.setSubject(title);
        //邮件内容
        simpleMailMessage.setText(context);
        JavaMailSender javaMailSender = ContextUtil.getApplicationContext().getBean(JavaMailSender.class);
        javaMailSender.send(simpleMailMessage);
    }
    private static final long INTERVAL = 10 * 1000 * 60;
    private long lastAlarmTime = 0;
    @Override
    protected void append(ILoggingEvent iLoggingEvent) {
        if (canAlarm()) {
            sendMail(iLoggingEvent.getLoggerName(), iLoggingEvent.getFormattedMessage());
        }
    }
    private boolean canAlarm() {
        // 做一个简单的频率过滤
        long now = System.currentTimeMillis();
        if (now - lastAlarmTime >= INTERVAL) {
            lastAlarmTime = now;
            return true;
        } else {
            return false;
        }
    }
}
复制代码


3. Spring容器


上面的邮件发送中,需要使用JavaMailSender,写一个简单的SpringContext工具类,用于获取Bean/Propertiy


@Component
public class ContextUtil implements ApplicationContextAware, EnvironmentAware {
    private static ApplicationContext applicationContext;
    private static Environment environment;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ContextUtil.applicationContext = applicationContext;
    }
    @Override
    public void setEnvironment(Environment environment) {
        ContextUtil.environment = environment;
    }
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    public static Environment getEnvironment() {
        return environment;
    }
}
复制代码


4. logback配置


接下来就是在日志配置中,使用我们上面定义的Appender


logback-spring.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d [%t] %-5level %logger{36}.%M\(%file:%line\) - %msg%n</pattern>
            <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="errorAlarm" class="com.git.hui.demo.mail.util.MailUtil">
        <!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>
    <!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
    <!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE  -->
    <!-- additivity=false 表示匹配之后,不再继续传递给其他的logger-->
    <logger name="com.git.hui" level="DEBUG" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="errorAlarm"/>
    </logger>
    <!-- 控制台输出日志级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
复制代码


5. 测试demo


接下来演示一下,是否可以达到我们的预期

@Slf4j
@RestController
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
    @GetMapping("div")
    public String div(int a, int b) {
        try {
            return String.valueOf(a / b);
        } catch (Exception e) {
            log.error("div error! {}/{}", a, b, e);
            return "some error!";
        }
    }
}
复制代码


image.png


5.小结


本篇博文主要提供了一个思路,借助logback的扩展机制,来实现错误日志与预警邮件绑定,实现一个简单的应用异常监控


上面这个实现只算是一个雏形,算是抛砖引玉,有更多可以丰富的细节,比如


  • 飞书/钉钉通知(借助飞书钉钉的机器来报警,相比较于邮件感知性更高)
  • 根据异常类型,做预警的区分
  • 更高级的频率限制等


在这里推荐一个我之前开源的预警系统,可以实现灵活预警方案配置,频率限制,重要性升级等





相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
8天前
|
Java 中间件
SpringBoot入门(6)- 添加Logback日志
SpringBoot入门(6)- 添加Logback日志
43 5
|
3天前
|
Java Maven Spring
超实用的SpringAOP实战之日志记录
【11月更文挑战第11天】本文介绍了如何使用 Spring AOP 实现日志记录功能。首先概述了日志记录的重要性及 Spring AOP 的优势,然后详细讲解了搭建 Spring AOP 环境、定义日志切面、优化日志内容和格式的方法,最后通过测试验证日志记录功能的准确性和完整性。通过这些步骤,可以有效提升系统的可维护性和可追踪性。
|
10天前
|
Dubbo Java 应用服务中间件
深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案
本文深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案。通过检查GraalVM版本兼容性、配置反射列表、使用代理类、检查配置文件、禁用不支持的功能、查看日志文件、使用GraalVM诊断工具和调整GraalVM配置等步骤,帮助开发者快速定位并解决问题,确保服务的正常运行。
26 1
|
1月前
|
Java 程序员 应用服务中间件
「测试线排查的一些经验-中篇」&& 调试日志实战
「测试线排查的一些经验-中篇」&& 调试日志实战
22 1
「测试线排查的一些经验-中篇」&& 调试日志实战
|
16天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
32 1
|
21天前
|
人工智能 Oracle Java
解决 Java 打印日志吞异常堆栈的问题
前几天有同学找我查一个空指针问题,Java 打印日志时,异常堆栈信息被吞了,导致定位不到出问题的地方。
30 2
|
1月前
|
Java API Spring
springBoot:注解&封装类&异常类&登录实现类 (八)
本文介绍了Spring Boot项目中的一些关键代码片段,包括使用`@PathVariable`绑定路径参数、创建封装类Result和异常处理类GlobalException、定义常量接口Constants、自定义异常ServiceException以及实现用户登录功能。通过这些代码,展示了如何构建RESTful API,处理请求参数,统一返回结果格式,以及全局异常处理等核心功能。
|
1月前
|
Java 关系型数据库 数据库连接
SpringBoot项目使用yml文件链接数据库异常
【10月更文挑战第3天】Spring Boot项目中数据库连接问题可能源于配置错误或依赖缺失。YAML配置文件的格式不正确,如缩进错误,会导致解析失败;而数据库驱动不匹配、连接字符串或认证信息错误同样引发连接异常。解决方法包括检查并修正YAML格式,确认配置属性无误,以及添加正确的数据库驱动依赖。利用日志记录和异常信息分析可辅助问题排查。
177 10
|
1月前
|
Java 关系型数据库 MySQL
SpringBoot项目使用yml文件链接数据库异常
【10月更文挑战第4天】本文分析了Spring Boot应用在连接数据库时可能遇到的问题及其解决方案。主要从四个方面探讨:配置文件格式错误、依赖缺失或版本不兼容、数据库服务问题、配置属性未正确注入。针对这些问题,提供了详细的检查方法和调试技巧,如检查YAML格式、验证依赖版本、确认数据库服务状态及用户权限,并通过日志和断点调试定位问题。
|
1月前
|
数据采集 监控 Java
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
本文是关于SpringBoot日志的详细教程,涵盖日志的定义、用途、SLF4J框架的使用、日志级别、持久化、文件分割及格式配置等内容。
127 0
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......