前言
随着项目规模的越来越大,会不断的引入新的模块,不同的模块都会打印自己的日志,最后就造成日志根本没法查看,比如我自己的项目中,就存在以下这些日志:
这其中,消息日志和后台线程的日志数据量非常庞大,如果所有日志打印在一个文件中,使用tail -f log.log文件,会发现日志在快速的滚动,根本无法查看甚至定位某一个具体的SQL或者Service访问日志。
解决方法就是可以将不同的日志加以分类输出,这样相互的日志不影响,尤其重要的接口访问日志,能够很方便的定位和排查问题。
步骤1:在log4j.properties中配置
先贴一下我自己所有的log4j.properties配置:
log4j.rootLogger=INFO, console, file log4j.appender.console=net.czt.log.AsyncConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d [%t] %-5p crazyant-web %-17c{2} (%13F:%L) %X{USER_ID}|%X{USER_IP}|%X{SERVER_ADDRESS}|%X{SERVER_NAME}|%X{REQUEST_URI}|%X{SESSION_ID} - %m%n log4j.appender.console.bufferSize=10000 log4j.appender.console.encoding=UTF-8 log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.file=/home/work/apache-tomcat-6.0.39/logs/crazyant.log log4j.appender.file.MaxBackupIndex=5 log4j.appender.file.MaxFileSize=1GB log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[%-5p] crazyant-web %d{yyyy-MM-dd HH:mm:ss,SSS} %X{USER_ID}|%X{USER_IP}|%X{SERVER_ADDRESS}|%X{SERVER_NAME}|%X{REQUEST_URI}|%X{SESSION_ID} method:%l%n%m%n log4j.appender.file.bufferSize=10000 log4j.appender.file.encoding=UTF-8 log4j.logger.net.czt.crazyant.msg=DEBUG, message log4j.additivity.net.czt.crazyant.msg=false log4j.appender.message=org.apache.log4j.RollingFileAppender log4j.appender.message.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_message.log log4j.appender.message.Append=true log4j.appender.message.MaxFileSize=1GB log4j.appender.message.MaxBackupIndex=5 log4j.appender.message.layout=org.apache.log4j.PatternLayout log4j.appender.message.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n log4j.appender.message.encoding=UTF-8 log4j.logger.net.czt.crazyant.async.service=DEBUG, async log4j.additivity.net.czt.crazyant.async.service=false log4j.appender.async=org.apache.log4j.RollingFileAppender log4j.appender.async.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_async.log log4j.appender.async.Append=true log4j.appender.async.MaxFileSize=1GB log4j.appender.async.MaxBackupIndex=5 log4j.appender.async.layout=org.apache.log4j.PatternLayout log4j.appender.async.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n log4j.appender.async.encoding=UTF-8 log4j.logger.net.czt.orm.mybatis.SqlMonitorManager=DEBUG, showsql log4j.additivity.net.czt.orm.mybatis.SqlMonitorManager=false log4j.logger.net.czt.transaction.interceptor.SmartTransactionInterceptor=DEBUG, showsql log4j.additivity.net.czt.transaction.interceptor.SmartTransactionInterceptor=false log4j.appender.showsql=org.apache.log4j.RollingFileAppender log4j.appender.showsql.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_sql.log log4j.appender.showsql.Append=true log4j.appender.showsql.MaxFileSize=1GB log4j.appender.showsql.MaxBackupIndex=5 log4j.appender.showsql.layout=org.apache.log4j.PatternLayout log4j.appender.showsql.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n log4j.appender.showsql.encoding=UTF-8 log4j.logger.net.czt.crazyant.service=DEBUG, service log4j.additivity.net.czt.crazyant.service=false log4j.appender.service=org.apache.log4j.RollingFileAppender log4j.appender.service.File=/home/work/apache-tomcat-6.0.39/logs/crazyant_service.log log4j.appender.service.Append=true log4j.appender.service.MaxFileSize=1GB log4j.appender.service.MaxBackupIndex=5 log4j.appender.service.layout=org.apache.log4j.PatternLayout log4j.appender.service.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n log4j.appender.service.encoding=UTF-8
在配置文件的下方,可以方便的看到,我将message(消息)、async(后端线程)、showsql(数据库日志)、service(接口调用)分别输出到了不同的日志文件。
其中的一些解释:
log4j.rootLogger=INFO, console, file
log4j有一个rootLogger和普通Logger的概念,默认情况下我们只需要一个rootLogger,就是所有的日志只会输出到这一个日志文件中。
看一下普通Logger的配置(以接口日志service为例):
1、log4j.logger.net.czt.crazyant.service=DEBUG, service
这句中的”net.czt.crazyant.service”,表示该普通logger日志配置生效的package的完全路径
其中色service,表示该普通logger的名字
2、log4j.additivity.net.czt.crazyant.service=false
其中的”net.czt.crazyant.service”,和上面的相同,表示该配置项针对的package
该句配置的意思,是不要将该package的日志输出到rootLogger日志中,只输出到自己配置的日志就行了;
3、log4j.appender.service=org.apache.log4j.RollingFileAppender,以及该配置段下面的配置项
这里的”service”字符串,和上面的第一个配置项的”service”相同,表示对该普通Logger的配置;
下方的配置项和rootLogger相同,表示每天输出文件、编码UTF8、分片规则、每行的输出模式等等
我自己遇到的问题,是上面的log4j.properties配置好以后,发现各个日志文件创建了,但是里面都没有内容,这是为啥呢?来看下面第二个注意的地方;
步骤2、输出日志时需要设定日志对象对应的具体Class
什么意思呢?上面的配置项中,有一个”net.czt.crazyant.service”的package字符串,那么我们自己想一下,log4j是怎样将不同package中的logger日志输出到不同文件呢,想一下会有两种方法:
1、采用intercepter或者aop的方式,log4j自己检测日志输出,检测到日志产生于哪个package,就将其输出到对应文件中;
2、由用户传一个Class参数,log4j获取该Class对应的Package,以此为准,来定位不同的日志文件;
看一下代码,显然log4j用的是后一种简单直接的方式:
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class MyClassImpl implements MyClass { /** * loger */ private static final Log logger = LogFactory.getLog(MyClassImpl.class); /** * my func */ public void myfunc() { logger.info("call method myfunc."); } }
在logger = LogFactory.getLog(MyClassImpl.class)中,传入了使用该logger的Class参数,而该Class被反射取到的package地址,就是log4j用来输出日志的package地址。
这种做法也有强大的地方,方便逻辑上的日志归类,比如很多代码不属于一个package,但是它们逻辑上属于一起的,举个例子,消息的处理不只是接口调用Service这个package,可能还会调用发送msg的操作,如果想把msg的package中一些日志也输出到Service,那么在这个msg的logger初始化的时候,传入一个Serivice的Class就行了。
或者对于某一类的所有日志来说,它们所有的logger对象,都来自封装好的单个对象实例即可,而这个单个对象实例传入的参数只有一个,用于标识这个逻辑归类即可。
总结
在Log4j.properties中,支持package或者具体class的日志单独输出,但是也需要代码中logger初始化的时候,能和日志配置中的package对应上。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
对于一些人来说,这可能是一个非常简单的问题,但就我个人而言,Log4j配置非常困难,学习执行脑部手术可能没有那么困难。 我正试图让多个日志记录者登录到不同的文件。这是我的log4j中的内容。属性文件: 这是我的(非常简单的)Java应用程序用于测试配置: 我有两个问题: 有一个问题,我总是在
本文向大家介绍Log4j按级别输出日志到不同文件的实现方法,包括了Log4j按级别输出日志到不同文件的实现方法的使用技巧和注意事项,需要的朋友参考一下 如下所示: 以上就是小编为大家带来的Log4j按级别输出日志到不同文件的实现方法全部内容了,希望大家多多支持呐喊教程~
问题内容: 我正在使用log4j登录我的应用程序。我正在尝试在不同文件中使用不同级别的日志,但是出了点问题。对于解决此问题的任何帮助,我们将不胜感激。 问题答案: log4j附加程序的标准行为是,它们以其阈值级别 或更高 的阈值记录所有消息,即具有阈值INFO的附加器将记录INFO,WARN,ERROR和FATAL消息,但不记录DEBUG。如果你想记录 只有 INFO信息,但不会发出警告及以上,然
我的目标是: 实现所有自定义,内置记录器从同一个包到不同的文件。 信息-信息日志文件 我尝试的是: 问题是: 记录器名称相同。因此,最新的记录器只能工作。在这种情况下,Info可以工作,但也不能调试。 我的疑问是: 我引用了这么多帖子。我认为下面的方法是有效的。 按此处所述,将每一个作为自定义记录器。但我确信这是否正确的解决方案
我在我的项目中使用log4j。我想有标准输出、调试记录器和最终报告记录器。调试记录器几乎写调试/信息级别的消息。报告将是不同的记录器,只写信息消息。我尝试了不同的方法,阅读了很多示例,我仍然无法解决这个问题。要么我丢失了我的标准输出,要么我将所有调试写入两个记录器。 我的密码在这里 } 任何提示都将不胜感激
如何编写一个简单的log4j2.xml文件,将不同级别的日志放入不同的文件中? 例如,我们有错误日志,任何信息日志,我需要将所有错误日志消息推入一个日志文件,所有信息日志消息推入另一个文件。 我怎么做?