SpringBoot Getting Started Series Unified Log Collection!

Spring Boot exception handling was described earlier, and unclear friends can see the previous articles.

Today we will focus on log collection in Spring Boot. Logs are the key to tracking error positioning issues. Especially in production environments, we need to quickly locate problems with logs.

Springboot's logging framework is rich, and Springboot itself has built-in logging capabilities, but in real projects it will appear: just log what you want, log output to disk, archive by day, log information synchronization to other systems, and so on.These are things Springboot does not have built-in logging.So I recommend logback.Let's talk about log collection in Spring Boot with logback.

 

Why Unify Logs

As we mentioned earlier, Springboot can log itself, so why do I need to standardize logging?

1. The log is unified and easy to read and manage.

2. Log split archiving function.

3. Log persistence function.

4. Convenient logging system (ELK) collection.

 

To configure

Create a logback-spring.xml file under resource, and paste the configuration information directly below, which can be referenced directly in the notes

<?xml version="1.0" encoding="UTF-8"?>
<!-- Log levels range from low to high TRACE < DEBUG < INFO < WARN < ERROR < FATAL,If set to WARN,Is lower than WARN None of the information will be output -->
<!-- scan:When this property is set to true When the configuration file changes, it will be reloaded, and the default value is true -->
<!-- scanPeriod:Set a time interval to monitor whether the configuration file has been modified or, if no time unit is given, the default unit is milliseconds.When scan by true This property takes effect when.The default time interval is 1 minute. -->
<!-- debug:When this property is set to true Will print out logback Internal log information, real-time viewing logback Running state.Default value is false.  -->
<configuration  scan="true" scanPeriod="10 seconds">

    <!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->

    <contextName>logback</contextName>
    <!-- name The value of is the name of the variable. value The value defined by the variable when the value of.Defined values are inserted into the logger Context.After defining the variable, you can make the ${}"To use variables. -->
    <property name="log.path" value="D:/nmyslog/nmys" />

    <!-- Color Log -->
    <!-- Color Log Dependent Rendering Classes -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- Color Log Format -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>


    <!--Output to console-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--This log appender For development purposes, only the bottom level is configured, and the log level output by the console is greater than or equal to this level of log information-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- Set Character Set -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!--output to a file-->

    <!-- Time Scroll Output level by DEBUG Journal -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- Path and file name of log file being logged -->
        <file>${log.path}/log_debug.log</file>
        <!--Log file output format-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- Set Character Set -->
        </encoder>
        <!-- Logger scrolling strategy, by date, by size -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- Archive -->
            <fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--Days of log file retention-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- This log file records only debug Level -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- Time Scroll Output level by INFO Journal -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- Path and file name of log file being logged -->
        <file>${log.path}/log_info.log</file>
        <!--Log file output format-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- Logger scrolling strategy, by date, by size -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- Daily log archive path and format -->
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--Days of log file retention-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- This log file records only info Level -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- Time Scroll Output level by WARN Journal -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- Path and file name of log file being logged -->
        <file>${log.path}/log_warn.log</file>
        <!--Log file output format-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- Set Character Set Here -->
        </encoder>
        <!-- Logger scrolling strategy, by date, by size -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--Days of log file retention-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- This log file records only warn Level -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <!-- Time Scroll Output level by ERROR Journal -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- Path and file name of log file being logged -->
        <file>${log.path}/log_error.log</file>
        <!--Log file output format-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- Set Character Set Here -->
        </encoder>
        <!-- Logger scrolling strategy, by date, by size -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--Days of log file retention-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- This log file records only ERROR Level -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--
        <logger>Used to set the log printing level for a package or specific class,
        And specify<appender>. <logger>Only one name Properties,
        An optional level And an optional addtivity Properties.
        name:Used to specify acceptance of this logger A package or a specific class of constraints.
        level:Used to set the print level, case-independent: TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF,
              There's also a special value INHERITED Or synonyms NULL,Represents the level at which a superior is enforced.
              If this property is not set, then the current logger The superior level will be inherited.
        addtivity:Whether to go up or not logger Deliver print information.Default is true. 
    -->
    <!--<logger name="org.springframework.web" level="info"/>-->
    <!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
    <!--
        Use mybatis When, sql Statement is debug Next will print, and here we only configure info,So I want to see sql If a statement is made, there are two operations:
        The first handles<root level="info">Change to<root level="DEBUG">This will print sql,But then there's a lot of other news on the blog side
        The second is to give it alone dao Lower Directory Configuration debug Mode, code as follows, configure sql Statement will print, others are normal info Level:
     -->


    <!--
        root Node is required to specify the most basic level of log output, there is only one level attribute
        level:Used to set the print level, case-independent: TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF,
        Cannot be set to INHERITED Or synonyms NULL. Default is DEBUG
        Can contain zero or more elements to identify this appender Will be added to this logger. 
    -->

    <!--development environment:Print Console-->
    <springProfile name="dev">
        <logger name="com.nmys.view" level="debug"/>
    </springProfile>

    <root level="info">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="DEBUG_FILE" />
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="WARN_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>

    <!--production environment:output to a file-->
    <!--<springProfile name="pro">-->
    <!--<root level="info">-->
    <!--<appender-ref ref="CONSOLE" />-->
    <!--<appender-ref ref="DEBUG_FILE" />-->
    <!--<appender-ref ref="INFO_FILE" />-->
    <!--<appender-ref ref="ERROR_FILE" />-->
    <!--<appender-ref ref="WARN_FILE" />-->
    <!--</root>-->
    <!--</springProfile>-->
