千家信息网

log4j如何控制日志输出文件名称

发表于:2025-11-08 作者:千家信息网编辑
千家信息网最后更新 2025年11月08日,小编给大家分享一下log4j如何控制日志输出文件名称,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!log4j控制日志输出文
千家信息网最后更新 2025年11月08日log4j如何控制日志输出文件名称

小编给大家分享一下log4j如何控制日志输出文件名称,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

    log4j控制日志输出文件名称

    1. 第一种方式

    在类对象中用如下方式定义logger变量

    private static Logger logger = Logger.getLogger("lemmaXml");

    这样通过名称的方式获取logger,需要在log4j.properties文件中定义一个名称为lemmaXml的appender,配置如下:

    log4j.logger.lemmaXml=INFO,lemmaXmllog4j.appender.lemmaXml=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.lemmaXml.Threshold=DEBUGlog4j.appender.lemmaXml.File=${catalina.home}/logs/lemmaXml.loglog4j.appender.lemmaXml.layout=org.apache.log4j.PatternLayoutlog4j.appender.lemmaXml.layout.ConversionPattern=%5p %d{yyyy-MM-dd HH:mm:ss} %m %n

    上述配置说明,名称为lemmaXml的appender,是每天形成一个日志文件,日志文件的名称为

    ${catalina.home}/logs/lemmaXml.log

    日志的格式为

    %5p %d{yyyy-MM-dd HH:mm:ss} %m %n

    2. 第二种方式(这种方式亲测正确)

    在类对象中用如下方式定义logger变量

    import org.apache.log4j.Logger;private static Logger logger = Logger.getLogger(ExportLemmaManagerService.class);

    即,通过类的参数来获取logger变量,此时必然也需要在log4j.properties文件有关于该对象日志文件的输出配置,当然这里的配置不是针对每个类专门配置,而是针对一个路径整体配置,即,你可以配置某个目录下的所有类方式的输出文件的文件名称,如下

    log4j.rootLogger=info,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Threshold=DEBUGlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n  log4j.logger.com.soso.baike.service=DEBUG,ServiceLoglog4j.appender.ServiceLog=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.ServiceLog.Threshold=DEBUGlog4j.appender.ServiceLog.File=${catalina.home}/logs/service.loglog4j.appender.ServiceLog.MaxBackupIndex=10log4j.appender.ServiceLog.layout=org.apache.log4j.PatternLayoutlog4j.appender.ServiceLog.layout.ConversionPattern=%5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n

    上述配置了目录com.soso.baike.service下的输出文件方式,上述ExportLemmaManagerService类就是在该包下,所以用该包下的类方式来定义logger的话,输出的文件就都在service.log文件中,每天生成一个新的日志文件。

    如何随心所欲地自定义log4j输出格式

    在某种情况下,我们需要在不影响原有代码的基础上自定义log4j的输出格式。

    例如这样的需求,硬性规定了项目的日志格式为:

    日期 日志等级 ClassName:line - [版本号] [请求ip地址] [项目应用名称] [服务接口模块] [模块方法] [业务参数1] [业务参数2] [业务参数3] 日志详细内容(必须为json格式)

    示例:

    2018-05-10 14:04:50,972 INFO ViolationService:51 - [v1.0.0] [192.168.137.47] [merchant-service.cx580.com] [OrderController] [messageList] [null] [] [] {"body":"订单状态消息列表resp:{\"code\":1000,\"msg\":\"成功\"}"}

    其中:

    • 版本号是指当前服务接口实际的版本信息,例如V1.0.1;

    • 请求ip地址为用户真实的请求ip;

    • 项目应用名称为项目的名称或者标识,例如支付服务定义应用名称为payService;

    • 服务接口模块是指请求接口对应的模块代码,例如请求订单接口,则接口模块为OrderControlller;

    • 模块方法是指接口对应的请求方法,例如下单接口对应模块方法为createOrder;

    • 业务参数1可根据实际情况写入相应的业务数据,录入订单号orderId,该参数可为空;

    • 业务参数2同上;

    • 业务参数3同上;

    • 日志详细内容是指请求接口时需打印出来的描述信息,例如创建订单异常时,在异常捕捉方法体中描述异常详细信息,日志内容需定义到一个json结构中。

    以上是我遇到的场景,这时在不影响原有项目代码的基础上,我们做出日志格式的调整,使用如下方案:

    1.通过log4j的占位替换符%X{}配合MDC格式化日志,使用AOP切面在请求线程开始处填充替换符变量

    2.继承log4j的具体appender类,重写subAppend方法,修改日志输出的内容格式。

    此时log4j文件如下

    log4j.rootCategory=INFO, stdout, file, errorfile#log4j.category.com.cx=DEBUGlog4j.logger.error=errorfile log4j.appender.stdout=com.test.common.GrayLogConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L%X{log_version}%X{log_ip}%X{log_item}%X{log_module}%X{log_method}%X{log_req_params} %m%n log4j.appender.file=com.test.common.GrayLogDailyRollingFileAppenderlog4j.appender.file.file=${log.dir}/${spring.application.name}.loglog4j.appender.file.DatePattern='.'yyyy-MM-ddlog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L%X{log_version}%X{log_ip}%X{log_item}%X{log_module}%X{log_method}%X{log_req_params} %m%n log4j.appender.errorfile=com.test.common.GrayLogDailyRollingFileAppenderlog4j.appender.errorfile.file=${log.dir}/${spring.application.name}_error.loglog4j.appender.errorfile.DatePattern='.'yyyy-MM-ddlog4j.appender.errorfile.Threshold = ERRORlog4j.appender.errorfile.layout=org.apache.log4j.PatternLayoutlog4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L%X{log_version}%X{log_ip}%X{log_item}%X{log_module}%X{log_method}%X{log_req_params} %m%n

    在log4j.properties文件,我们做了两个变动,一个是添加了%X{value}的变量,另一个则是将原本的DailyRollingFileAppender修改成了com.test.common.GrayLogConsoleAppender。

    处理log4j的变量,对代码进行controller切面,在一个http请求java的入口中放入线程变量,该线程变量在当次http请求生命周期内生效。

    切面代码如下:

    @Around("execution(public * com.test.controller..*.*(..))")    public Object aroundController(ProceedingJoinPoint joinPoint) {        ServletRequestAttributes attributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        HttpServletRequest request =attributes.getRequest();        String execIp = request.getHeader("X-Real-IP");        if(StringUtils.isBlank(execIp)){            execIp=request.getRemoteAddr();        }        String execClass= joinPoint.getTarget().getClass().getSimpleName();        String execMethod = joinPoint.getSignature().getName();        Map map = request.getParameterMap();        List paramsList = new ArrayList<>();        for(Map.Entry m : map.entrySet()){            String [] value = m.getValue();            paramsList.add( m.getKey() + "=" + StringUtils.join(value,","));        }         String execParams = "[" + StringUtils.join(paramsList,"&") + "] [] []";        MDC.put("log_version"," - [V1.0.0]");        MDC.put("log_item"," [violation-mini]");        MDC.put("log_module"," [" + execClass + "]");        MDC.put("log_method"," [" + execMethod+ "]");        MDC.put("log_req_params"," " + execParams);        MDC.put("log_ip"," [" + execIp+ "]");        Object result= null;        try {            result = joinPoint.proceed();        } catch (Throwable throwable) {            LOGGER.error("方法异常:",throwable);        }        return result;    }

    至此,格式中的MDC变量都已被放入成功。

    下一步,将原本的日志内容套上json外套。

    新建GrayLogConsoleAppender类继承具体的appender类

    代码如下:

    package com.test.common; import net.sf.json.JSONObject;import org.apache.commons.lang.StringUtils;import org.apache.log4j.ConsoleAppender;import org.apache.log4j.spi.LoggingEvent;import org.apache.log4j.spi.ThrowableInformation; import java.lang.reflect.Field; /** * @Author: Lxx * @Description: * @Date: Created in 17:29 2018/5/30 */public class GrayLogConsoleAppender extends ConsoleAppender {    @Override    protected void subAppend(LoggingEvent event) {        try {            Class clazz = LoggingEvent.class;            Field filed = clazz.getDeclaredField("throwableInfo");            filed.setAccessible(true);            Object exception = filed.get(event);            JSONObject json = new JSONObject();            if(exception != null){                if(exception instanceof ThrowableInformation){                    ThrowableInformation throwableInformation = (ThrowableInformation) exception;                    String [] details = throwableInformation.getThrowableStrRep();                    String error_msg = StringUtils.join(details,"\r\n");                    json.put("exception",error_msg);                }            }            filed.set(event,null);            boolean flag = false;            Field filed1 = clazz.getDeclaredField("message");            filed1.setAccessible(true);            Object message = filed1.get(event);            if (message instanceof String) {                String msg = (String) message;                if (message != null) {                    flag = true;                }                json.put("body", msg);                filed1.set(event, json.toString());            }            if(!flag){                Field filed2 = clazz.getDeclaredField("renderedMessage");                filed2.setAccessible(true);                Object message2 = filed2.get(event);                if (message2 instanceof String) {                    String msg = (String) message2;                    json.put("body", msg);                    filed2.set(event, json.toString());                }            }        } catch (Exception e) {            e.printStackTrace();        }        super.subAppend(event);    }}

    至此,已为日志内容套上json外套,并且当有异常日志时,将异常的堆栈信息放入json的exception中输出出来,不打印堆栈信息。

    最终结果:

    2018-06-09 00:48:31,849 INFO LogAspect:65 - [V1.0.0] [223.88.53.135] [violation-mini] [TestController] [queryList] [appName=abc&authType=test&avatar=&nickName=&token=asdfasdfadsfasdf&userId=asdfasdfasdfasdf&userType=aaaaa] [] [] {"body":"结果为:ResponseResult{code='0', msg='null', errormsg='查询成功', data={}, successFlag=false}"}

    以上是"log4j如何控制日志输出文件名称"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

    日志 文件 名称 输出 变量 接口 方式 格式 内容 参数 配置 业务 方法 模块 代码 信息 项目 订单 服务 控制 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 噗嗤网络技术 小学生网络安全图片 三年级 付大额软件开发费账务处理 服务器组建台式机 云计算机网络技术主要学什么 仿真模拟软件开发公司 北京网络技术咨询优点 明日之后赛尔线有哪些服务器 郑州慧牛网络技术有限公司 论网络安全英语作文 连接不可用服务器 政协网络安全管理相关制度和规定 渗透测试转网络安全 江夏区翻译服务器 表格中数据库的基本功能 贵阳学网络技术中专学校 广东东莞兔印网络技术有限公司 昌平区网络技术咨询收费 合肥坤泰网络技术有限公司 拼多多软件开发招聘 网络安全公司360排名多少 医疗数据库档案查询 物理服务器与云服务器的共同点 云计算机网络技术主要学什么 连云港戴尔服务器 山西云搜网络技术怎么样 大专自学数据库好找人吗 中软国际软件开发定向委培生 长沙网络技术员招聘信息 太阳能控制器软件开发
    0