og4J的配置文件(Configuration File)就是用来设置记录器的级别、存放器和布局的,它可接key=value格式的设置或xml格式的设置信息。通过配置,可以创建出Log4J的运行环境。
日志分等级输出到不同文件
log4j的配置文件
log4j.rootLogger = debug,stdout,D,E,Database,file
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.Threshold = INFO
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n`
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
我们先看一下这些配置都配置了什么,了解一下基本格式 1.配置根Logger:og4j.rootLogger = [ level ] , appenderName1 , appenderName2 , …
(1)level:记录日志级别的优先级:OFF,fatal,error,warn,info,debuge,all
(2)log4j中只使用4种:error>warn>info>debuge,定义高级别可以看到低级别的信息,但是定义低级别的,看不到高级别
2.log4j提供的appender有如下:
(1)org.apache.log4j.ConsoleAppender(控制台)
(2)org.apache.log4j.FileAppender(文件)
(3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
(4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
(5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
3.配置日志信息的输出格式:
(1)org.apache.log4j.HTMLLayout(以HTML表格形式布局)
(2)org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
(3)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
(4)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
4.格式说明,layout中的参数都是%开始,后面不同的参数代表不同的格式化信息
(1)%c 输出所属列的全名
(2)%d 输出日志时间格式为%d{yyyy-MM-dd HH:mm:ss,SSS},可指定格式 如 %d{HH:mm:ss}
(3)%l 输出日志事件发生位置,包括类目名、发生线程,在代码中的行数
(4)%n 换行符
(5)%m 输出代码指定信息,如info(“message”),输出message
(6)%p 输出优先级,即 FATAL ,ERROR 等
(7)%r 输出从启动到显示该log信息所耗费的毫秒数
(8)%t 输出产生该日志事件的线程名
控制台打印Info级别以上日志
这个的具体配置上上面已经给出,这里我梳理一下他们的级别:
log4j.logger.xx >log4j.rootLogger,也就是log4j.appender.Threshold决定了最低接受级别。rootLogger首先决定了所有log的输出级别,而log4j.looger.xx是对xx路径下的jar包的输出级别的修改,直接覆盖rootLogger,但是对于不同的输出口,他们的接受级别不同。
调用代码: package utils;
import org.apache.log4j.Logger;
import org.apache.log4j.net.SimpleSocketServer;
public class log4jTest {
private static Logger logger=Logger.getLogger(log4jTest.class);
public static void main(String[] args) {
logger.debug("debug 调试");
logger.info("info 信息");
logger.error("error 错误");
logger.warn("warn 信息");
}
}
举例一:log4j.appender.xx.Threshold>rootLogger
log4j.rootLogger = debug
log4j.appender.D.Threshold = info
log4j.appender.E.Threshold = warn
那么项目的输出级别是debug,但是D只接受info级别以上的Log,E只接受Warn级别以上的log
举例二:log4j.appender.xx.Threshold<rootLogger log4j.rootLogger = warn log4j.appender.D.Threshold = info log4j.appender.E.Threshold = error 我们看一下D的日志输出: 2017-01-10 11:49:40 [ main:0 ] - [ ERROR ] error 错误 2017-01-10 11:49:40 [ main:266 ] - [ WARN ] warn 信息 E的日志输出: 2017-01-10 11:49:40 [ main:0 ] - [ ERROR ] error 错误 可以看出:尽管我们D的日志想要info级别以上的信息,但是我们只看到了两条,不是3条,因为rootlogger输出warn以上的信息,E的日志信息值输出error以上的信息。
error级别以下的错误信息email邮件发送
配置信息:
#log4j的邮件发送appender,如果有必要你可以写自己的appender
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
#发送邮件的门槛,仅当等于或高于ERROR(比如FATAL)时,邮件才被发送
log4j.appender.MAIL.Threshold=ERROR
#缓存文件大小,日志达到10k时发送Email
log4j.appender.MAIL.BufferSize=10
#发送邮件的邮箱帐号
log4j.appender.MAIL.From=xxxxx@163.com
#SMTP邮件发送服务器地址
log4j.appender.MAIL.SMTPHost=smtp.163.com
#SMTP发送认证的帐号名
log4j.appender.MAIL.SMTPUsername=xxxxx@163.com
#SMTP发送认证帐号的密码
log4j.appender.MAIL.SMTPPassword=xxxxx
#是否打印调试信息,如果选true,则会输出和SMTP之间的握手等详细信息
log4j.appender.MAIL.SMTPDebug=true
#邮件主题
log4j.appender.MAIL.Subject=Log4JErrorMessage
#发送到什么邮箱,如果要发送给多个邮箱,则用逗号分隔;
#如果需要发副本给某人,则加入下列行
#log4j.appender.MAIL.Bcc=xxx@xxx.xxx
log4j.appender.MAIL.To=xxxx@cyou-inc.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework]%d - %c -%-4r[%t]%-5p %c %x -%m%n
注意: log4j.rootLogger=info,console,MAIL 需要加上MAIL,否则不会调用邮件发送类,发送邮件
所有日志通过socket发送到另一个服务器备份
服务器端配置:
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=application-error.log
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%d] [%t] [%m]%n
服务器端启动监听: 这里我们可以启动已经有的SimpleSocketServer监听固定端口。 但是这里我自己写了一段代码来启动监听: public class SocketServer {
static Logger cat=Logger.getLogger(SocketServer.class);
static int port=1026;
static String configFile="resources/log4j.properties";
public static void main(String[] args) {
init(port,configFile);
try{
cat.info("正在监听端口:"+port);
ServerSocket serverSocket=new ServerSocket(port);
while(true){
cat.info("等待接受一下新的客户端请求");
Socket socket=serverSocket.accept();
cat.info("连接到客户端:"+socket.getInetAddress());
cat.info("开启一个新的套接字节点");
new Thread(new SocketNode(socket,
LogManager.getLoggerRepository()),"服务器Socket-" + port).start();
}
}catch(Exception e){
e.printStackTrace();
}
}
static void init(Integer portStr, String configFile){
if(configFile.endsWith(".xml")) {
DOMConfigurator.configure(configFile);
} else {
PropertyConfigurator.configure(configFile);
}
}
}
客户端配置文件: #Define the log4j configuration for local application log4j.rootLogger=ERROR, server
#We will use socket appender
log4j.appender.server=org.apache.log4j.net.SocketAppender
#Port where socket server will be listening for the log events
log4j.appender.server.Port=1026
#Host name or IP address of socket server
log4j.appender.server.RemoteHost=127.0.0.1
#Define any connection delay before attempting to reconnect
log4j.appender.server.ReconnectionDelay=10000
客户端发起请求:
public class ClientSocket {
private static Logger logger = Logger.getLogger(ClientSocket.class);
public static void main(String[] args) throws InterruptedException {
logger.error("error 错误");
logger.debug("debug 调试");
logger.info("info 信息");
}
}
服务器端信息:
[INFO ] 2017-01-10 14:37:04,894 method:utils.SocketServer.main(SocketServer.java:26)
正在监听端口:1026
[INFO ] 2017-01-10 14:37:05,607 method:utils.SocketServer.main(SocketServer.java:29)
等待接受一下新的客户端请求
[INFO ] 2017-01-10 14:37:49,918 method:utils.SocketServer.main(SocketServer.java:31)
连接到客户端:/127.0.0.1
[INFO ] 2017-01-10 14:37:49,987 method:utils.SocketServer.main(SocketServer.java:32)
开启一个新的套接字节点
[INFO ] 2017-01-10 14:37:50,242 method:utils.SocketServer.main(SocketServer.java:29)
等待接受一下新的客户端请求
[ERROR] 2017-01-10 14:37:50,153 method:
error 错误
[INFO ] 2017-01-10 14:37:50,428 method:org.apache.log4j.net.SocketNode.run(SocketNode.java:96)
Caught java.net.SocketException closing conneciton.
这里我发现一个问题,我们客户端发起请求的时候,服务器端虽然能拦截到相应的信息,但是却关闭了连接,这个问题我不是很清楚,我如果循环请求我的服务器那么是可以正常监听到信息的。因此我查看源码SocketAppender,发现ObjectOutputStream oos使用完没有关闭,因此猜测main程序和我们的代码强占资源,如果main跑的快,那么就会出现reset.这个还有待研究。
记录到数据库
配置文件:
log4j.appender.Database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.Database.URL=jdbc:mysql://localhost:3306/log4j
log4j.appender.Database.driver=com.mysql.jdbc.Driver
log4j.appender.Database.user=root
log4j.appender.Database.password=xxx
log4j.appender.Database.sql=INSERT INTO log4j (ip,time,thread,clazz,method,level,message) VALUES ('127.0.0.1','%-d{yyyy-MM-dd HH:mm:ss}','%t','%c','%l','%p','%m')
log4j.appender.Database.layout=org.apache.log4j.PatternLayout
log4j.appender.Database.layout.ConversionPattern= %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
这样当我们产生日志就会在表中插入一条日志信息