您现在的位置是:网站首页 > 代码编程 > JAVA开发JAVA开发
【原】log4j使用之SocketAppender教程
不忘初心 2019-05-16 围观() 评论() 点赞() 【JAVA开发】
简介:之前提到了错误日志发送邮件的方式,log4j还提供了一个SocketAppender,用来将日志进行网络传输,发送到指定的服务器上,比如:大名鼎鼎的ELK就提供的有这种方式。
之前提到了错误日志发送邮件的方式,log4j还提供了一个SocketAppender,用来将日志进行网络传输,发送到指定的服务器上,比如:大名鼎鼎的ELK就提供的有这种方式。
直接上配置文件:log4j.properties
# 配置根logger,如果下面没有自定义logger,那么项目中的日志就都是debug级别,输出到console
log4j.rootLogger=DEBUG,console,socket
# 屏蔽框架日志,只有报错的时候才放出来,优先级高于rootLogger
log4j.logger.org.springframework=ERROR
log4j.logger.org.apache.ibatis=ERROR
log4j.logger.org.mybatis.spring=ERROR
log4j.logger.com.mchange=ERROR
# 自定义包路径中的日志等级,直接写一个level即可,appender可选择,如果没写就默认使用rootLogger中配置的console
log4j.logger.com.ssm=DEBUG
# 打印出jdbc的日志
log4j.appender.java.sql.ResultSet=DEBUG
log4j.appender.java.sql.Connection=DEBUG
log4j.appender.java.sql.Statement=DEBUG
log4j.appender.java.sql.PreparedStatement=DEBUG
# 控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%5p] - %c - %m%n
# 应用于socket
log4j.appender.socket=org.apache.log4j.net.SocketAppender
#指定日志输出级别
log4j.appender.socket.Threshold=DEBUG
#接收方地址
log4j.appender.socket.RemoteHost=localhost
#接收方端口
log4j.appender.socket.Port=5555
#本地信息(文件名、类信息、方法名、行号),默认false
log4j.appender.socket.LocationInfo=true
#延时连接
log4j.appender.socket.ReconnectionDelay=10000
#选择输出方式
log4j.appender.socket.layout=org.apache.log4j.PatternLayout
#配置日志输出格式
log4j.appender.socket.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%5p] - %c - %m%n
参数都很好理解,这里不做过多解释,大家直接看配置文件中的注释,唯一需要注意一下locationInfo这个参数,在下面的socket中取值会用到。
再来写一个5555端口的socket:
package com.ssm.socket;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by Felix on 2019/05/06.
*/
public class Log4jSocket {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(5555);
while (true) {
final Socket socket = serverSocket.accept();
new Thread() {
// InputStream is = socket.getInputStream();
// InputStreamReader isr = new InputStreamReader(is);
// BufferedReader br = new BufferedReader(isr);
// String msg;
// 必须要转成LoggingEvent,普通的接收方式会有问题,一堆乱码不说,还有一些看不懂的字符串
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
LoggingEvent event;
LocationInfo locationInfo;
@Override
public void run() {
try {
while (true) {
event = (LoggingEvent) ois.readObject();
if (event == null) {
continue;
}
locationInfo = event.getLocationInformation();
System.out.println("文件名:" + locationInfo.getFileName());
System.out.println("类名:" + locationInfo.getClassName());
System.out.println("方法名:" + locationInfo.getMethodName());
System.out.println("行号:" + locationInfo.getLineNumber());
// 将格式拼装成log4j.properties中的格式:%d{yyyy-MM-dd HH:mm:ss} [%5p] - %c - %m%n
System.out.println(sdf.format(new Date(event.getTimeStamp())) + " [" + event.getLevel() + "] - " + event.getLoggerName() + " - " + event.getMessage());
}
// while ((msg = br.readLine()) != null) {
// System.out.println(msg);
// }
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
关于TCP的socket,这里也不再详细叙说了,如有不明白的地方,请移步:Java Socket编写基于TCP协议的简易聊天室
先启动这个socket,再启动项目,来看一下效果:
我输出了locationInfo中的值,而且还将接收到的日志组装成了和log4j.properties一样的格式。
这个socket中的代码注释,大家需要注意一下,之前在写socket的时候都是直接将IO流取出来转换成字符,这里就不行,接收log4j的日志,一定不能直接使用普通的接收方式,否则就会看到很多乱码和一堆看不懂的信息,如下图:
因为log4j使用的是ObjectOutputStream,传输过来的是一个序列化的Object,大家可以看一下SocketAppender的append()方法:
public void append(LoggingEvent event) {
if(event == null)
return;
if(address==null) {
errorHandler.error("No remote host is set for SocketAppender named \""+
this.name+"\".");
return;
}
if(oos != null) {
try {
if(locationInfo) {
event.getLocationInformation();
}
if (application != null) {
event.setProperty("application", application);
}
event.getNDC();
event.getThreadName();
event.getMDCCopy();
event.getRenderedMessage();
event.getThrowableStrRep();
oos.writeObject(event);
//LogLog.debug("=========Flushing.");
oos.flush();
if(++counter >= RESET_FREQUENCY) {
counter = 0;
// Failing to reset the object output stream every now and
// then creates a serious memory leak.
//System.err.println("Doing oos.reset()");
oos.reset();
}
} catch(IOException e) {
if (e instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
oos = null;
LogLog.warn("Detected problem with connection: "+e);
if(reconnectionDelay > 0) {
fireConnector();
} else {
errorHandler.error("Detected problem with connection, not reconnecting.", e,
ErrorCode.GENERIC_FAILURE);
}
}
}
}
oos就是ObjectOutputStream,最终是使用oos.writeObject()方法输出了一个LoggingEvent对象,所以接收的时候,也需要使用LoggingEvent来接收。
看完文章,有任何疑问,请加入群聊一起交流!!!
很赞哦! ()
相关文章
- log4j配置文件详解
- log4j使用之ConsoleAppender教程
- log4j使用之FileAppender教程
- log4j使用之RollingFileAppender教程
- log4j使用之DailyRollingFileAppender教程
- log4j使用之JDBCAppender教程
- log4j使用之SMTPAppender教程
- 使用SMTPAppender碰到的几个问题
- 为什么说在log4j中Threshold拥有最高优先级
- org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
标签云
猜你喜欢
- IntelliJ IDEA 2019.2已经可以利用补丁永久破解激活了
- IntelliJ IDEA 2019.3利用补丁永久破解激活教程
- IntelliJ IDEA高版本最灵活的永久破解激活方法(含插件激活,时长你说了算)
- Jetbrains全家桶基于ja-netfilter的最新破解激活详细图文教程
- IntelliJ IDEA 2022.1永久破解激活教程(亲测可用,持续更新)
- 分享几个正版 IntelliJ IDEA 激活码(破解码、注册码),亲测可用,持续更新
- ja-netfilter到底需不需要mymap,2021.3.2版本激活失效?
- 如何激活idea2022.1及以上版本中的插件(亲测可用)
- 【史上最全】IntelliJ IDEA最新2022.1版本安装和激活视频教学(含插件)
- IntelliJ IDEA 2022.2 版本最新2099年永久激活方法,亲测可用,也可以开启新UI了。
站点信息
- 网站程序:spring + freemarker
- 主题模板:《今夕何夕》
- 文章统计:篇文章
- 标签管理:标签云
- 微信公众号:扫描二维码,关注我们