两种方式实现 log4j 打印 pod ip

1,276 阅读1分钟

为什么需要打印 pod ip ?

  • pod ip 是 k8s 每个节点的 IP 会变化;
  • 可以从日志中判断请求打到了哪个 pod 节点;

如何打印?

log4j 中内置许多格式化符号 p% %t ...

我们这次打印的 POD IP 不在其中,但思路也是搞一个这种 格式化 的符号怎么搞呢?两种方式

第一种

借助 Java System 类、搞一个变量放在内存中;

@Configuration
public class LogIpConfiguration {

    private String getLocalIp() {
        try {
            // 通过本机名去获取地址
            return InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            return "127.0.0.1";
        }
    }

    /**
     * 设置 "local-ip" system 变量,给log4j2 配置使用:
     * 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次
     * 类似于Serclet的inti()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
     */
    @PostConstruct
    public void postConstruct() {
        String localIp = getLocalIp();
        System.setProperty("ip", localIp);
    }

}

第二种

借助 Log4J 自己的 MDC 、添加过滤器实现,感觉这个东西和 ThreadLocal 大同小异,ThreadLocal(解决多线程中相同变量的访问冲突问题)

@Component
@Slf4j
public class LoggerMdcFilter extends OncePerRequestFilter implements Filter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            // 获取 pod ip
            String podIp = new InetUtils(new InetUtilsProperties()).findFirstNonLoopbackHostInfo().getIpAddress();
            MDC.put("POD_IP", podIp);
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            log.info("LoggerMdcFilter: doFilterInternal exception {}", e.getMessage());
        }
    }
}
@Configurable
public class FilterConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new LoggerMdcFilter());
        return registrationBean;
    }
}

log4j 中使用

<!--处理所有级别的日志-->
<RollingFile name="RollingFileAll" fileName="/data/ark/logs/promotion/all.log"
             filePattern="/data/ark/logs/promotion/$${date:yyyy-MM}/all-%d{yyyy-MM-dd}-%i.log">
    <PatternLayout
            pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%X{POD_IP}] %-5level - [%thread] %class{36} [%traceId] %L %M - %msg%xEx%n"/>
    <Policies>
        <SizeBasedTriggeringPolicy size="500 MB"/>
        <TimeBasedTriggeringPolicy/>
    </Policies>
</RollingFile>