springboot+log4j日志配置

目录

1.log4j2配置

1.1 引入依赖

1.2 配置日志打印详细

2. 添加日志traceId

2.1 编写工具类

2.2 添加一个拦截器

2.3 添加配置

2.4 修改log4j2.yml日志配置

3.开启异步线程日志打印

3.1 引入依赖

3.2 JVM启动参数

3.3 验证是否开启异步日志打印

4. 常见问题

4.1 log4j2的配置不生效


日志是每个项目中必不可少的配置,主要用来运行情况和定位问题

以下为自己亲自测试的,如果大家有更好的方式,欢迎在下方留言!

1.log4j2配置

1.1 引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <!--去掉-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>1.5.6.RELEASE</version>
</dependency>

<dependency>  <!-- 支持识别yml配置 -->
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-yaml</artifactId>
</dependency>

1.2 配置日志打印详细

在resource目录下创建log4j2.yml文件

Appenders:
  Console:  #输出到控制台
    name: CONSOLE #Appender命名
    target: SYSTEM_OUT
    PatternLayout:
      pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n"
  RollingFile: # 输出到文件,超过256MB归档
    - name: ROLLING_FILE
      ignoreExceptions: false
      fileName: ./logs/hhmt-cpa.log
      filePattern: "./logs/$${date:yyyy-MM}/hhmt-cpa-%d{yyyy-MM-dd}-%i.log"
      PatternLayout:
        pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n"
      Policies:
        SizeBasedTriggeringPolicy:
          size: "10 KB"
      DefaultRolloverStrategy:
        max: 1000
Loggers:
  Root:
    level: info
    AppenderRef:
      - ref: CONSOLE
  Logger: #单独设置某些包的输出级别
    - name: com.hhmt.delivery #复数加上-(这里我设置的是包的根路径的包名)
      additivity: false #去除重复的log
      level: info
      AppenderRef:
        - ref: CONSOLE #复数加上-
        - ref: ROLLING_FILE #复数加上-

效果展示

如果想要尝试更加详细的可以使用这个:

#log4j 配置
#log4j定义了8个级别的log优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
#CONSOLE前面的DEBUG是控制台需要打印什么DEBUG级别以上的日志的信息
#log4j.rootLogger=DEBUG, CONSOLE, ERROR, WARN, INFO, DEBUG, ALL
log4j.rootLogger= DEBUG, CONSOLE, ERROR, WARN, INFO, DEBUG, ALL
#-----------------------------------------------------------------------------------------------------
#输出信息到控制台CONSOLE
log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Target = System.out
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
#-----------------------------------------------------------------------------------------------------
#输出ERROR 级别以上的日志到error.log
log4j.logger.ERROR=ERROR
log4j.appender.ERROR = org.apache.log4j.DailyRollingFileAppender
log4j.appender.ERROR.File =logs/error/error.log
log4j.appender.file.DatePattern ='.'yyyy-MM-dd
log4j.appender.ERROR.Threshold = ERROR
log4j.appender.ERROR.Append = true
log4j.appender.ERROR.layout = org.apache.log4j.PatternLayout
log4j.appender.ERROR.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
#-----------------------------------------------------------------------------------------------------
#输出WARN 级别以上的日志到warn.log
log4j.logger.WARN=WARN
log4j.appender.WARN = org.apache.log4j.DailyRollingFileAppender
log4j.appender.WARN.File =logs/warn/warn.log
log4j.appender.file.DatePattern ='.'yyyy-MM-dd
log4j.appender.WARN.Threshold = WARN
log4j.appender.WARN.Append = true
log4j.appender.WARN.layout = org.apache.log4j.PatternLayout
log4j.appender.WARN.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
#-----------------------------------------------------------------------------------------------------
#输出INFO级别以上的内容到info.log中  info日志每100MB创建一个新文件
log4j.logger.INFO=INFO
log4j.appender.INFO = org.apache.log4j.RollingFileAppender 
log4j.appender.ROLLING_FILE.MaxFileSize=100MB 
log4j.appender.INFO.File = logs/info/info.log
#log4j.appender.file.DatePattern ='.'yyyy-MM-dd
log4j.appender.INFO.Threshold = INFO
log4j.appender.INFO.Append = true
log4j.appender.INFO.layout = org.apache.log4j.PatternLayout
log4j.appender.INFO.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
#-----------------------------------------------------------------------------------------------------
#输出DEBUG 级别以上的日志到debugger.log
log4j.logger.DEBUG=DEBUG
log4j.appender.DEBUG = org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.MaxFileSize=100MB 
log4j.appender.DEBUG.File = logs/debugger/debugger.log
#log4j.appender.file.DatePattern ='.'yyyy-MM-dd
log4j.appender.DEBUG.Threshold = DEBUG
log4j.appender.DEBUG.Append = true
log4j.appender.DEBUG.layout = org.apache.log4j.PatternLayout
log4j.appender.DEBUG.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
#-----------------------------------------------------------------------------------------------------
#输出ALL级别的日志到all.log
log4j.logger.ALL=ALL
log4j.appender.ALL = org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.MaxFileSize=100MB 
log4j.appender.ALL.File = logs/all/all.log
#log4j.appender.file.DatePattern ='.'yyyy-MM-dd
log4j.appender.ALL.Threshold = ALL
log4j.appender.ALL.Append = true
log4j.appender.ALL.layout = org.apache.log4j.PatternLayout
log4j.appender.ALL.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
#-----------------------------------------------------------------------------------------------------

