springboot logging


springboot logging

                             

官网:Spring Boot Features(logging)

                                 

                                       

******************

控制台日志彩色输出

                        

控制台彩色输出需要终端支持ansi

# application.yml
spring.output.ansi.enabled


*************
spring-configuration-metadata.json(配置提示)

    {
      "name": "spring.output.ansi.enabled",
      "type": "org.springframework.boot.ansi.AnsiOutput$Enabled",
      "description": "Configures the ANSI output.",
      "defaultValue": "detect"    # 默认值为detect,终端支持则显示彩色
    },


*************
AnsiOutput

public abstract class AnsiOutput {

    。。。

    public static enum Enabled {
        DETECT,
        ALWAYS,
        NEVER;

        private Enabled() {
        }
    }
}

                      

示例

%clr(%5p)               # 随后5格式用彩色输出
                        # %5p表示右对齐,不足5位左边用空格填充
                        # %-5p表示左对齐,不足5为右边用空格填充

%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
                        # 随后日期时间彩色输出,格式为:yyyy-MM-dd HH:mm:ss.SSS
                        # 颜色为黄色

                           

日志级别默认输出颜色

FATAL  Red
ERROR  Red

WARN   Yellow

INFO   Green
DEBUG  Green
TRACE  Green

                          

支持输出的日志颜色

red、blue、green、yellow
cyan、faint、magenta

                      

                                   

******************

日志输出到文件

                         

By default, Spring Boot logs only to the console and does not write log files. 
# springboot日志默认值输出到控制台

If you want to write log files in addition to the console output, 
you need to set a logging.file.name or logging.file.path property 
(for example, in your application.properties)
# 使用logging.file.name、logging.file.path可将日志同时输出到文件

Log files rotate when they reach 10 MB and, as with console output, 
ERROR-level, WARN-level, and INFO-level messages are logged by default
# 日志文件达到10M就会新建一个文件,
# 和console输出一样,默认值输出info、warn、error级别的日志

                         

使用规则

不使用logging.file.name、logging.file.path   ==> 只输出到控制台
只使用logging.file.name=my.log ==> 在项目路径下输出my.log文件
之所以logging.file.path=./     ==> 在项目路径下输出spring.log(默认文件名)文件
同时使用logging.file.name、logging.file.path ==> 以logging.file.name为准

                                         

                                                                             

******************

日志文件滚动

                            

If you are using the Logback, it’s possible to fine-tune log rotation settings 
using your application.properties or application.yaml file. 
logback日志文件可直接在配置文件中配置

For all other logging system, you’ll need to configure rotation settings directly 
yourself (for example, if you use Log4J2 then you could add a log4j.xml file)
其他日志框架,需要自行配置(如log4j2,需要使用log4j.xml进行配置)

                         

logback配置参数

logging.logback.rollingpolicy.file-name-pattern        # 日志文件命名规则,默认${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.clean-history-on-start   # 启动时是否删除历史日志文件,默认false
logging.logback.rollingpolicy.max-file-size            # 单个日志文件大小,默认10M
logging.logback.rollingpolicy.total-size-cap           # 日志文件最大的总大小,默认0B(不限制)
logging.logback.rollingpolicy.max-history              # 日志文件最大保存天数,默认7天

spring-configuration-metadata.json(配置提示)

    {
      "name": "logging.logback.rollingpolicy.clean-history-on-start",
      "type": "java.lang.Boolean",
      "description": "Whether to clean the archive log files on startup.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": false
    },
    {
      "name": "logging.logback.rollingpolicy.file-name-pattern",
      "type": "java.lang.String",
      "description": "Pattern for rolled-over log file names.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz"
    },
    {
      "name": "logging.logback.rollingpolicy.max-file-size",
      "type": "org.springframework.util.unit.DataSize",
      "description": "Maximum log file size.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "10MB"
    },
    {
      "name": "logging.logback.rollingpolicy.max-history",
      "type": "java.lang.Integer",
      "description": "Maximum number of days archive log files are kept.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": 7
    },
    {
      "name": "logging.logback.rollingpolicy.total-size-cap",
      "type": "org.springframework.util.unit.DataSize",
      "description": "Total size of log backups to be kept.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "0B"
    },

                                                     

                              

******************

设置日志级别

                       

命令格式:logging.level.<logger-name>=<level>

level 可选值:trace、debug、info、warn、error、fatal、off

                         

配置文件设置日志级别

logging:
  level:
    root: "warn"
    org.springframework.web: "debug"
    org.hibernate: "error"
    com.example.demo.controller.HelloController: debug

                               

环境变量设置日志级别:LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG

