This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

SpringBoot actual mail alarm based on exception log

I believe that all the partners struggling in the front line, will be very concerned about the operation of their own system, generally speaking, the company with complete infrastructure will have a perfect alarm scheme, so if we are a small company, we can not lose the object’s perception ability because there is no infrastructure; If our system has a lot of exceptions but can’t reach us in real time, then there is only one result — kill a program ape to heaven

This paper simply introduces a way to realize the mail alarm scheme based on error log

I. Project environment

1. Project dependency

This project is developed with SpringBoot 2.2.1.RELEASE + Maven 3.5.3 + IDEA

Start a Web service for testing

<dependencies>
    <! -- Core dependencies for mail delivery -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
</dependencies>
Copy the code

2. The configuration

The mail-related configuration is as follows, be careful to fill in the missing configuration below with your user name + authorization code

spring:
  # Email configuration
  mail:
    host: smtp.163.com
    from: [email protected]
    # Fill in your own sender username + authorization code
    username:
    password:
    default-encoding: UTF-8
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
Copy the code

II. Mail alerts for exception logs

1. Design ideas

The main starting point for the following solution is that when a large number of exceptions occur in the application, it is likely that the application has a problem and needs to be sent to the project owner immediately

The key to implementing this solution is the perception and reporting of exceptions

  • Exceptions are caught and logged (this seems to be standard, don’t tell me there are still applications that don’t output log files…)
    • This awareness can be achieved using logback’s extension mechanism, as described below
  • Exception reporting: Mails are sent

For more information on how to use email, please refer to SpringBoot’s post on email

2. Customize appender

Define an Appender for error sending, as follows

public class MailUtil extends AppenderBase<ILoggingEvent> {

    public static void sendMail(String title, String context) {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        // The sender of the email
        simpleMailMessage.setFrom(ContextUtil.getEnvironment().getProperty("spring.mail.from"."[email protected]"));
        // The email recipient can be multiple
        simpleMailMessage.setTo("[email protected]");
        // Email subject
        simpleMailMessage.setSubject(title);
        // Email content
        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(a) {
        // Do a simple frequency filter
        long now = System.currentTimeMillis();
        if (now - lastAlarmTime >= INTERVAL) {
            lastAlarmTime = now;
            return true;
        } else {
            return false; }}}Copy the code

3. The Spring container

In the above email sending, you need to write a simple SpringContext utility class to get the Bean/Propertiy using the JavaMailSender

@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(a) {
        return applicationContext;
    }

    public static Environment getEnvironment(a) {
        returnenvironment; }}Copy the code

4. Logback configuration

The next step is to use the appenders we defined above in the logging configuration

The logback-spring. XML file contains the following contents:


      
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d [%t] %-5level %logger{36}.%M\(%file:%line\) - %msg%n</pattern>
            <! -- Console use UTF-8, not GBK, otherwise Chinese garbled -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="errorAlarm" class="com.git.hui.demo.mail.util.MailUtil">
        <! -- If you only want Error logs, then you need to filter them, default is info, ThresholdFilter-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>


    <! -- Specify the logging level of a package in a project when logged operations are performed -->
    <! -- FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
    <! -- apptivity =false =false -->
    <logger name="com.git.hui" level="DEBUG" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="errorAlarm"/>
    </logger>

    <! -- Console output log level -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
Copy the code

5. Test the demo

So let’s see if we can do that

@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!"; }}}Copy the code

5. Summary

This blog post mainly provides an idea, with the help of logback extension mechanism, to achieve error log and warning email binding, to achieve a simple application exception monitoring

The above implementation is just a prototype, and it is a good introduction. There are more details that can be enriched, such as

  • Flying book/staple notification (using a flying book staple machine to alarm, more perceptual than email)
  • According to the exception type, do the warning distinction
  • More advanced frequency limits, etc

Here I recommend an open source early warning system, which can achieve flexible early warning solution configuration, frequency limit, importance escalation, etc

  • An extensible alarm system github.com/liuyueyi/qu…

III. Can’t miss the source code and related knowledge

0. Project

  • Project: github.com/liuyueyi/sp…
  • Source: github.com/liuyueyi/sp…

Recommend related blog posts

  • Introduction to SpringBoot series email sending posture

1. Wechat official account: a gray Blog

The above content is not as good as the letter, purely the words of a family, due to the limited personal ability, there are inevitably omissions and mistakes, such as found bugs or better suggestions, welcome criticism and correction, not grudging gratitude

Below a gray personal blog, record all study and work in the blog, welcome everyone to visit

  • A gray Blog personal Blog blog.hhui. Top
  • A Gray Blog-Spring feature Blog Spring.hhui. Top