原文参考:【亲测有用】springboot + log4j2 日志按天并且按大小切割_u013282737的博客-CSDN博客_springboot 日志切割

2. 添加日志traceId

在传统系统中,如果能够提供日志输出,基本上已经能够满足需求的。但一旦将系统拆分成两套及以上的系统,再加上负载均衡等,调用链路就变得复杂起来。

特别是进一步向微服务方向演化,如果没有日志的合理规划、链路追踪,那么排查日志将变得异常困难。

比如系统A、B、C,调用链路为A -> B -> C,如果每套服务都是双活,则调用路径有2的三次方种可能性。如果系统更多,服务更多,调用链路则会成指数增长。

因此,无论是几个简单的内部服务调用,还是复杂的微服务系统,都需要通过一个机制来实现日志的链路追踪。让你系统的日志输出,像诗一样有形式美,又有和谐的韵律。

日志追踪其实已经有很多现成的框架了,比如Sleuth、Zipkin等组件。但这不是我们要讲的重点,本文重点基于Spring Boot、LogBack来手写实现一个简单的日志调用链路追踪功能。基于此实现模式,大家可以更细粒度的去实现。

2.1 编写工具类

package com.huachun.utils;

import java.util.UUID;

public class TraceIdUtils {

    private static final ThreadLocal<UUID> requestIdHolder = new ThreadLocal<>();

    private TraceIdUtils() {
    }

    /**
     * 生成traceId
     *
     * @return TraceId 基于UUID
     */
    public static String getTraceId() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    public static void generateRequestId() {
        requestIdHolder.set(UUID.randomUUID());
    }

    public static void generateRequestId(UUID uuid) {
        requestIdHolder.set(uuid);
    }

    public static UUID getRequestId() {
        return (UUID) requestIdHolder.get();
    }

    public static void removeRequestId() {
        requestIdHolder.remove();
    }
}
package com.huachun.utils;

import org.slf4j.MDC;
import org.springframework.util.StringUtils;

public class TraceIdContext {

    public static final String TRACE_ID_KEY = "requestId";

    public static void setTraceId(String traceId) {
        if (!StringUtils.isEmpty(traceId)) {
            MDC.put(TRACE_ID_KEY, traceId);
        }
    }

    public static String getTraceId() {
        String traceId = MDC.get(TRACE_ID_KEY);
        return traceId == null ? "" : traceId;
    }