It’s also possible to set logging levels using environment variables. 
For example, LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG will set 
org.springframework.web to DEBUG
# 可使用环境变量设置日志级别,LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG,
# 会将org.springframework.web包的日志级别设置为debug


The above approach will only work for package level logging. 
Since relaxed binding always converts environment variables to lowercase, 
it’s not possible to configure logging for an individual class in this way. 
# 上述方法只能设置包的日志级别,
# 由于会将环境变量转换为小写,类的日志级别不能这么设置

If you need to configure logging for a class, you can use the 
SPRING_APPLICATION_JSON variable
# 可以使用SPRING_APPLICATION_JSON设置日志级别


SPRING_APPLICATION_JSON设置日志级别
java -jar demo.jar --spring.application.json='{"logging":{"level":{"com.example.demo.controller.HelloController":"debug"}}}'
java -jar demo.jar --spring.application.json='{"logging":{"level":{"com.example.demo.controller.HelloController":"debug"}}}'

                                        

                                  

******************

日志组

                     

It’s often useful to be able to group related loggers together so that 
they can all be configured at the same time. 
# 将相关日志(logger)组合在一起,可以方便的对这些日志进行管理

For example, you might commonly change the logging levels for all Tomcat 
related loggers, but you can’t easily remember top level packages.
# 例如,你可能经常改变tomcat日志,但是不能记住所有相关的包,
# 此时,可将相关的包建立为一个tomcat组合

                     

示例

logging:
  group:
    tomcat: "org.apache.catalina,org.apache.coyote,org.apache.tomcat"
# 定义tomcat日志组合:org.apache.catalina, org.apache.coyote,org.apache.tomcat

# 直接对日志组合设置日志级别
logging:
  level:
    tomcat: "debug"

                       

预置的日志组合

# web 日志组合
org.springframework.core.codec, 
org.springframework.http, 
org.springframework.web, 
org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans

# sql 日志组合
org.springframework.jdbc.core, 
org.hibernate.SQL, 
org.jooq.tools.LoggerListener

                      

                            

******************

log shutdown hook

                   

In order to release logging resources when your application terminates, 
a shutdown hook that will trigger log system cleanup when the JVM exits is provided. 
# shutdown hook可在jvm关闭的时候释放日志资源

This shutdown hook is registered automatically unless your application 
is deployed as a war file.
# 除非打包成war文件,shutdown hook会自动注册

If your application has complex context hierarchies the shutdown hook 
may not meet your needs. If it does not, disable the shutdown hook and 
investigate the options provided directly by the underlying logging system
# 在应用系统比较复杂的情况下,shutdown hook可能不符合需求,
# 这时可关闭shutdown hook自动注册功能

For example, Logback offers context selectors which allow each Logger 
to be created in its own context
# 例如,logback提供context selectors,这可以context创建logger,
# 这时就可能不需要注册shutdown hook

                  

关闭自动注册shutdown hook

logging:
  register-shutdown-hook: false

                              

                               

******************

自定义日志配置

                       

The various logging systems can be activated by including the appropriate libraries 
on the classpath and can be further customized by providing a suitable configuration 
file in the root of the classpath or in a location specified by the following Spring 
Environment property: logging.config
# 日志系统激活方式:导入相应jar包、在classpath或者指定路径(logging.config)中提供配置文件

You can force Spring Boot to use a particular logging system by using the
org.springframework.boot.logging.LoggingSystem system property. The value should be the 
fully qualified class name of a LoggingSystem implementation. 
# 可以使用系统变量org.springframework.boot.logging.LoggingSystem强制使用某个日志系统
# 这个值需要是LoggingSystem的实现类的全限定名

You can also disable Spring Boot’s logging configuration entirely by using a value of none
# 将org.springframework.boot.logging.LoggingSystem设置为none,
# 可以禁用springboot日志配置

Since logging is initialized before the ApplicationContext is created, it is not 
possible to control logging from @PropertySources in Spring @Configuration files. 
The only way to change the logging system or disable it entirely is via System properties
# 日志在ApplicationContext创建之前初始化,不能通过@PropertySources加载日志配置
# 唯一改变日志配置的方法就是使用系统变量

                                      

日志系统默认加载的配置文件

Logback ==> logback-spring.xml, logback-spring.groovy, 
            logback.xml, logback.groovy

Log4j2  ==> log4j2-spring.xml, log4j2.xml
JDK (Java Util Logging) ==> logging.properties

                          

配置文件使用注意

When possible, we recommend that you use the -spring variants for your logging 
configuration (for example, logback-spring.xml rather than logback.xml). If you use 
standard configuration locations, Spring cannot completely control log initialization
# 推荐使用 -spring后缀的配置文件(logback-spring.xml)
# 如果使用logback.xml,spring就不能完全控制日志初始化

