为什么需要打印 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>