应用日志配置

对应 org.springframework.boot.logging.LoggingSystemProperties

logging:
  config: classpath:log4j2-spring.xml
  level:
    root: info
    io.undertow.server: trace
    org.xnio.nio: trace
  path:
  file: /data/logs/${laix.config.name}/${laix.config.name}.logLoggingEventCompositeJsonEncoder
    max-size: 150MB
    max-history: 7
  pattern:
    file: '%d{yyyy-MM-dd HH:mm:ss.SSS}{GMT+8} %-4level [%thread] ${laix.config.name} %equals{%X{X-B3-TraceId}}{}{non_trace} %logger{50} - %.-2048msg%n'
    #logback_file: '%d{yyyy-MM-dd HH:mm:ss.SSS,Asia/Shanghai} %-4level [%thread] ${laix.config.name} %X{X-B3-TraceId:-non_trace} %logger{50} - %.-2048msg%n'
    console: '%d{yyyy-MM-dd HH:mm:ss.SSS,Asia/Shanghai} %-4level [%thread] ${laix.config.name} %X{X-B3-TraceId:-non_trace} %logger{50} - %.-2048msg%n'
# 暴力 json pattern,无法处理换行型异常如错误堆栈
#   console: '{
#                               "Time": "%d{yyyy-MM-dd HH:mm:ss.SSS,Asia/Shanghai}",
#                               "level": "%level",
#                               "Thread":"%thread",
#                               "Project":"${laix.config.name}",
#                               "TraceId": "%mdc{X-B3-TraceId:-non_trace}",
#                               "Logger": "%logger",
#                               "Message": "%.-2048msg"
#                             }%n'
#    # <https://logging.apache.org/log4j/2.x/manual/layouts.html>
    exception-conversion-word: '%wEx'

org.springframework.boot.context.logging.LoggingApplicationListener 会侦听 ApplicationStartingEvent, ApplicationEnvironmentPreparedEvent, ApplicationPreparedEvent 三事件进行日志系统初始化。

private void onApplicationStartingEvent(ApplicationStartingEvent event) {
		this.loggingSystem = LoggingSystem
				.get(event.getSpringApplication().getClassLoader());
		this.loggingSystem.beforeInitialize();
	}

private void onApplicationEnvironmentPreparedEvent(
		ApplicationEnvironmentPreparedEvent event) {
	if (this.loggingSystem == null) {
		this.loggingSystem = LoggingSystem
				.get(event.getSpringApplication().getClassLoader());
	}
	initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader());
}

private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
	ConfigurableListableBeanFactory beanFactory = event.getApplicationContext()
			.getBeanFactory();
	if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
		beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
	}
}

Spring Boot 抽象了配置的输出格式(pattern),路径/文件,Logger 的打印级别,日志系统的配置文件(logging.config)。当 logging.config 不为空字符串时,会优先使用 logging.config 声明的配置文件资源,该资源可以是 Spring Resource 支持的任意文件(包括 http 链接)。

可以通过 logging.level.root 设置全局的 Logger 打印级别,针对不同 Logger 可以设置不同打印级别,具体 Logger 设置覆盖全局设置。Logger 的管理应该是通过 apache commons logging 实现?

由于 Spring Boot 只依赖于 commons-logging, 因此项目可以自由使用 logback, log4j 和 jul

logback 配置动态性支持好于 log4j2

log*-spring.xml 寻找规则

日志实现乱码问题

常用框架 Logger

# tomcat socket 连接等
org.apache.coyote: debug
org.apache.catalina.connector: debug
# undertow socket 连接等
io.undertow.server: trace
org.xnio.nio: trace
# Ribbon LoadBalancer 负载均衡选择实例 IP 日志
logging.level.com.netflix.loadbalancer.LoadBalancerContext: debug
# netty 关键 debug 日志
# spring 2.0.x reactor.netty.ipc
# spring 2.1.x reactor.netty
reactor.netty.http.server.AccessLog: debug
reactor.ipc.netty.channel.ContextHandler: debug
reactor.ipc.netty.http.server.HttpServer: debug
reactor.ipc.netty.http: debug
reactor.netty.http: debug
io.netty.util.concurrent: debug
io.netty.channel: debug
reactor.left.loggingHandler: debug
io.netty.handler.logging.LoggingHandler: debug
# mybatis sql 语句
com.xxx.app.mapper: debug
# ribbon load balance & CircuitBreaker
com.netflix.loadbalancer.LoadBalancerContext: debug #com.netflix.loadbalancer.LoadBalancerContext#getServerFromLoadBalancer
org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryPolicy: debug
# spring retry
org.springframework.retry.support: debug

netty access

设置 -Dreactor.netty.http.server.accessLogEnabled=true

设置 reactor.netty.http.server.AccessLog=debug

reactor.netty.http.server.AccessLog - 0:0:0:0:0:0:0:1%0 - - [10/Sep/2019:11:59:50 +0800] "GET /alter HTTP/1.1" 200 32 8080 4415 ms