随着项目规模的越来越大,会不断的引入新的模块,不同的模块都会打印自己的日志,最后就造成日志根本没法查看,比如我自己的项目中,就存在以下这些日志:
- 接收外界消息的日志、对外发送消息的日志;
- 后台常驻线程的处理日志;
- 外部接口访问的参数、返回结果等接口日志;
- Service访问数据库产生的SQL日志;
这其中,消息日志和后台线程的日志数据量非常庞大,如果所有日志打印在一个文件中,使用tail -f log.log文件,会发现日志在快速的滚动,根本无法查看甚至定位某一个具体的SQL或者Service访问日志。
解决方法就是可以将不同的日志加以分类输出,这样相互的日志不影响,尤其重要的接口访问日志,能够很方便的定位和排查问题。
步骤1:在log4j.properties中配置
先贴一下我自己所有的log4j.properties配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
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为例):
- log4j.logger.net.czt.crazyant.service=DEBUG, service
- 这句中的”net.czt.crazyant.service”,表示该普通logger日志配置生效的package的完全路径
- 其中色service,表示该普通logger的名字
- log4j.additivity.net.czt.crazyant.service=false
- 其中的”net.czt.crazyant.service”,和上面的相同,表示该配置项针对的package
- 该句配置的意思,是不要将该package的日志输出到rootLogger日志中,只输出到自己配置的日志就行了;
- log4j.appender.service=org.apache.log4j.RollingFileAppender,以及该配置段下面的配置项
- 这里的”service”字符串,和上面的第一个配置项的”service”相同,表示对该普通Logger的配置;
- 下方的配置项和rootLogger相同,表示每天输出文件、编码UTF8、分片规则、每行的输出模式等等
我自己遇到的问题,是上面的log4j.properties配置好以后,发现各个日志文件创建了,但是里面都没有内容,这是为啥呢?来看下面第二个注意的地方;
步骤2、输出日志时需要设定日志对象对应的具体Class
什么意思呢?上面的配置项中,有一个”net.czt.crazyant.service”的package字符串,那么我们自己想一下,log4j是怎样将不同package中的logger日志输出到不同文件呢,想一下会有两种方法:
- 采用intercepter或者aop的方式,log4j自己检测日志输出,检测到日志产生于哪个package,就将其输出到对应文件中;
- 由用户传一个Class参数,log4j获取该Class对应的Package,以此为准,来定位不同的日志文件;
看一下代码,显然log4j用的是后一种简单直接的方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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对应上。
原创文章,转载请注明地址:http://www.crazyant.net/1931.html