目的:
利用log4j2进行请求中的手机号码的收集,并将收集到的日志文件存放在共享磁盘里。
问题:
由于多台服务器写日志,那么就需要给每台服务器打印的日志文件加个前缀名,以免冲突。
解决方案:
参考:http://logging.apache.org/log4j/2.0/manual/lookups.html#SystemPropertiesLookup
解决方案一:
可以选着采用获取系统变量的方式进行日志文件名的个性化。
引用:https://jingyan.baidu.com/article/597a0643207829312b5243e3.html
但是需要注意的是,在配置好环境变量后需要重启IDE,不然会扑街,就是${env:LOG_NAME}直接显示的情况。
解决方案二:
采用System Properties Lookup,虽然官网的介绍非常简单,但是使用起来就很蛋疼,怎么着都不管用。折腾了大把时间,才搞出来,分享一下吧:
log4j2.yml
Configuration:
status: warn
Properties: # 定义全局变量
Property: # 缺省配置(用于开发环境)。其他环境需要在VM参数中指定,如下:
#测试:-Dlog.level.console=warn -Dlog.level.xjj=trace
#生产:-Dlog.level.console=warn -Dlog.level.xjj=info
- name: log.level.console
value: trace
- name: log.level.hbc.api
value: trace
- name: log.path
value: ../log4j2logs/appspider
- name: phone.path
value: /data1/appspider/data/phonefiles/in
- name: project.name
value: global
- name: phonefile.name
value: phone
Appenders:
Console: #输出到控制台
name: CONSOLE
target: SYSTEM_OUT
ThresholdFilter:
level: ${sys:log.level.console} # “sys:”表示:如果VM参数中没指定这个变量值,则使用本文件中定义的缺省全局变量值
onMatch: ACCEPT
onMismatch: DENY
PatternLayout:
pattern: "%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread](%file:%line) - %m%n"
RollingRandomAccessFile: # 输出到文件
- name: ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/${project.name}.log
filePattern: "${log.path}/${project.name}.%d{yyyy-MM-dd-HH}.log"
PatternLayout:
pattern: "%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread](%file:%line) - %m%n"
Policies:
TimeBasedTriggeringPolicy:
interval: 1
modulate: true
# SizeBasedTriggeringPolicy:
# size: "128 MB"
# DefaultRolloverStrategy:
# max: 1000
- name: PHONE_FILE
ignoreExceptions: true # 是否忽略异常
fileName: ${phone.path}/${sys:LOG_PREFIX}.${phonefile.name}.log # 日志名称,可以引用系统变量但是注意重启idea才能加载
filePattern: "${phone.path}/${sys:LOG_PREFIX}.${phonefile.name}.%d{yyyyMMdd}.txt" # 回滚后文件名称
PatternLayout:
pattern: "%m%n" # 打印内容格式
Policies:
TimeBasedTriggeringPolicy:
interval: 1
modulate: true
DefaultRolloverStrategy: 7 # 最大保留个数
Loggers:
Root:
level: info
AppenderRef:
- ref: CONSOLE
- ref: ROLLING_FILE
Logger: # 配置特殊的Log级别,方便调试
- name: sys:log.level.hbc.api
additivity: false
level: ${sys:log.level.hbc.api}
AppenderRef:
- ref: CONSOLE
- ref: ROLLING_FILE
- name: com.hbc.api.common.collect.CollectPhoneToFile
additivity: false
level: info
AppenderRef:
- ref: PHONE_FILE
fileName: ${phone.path}/${sys:LOG_PREFIX}.${phonefile.name}.log
对应的java代码:
public class CollectPhoneToFile {
private static Logger logger ;
//遗留一个问题,每次启动项目多生成一个${sys文件,后续再处理吧
static {
System.setProperty("LOG_PREFIX", getIpAdress());
LoggerContext ctx =(LoggerContext) LogManager.getContext(false);
ctx.reconfigure();
logger = LoggerFactory.getLogger(CollectPhoneToFile.class);
}
public static void write(String info){
logger.info(info);
}
/**
* 获取IP地址
*
* @return IP地址
*/
private static String getIpAdress(){
String serverIP = "" ;
try{
serverIP = InetAddress.getLocalHost().getHostAddress();
}catch(Exception e){
e.printStackTrace() ;
}
return serverIP ;
}
其中绝大部分分人卡在下面两句:
LoggerContext ctx =(LoggerContext) LogManager.getContext(false);
ctx.reconfigure();
但是按照我的方法解决后,还是会遗留一个问题。就是系统启动时多生产了一个${sys:LOG_PREFIX}.phone.log文件,我还没有找到优雅一点的办法解决它,暂且先放放。
解决方案三;
如果你只是想在文件里搞个特殊名堂,那么代码会简单很多:
public class CollectPhoneToFile {
private static Logger logger ;
//遗留一个问题,每次启动项目多生成一个${sys文件,后续再处理吧
static {
System.setProperty("LOG_PREFIX", getIpAdress());
// LoggerContext ctx =(LoggerContext) LogManager.getContext(false);
// ctx.reconfigure();
logger = LoggerFactory.getLogger(CollectPhoneToFile.class);
}
public static void write(String info){
logger.info(info);
}
/**
* 获取IP地址
*
* @return IP地址
*/
private static String getIpAdress(){
String serverIP = "" ;
try{
serverIP = InetAddress.getLocalHost().getHostAddress();
}catch(Exception e){
e.printStackTrace() ;
}
return serverIP ;
}
}
但是,这样做的话,文件名就无法个性化。其实可以找到一个好一点的办法就是讲静态块里的代码放在项目启动最前面进行设定System.setProperty("LOG_PREFIX", getIpAdress());,由于我是用的是springboot,不太好找那个地方,也试着去搞一搞结果都不是很理想。
--------------- 华丽的分割线 -----------
各位看官,谁有更好的方法可以推荐一下哦!!!