    public static void removeTraceId() {
        MDC.remove(TRACE_ID_KEY);
    }

    public static void clearTraceId() {
        MDC.clear();
    }

}

2.2 添加一个拦截器

package com.huachun.filter;

import com.huachun.utils.TraceIdUtils;
import com.huachun.utils.TraceIdContext;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.AbstractRequestLoggingFilter;

import javax.servlet.http.HttpServletRequest;

public class TraceIdRequestLoggingFilter extends AbstractRequestLoggingFilter {
    @Override
    protected void beforeRequest(HttpServletRequest request, String message) {
        String requestId = request.getHeader(TraceIdContext.TRACE_ID_KEY);
        if (!StringUtils.isEmpty(requestId)) {
            TraceIdContext.setTraceId(requestId);
        } else {
            TraceIdContext.setTraceId(TraceIdUtils.getTraceId());
        }
    }

    @Override
    protected void afterRequest(HttpServletRequest request, String message) {
        TraceIdContext.removeTraceId();
    }
}

2.3 添加配置

package com.huachun.config;

import com.huachun.filter.TraceIdRequestLoggingFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TraceIdConfig {

    @Bean
    public TraceIdRequestLoggingFilter traceIdRequestLoggingFilter() {
        return new TraceIdRequestLoggingFilter();
    }
}

2.4 修改log4j2.yml日志配置

Appenders:
  Console:  #输出到控制台
    name: CONSOLE #Appender命名
    target: SYSTEM_OUT
    PatternLayout:
      pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS}:%4p [%t] [%X{requestId}] (%logger{36}:%L) - %m%n"

  RollingFile: # 输出到文件,超过256MB归档
    - name: ROLLING_FILE
      ignoreExceptions: false
      fileName: ./log_demo/log_demo.log
      filePattern: "./log_demo/$${date:yyyy-MM}/log_demo-%d{yyyy-MM-dd}-%i.log"
      PatternLayout:
        pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS}:%4p [%t] [%X{requestId}] (%logger{36}:%L) - %m%n"
      Policies:
        SizeBasedTriggeringPolicy:
          size: "52 MB"
      DefaultRolloverStrategy:
        max: 1000
Loggers:
  Root:
    level: info
    AppenderRef:
      - ref: CONSOLE
  Logger: #单独设置某些包的输出级别
    - name: org.huachun #复数加上-(这里我设置的是包的根路径的包名)
      additivity: false #去除重复的log
      level: info
      AppenderRef:
        - ref: CONSOLE #复数加上-
        - ref: ROLLING_FILE #复数加上-

主要替换了原有的输出格式

pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS}:%4p [%t] [%X{requestId}] (%logger{36}:%L) - %m%n"

在value属性的表达式中,我们新增了自定义的变量值requestId,通过“[%X{requestId}]”的形式来展示。

这个requestId便是我们用来追踪日志的唯一标识。如果一个请求,从头到尾都使用了同一个requestId便可以把整个请求链路串联起来。如果系统还基于EKL等日志搜集工具进行统一收集,就可以更方便的查看整个日志的调用链路了。

参考原文:基于SpringBoot实现让日志像诗一样有韵律(日志追踪)_程序新视界的博客-CSDN博客_springboot 日志追踪框架

3.开启异步线程日志打印

3.1 引入依赖

<dependency>
  <groupId>com.lmax</groupId>
  <artifactId>disruptor</artifactId>
  <version>3.4.2</version>
</dependency>

3.2 JVM启动参数

需要添加在JVM启动参数的地方

-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

错误的方式:

System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

3.3 验证是否开启异步日志打印

 

原文参考: Springboot配置log4j2异步输出日志_强哥叨逼叨的博客-CSDN博客

4. 常见问题

4.1 log4j2的配置不生效

问题描述:参照上面的配置,在其他项目中是可以正常输出配置格式的日志,但是到了另一个项目就无法正常输出了

但是在另一个项目中始终无法正确输出配置的格式

问题原因:

解决办法: 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值