There are known classloading issues with Java Util Logging that cause problems when 
running from an 'executable jar'. We recommend that you avoid it when running from an 
'executable jar' if at all possible
# java util logging在使用时会有一些问题,尽量避免使用

                           

spring配置 ==> 对应的系统配置

PID                               ==> PID(进程id)

logging.file.name                 ==> LOG_FILE               #日志文件名称,默认为spring.log
logging.file.path                 ==> LOG_PATH               #日志文件路径,同时设置以logging.file.name为准

logging.charset.console           ==> CONSOLE_LOG_CHARSET    #控制台字符集
logging.charset.file              ==> FILE_LOG_CHARSET       #日志文件字符集

logging.pattern.console           ==> CONSOLE_LOG_PATTERN    #控制台日志输出样式
logging.pattern.dateformat        ==> LOG_DATEFORMAT_PATTERN #日期输出样式
logging.pattern.file              ==> FILE_LOG_PATTERN       #日志文件输出样式
logging.pattern.level             ==> LOG_LEVEL_PATTERN      #日志级别(info、warn等)输出格式
                                                             #默认%5p,右对齐,占5个占位符,不足左边补空格

logging.exception-conversion-word ==> LOG_EXCEPTION_CONVERSION_WORD
                                                             #日志输出发生异常时,使用的转换文字