</configuration>

Be careful

  • The logging environment, spring.profiles.acticve, follows the project launch.
  • Once started, you can find the generated log file in your own directory.
  • The officially recommended format for XML names is logback-spring.xml, not logback.xml.

 

Configure application.properties

Configuring logback in application.properties

############################################################
#
# logback configuration, log management
#
############################################################
#Log configuration, output to text,
logging.config=classpath:logback-spring.xml
#idea Console Default Log Level Modification
# Specifies the file name of the output log, which is output by default to the current project directory
#logging.file.path=springboot.log

Collect exception logs

Unified exception handling has been discussed in the previous article. See this article, Implementation of Unified Exception Handling in the Introduction to SpringBoot Series (11).

Modify the GlobalExceptionHandler class of the Unified Exception Processor to change direct printing in the exception method to log input and printing:

@ExceptionHandler(value = Exception.class)
    public Object errorHandler(HttpServletRequest reqest, 
            HttpServletResponse response, Exception e) throws Exception {
        
        //e.printStackTrace();
        // Logging
        logger.error(ExceptionUtils.getMessage(e));
        // Is an ajax request
        if (isAjax(reqest)) {
            return JSONResult.errorException(e.getMessage());
        } else {
            ModelAndView mav = new ModelAndView();
            mav.addObject("exception", e);
            mav.addObject("url", reqest.getRequestURL());
            mav.setViewName(ERROR_VIEW);
            return mav;
        }
    }

Logging in programs

Create a LoggingController controller in com.weiz.controller

package com.weiz.controller;

import com.weiz.utils.JSONResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/log")
public class LoggingController {
    Logger logger = LoggerFactory.getLogger(getClass());

    @RequestMapping("/write")
    public JSONResult  writeLog(){
        // Level from low to high trace<debug<info<warn<error
        logger.trace("This is a trace Journal");
        logger.debug("This is a debug Journal");
        logger.info("This is a info Journal");
        logger.warn("This is a warn Journal");
        logger.error("This is a error Journal");
        return JSONResult.ok("write log success");
    }
}

test

Start the project and enter http://localhost:8080/log/write in the browser to view the log files in the relevant directory

Tags: Programming Spring xml SpringBoot SQL

Posted on Wed, 13 May 2020 10:22:39 -0700 by Tandem