# spring-configuration-metadata.json

    {
      "name": "logging.pattern.console",
      "type": "java.lang.String",
      "description": "Appender pattern for output to the console. Supported only with the default Logback setup.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "%clr(%d{${LOG_DATEFORMAT_PATTERN:-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}"
    },
    {
      "name": "logging.pattern.dateformat",
      "type": "java.lang.String",
      "description": "Appender pattern for log date format. Supported only with the default Logback setup.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "yyyy-MM-dd HH:mm:ss.SSS"
    },
    {
      "name": "logging.pattern.file",
      "type": "java.lang.String",
      "description": "Appender pattern for output to a file. Supported only with the default Logback setup.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"
    },
    {
      "name": "logging.pattern.level",
      "type": "java.lang.String",
      "description": "Appender pattern for log level. Supported only with the default Logback setup.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "%5p"
    },

    {
      "name": "logging.exception-conversion-word",
      "type": "java.lang.String",
      "description": "Conversion word used when logging exceptions.",
      "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
      "defaultValue": "%wEx"
    },

                     

logback spring配置 ==> 对应的系统配置

logging.logback.rollingpolicy.file-name-pattern
==> LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN
# 默认为:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz).

logging.logback.rollingpolicy.clean-history-on-start
==> LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START
# 是否在启动时清理历史日志文件,默认为false

logging.logback.rollingpolicy.max-file-size
==> LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE
# 单个文件最大大小

logging.logback.rollingpolicy.total-size-cap
==> LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP
# 日志文件总大小,默认不设限

logging.logback.rollingpolicy.max-history
==> LOGBACK_ROLLINGPOLICY_MAX_HISTORY
# 日志文件保存的最长时间,默认为7天

                       

logback 配置使用示例

Notably, if you use Logback, you should use : as the delimiter 
between a property name and its default value and not use :-
# 属性名和默认值之间使用 “:”分隔,不要用“:-”

logging.pattern.level=user:%X{user:-gtlx} %5p  # user和%X{user}用 “:”间隔
                                         # %X{user:-gtlx},user如果没有,默认为gtlx

输出示例
2021-09-15 12:15:31.635 user:gtlx  INFO 936 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-09-15 12:15:31.657 user:gtlx  INFO 936 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 2.253 seconds (JVM running for 3.234)

**************

相关类与接口

                             

LogbackLoggingSystem

public class LogbackLoggingSystem extends Slf4JLoggingSystem {
                            //Slf4JLoggingSystem是AbstractLoggingSystem的子类

    。。。

    protected String[] getStandardConfigLocations() {
        return new String[]{"logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml"};
    }

                             

AbstractLoggingSystem

public abstract class AbstractLoggingSystem extends LoggingSystem {
    protected static final Comparator<LoggerConfiguration> CONFIGURATION_COMPARATOR = new LoggerConfigurationComparator("ROOT");
    private final ClassLoader classLoader;

    public AbstractLoggingSystem(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public void beforeInitialize() {
    }

    public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
        if (StringUtils.hasLength(configLocation)) {
            this.initializeWithSpecificConfig(initializationContext, configLocation, logFile);
        } else {
            this.initializeWithConventions(initializationContext, logFile);
        }
    }

    private void initializeWithSpecificConfig(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
        configLocation = SystemPropertyUtils.resolvePlaceholders(configLocation);
        this.loadConfiguration(initializationContext, configLocation, logFile);
    }

    private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {
        String config = this.getSelfInitializationConfig();
                        //先加载SelfInitializationConfig
        if (config != null && logFile == null) {
            this.reinitialize(initializationContext);
        } else {
            if (config == null) {
                config = this.getSpringInitializationConfig();
            }           //如果没有,则加载SpringInitializationConfig

            if (config != null) {
                this.loadConfiguration(initializationContext, config, logFile);
            } else {
                this.loadDefaults(initializationContext, logFile);
            }           //如果没有,则加载默认配置
        }
    }

    protected String getSelfInitializationConfig() {
        return this.findConfig(this.getStandardConfigLocations());
    }                   //"logback-test.groovy", "logback-test.xml", 
                        // "logback.groovy", "logback.xml"

    protected String getSpringInitializationConfig() {
        return this.findConfig(this.getSpringConfigLocations());
    }                   //"logback-test-spring.groovy", "logback-test-spring.xml", 
                        // "logback-spring.groovy", "logback-spring.xml"

    private String findConfig(String[] locations) {
        String[] var2 = locations;
        int var3 = locations.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String location = var2[var4];
            ClassPathResource resource = new ClassPathResource(location, this.classLoader);
            if (resource.exists()) {
                return "classpath:" + location;
            }            //在classpath路径下查找对应配置
        }

        return null;
    }

    protected abstract String[] getStandardConfigLocations();

    protected String[] getSpringConfigLocations() {
        String[] locations = this.getStandardConfigLocations();

        for(int i = 0; i < locations.length; ++i) {
            String extension = StringUtils.getFilenameExtension(locations[i]);
            locations[i] = locations[i].substring(0, locations[i].length() - extension.length() - 1) + "-spring." + extension;
        }

        return locations;
    }

    。。。

                             

LoggingSystem

public abstract class LoggingSystem {
    public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
    public static final String NONE = "none";
    public static final String ROOT_LOGGER_NAME = "ROOT";
    private static final LoggingSystemFactory SYSTEM_FACTORY = LoggingSystemFactory.fromSpringFactories();

    public LoggingSystem() {
    }

                                

                            

******************

logback 拓展

                    

Spring Boot includes a number of extensions to Logback that can help with advanced 
configuration. You can use these extensions in your logback-spring.xml configuration file
# springboot针对logback提供了一些拓展配置,可以在logback-spring.xml配置文件中进行设置

Because the standard logback.xml configuration file is loaded too early, you cannot use 
extensions in it. You need to either use logback-spring.xml or define a logging.config property
# 由于logback.xml加载的很早,因此不能使用拓展配置
# 可以在logback-spring.xml配置,或者使用logging.config指定自定义的配置文件

                           

profile 配置

The <springProfile> tag lets you optionally include or exclude sections of configuration 
based on the active Spring profiles. Profile sections are supported anywhere within the 
<configuration> element. Use the name attribute to specify which profile accepts the 
configuration. 
# springProfile可让配置在特定的环境下激活
# springProfile可在<configuration>内的任意地方使用

The <springProfile> tag can contain a profile name (for example staging) or a profile 
expression. A profile expression allows for more complicated profile logic to be expressed, 
for example production & (eu-central | eu-west)
# springProfile可包含profile、profile表达式


*************
示例

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev | staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="production & (eu-central | eu-west)">
    <!-- configuration to be enabled when the production and ("dev" or "staging") profiles are active -->
</springProfile>

<springProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

                            

springPropety 使用环境变量

The <springProperty> tag lets you expose properties from the Spring Environment for 
use within Logback. Doing so can be useful if you want to access values from your 
application.properties file in your Logback configuration. 
# springProperty可以实现在logback配置中使用application.properties中的属性

The tag works in a similar way to Logback’s standard <property> tag. However, rather than 
specifying a direct value, you specify the source of the property (from the Environment). 
# 这和property标签作用相似,但是property标签只能直接设值,springProperty可读取环境变量中的值

If you need to store the property somewhere other than in local scope, you can use the scope attribute. If you need a fallback value (in case the property is not set in the Environment), you can use the defaultValue attribute
# springProperty可设置属性的存储范围(scope设置,可选值local、context等)
# default可设置属性的默认值


***************
示例

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
        defaultValue="localhost"/>
# logback 属性值名称为fluent,作用范围是整个上下文
# myapp.fluentd.host读取属性文件中的值,默认值:localhost

<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>   # 引用属性值
    ...
</appender>

                         

                           

おすすめ

転載: blog.csdn.net/weixin_43931625/article/details/120284843