log4j——SocketAppender
阿新 • • 發佈:2018-12-27
SocketAppender所實現的功能
SocketAppender所實現的功能是將本地的日誌LoggingEvent類序列化傳送到遠端主機,在遠端主機中完成反序列化,然後通過其中的方法獲取相應的日誌資訊。
SocketServer
這個SocketServer其主要功能是監聽本地的一個埠,這裡我們選擇官方定義的4560埠號,也就是說SocketServer通過監聽4560埠號中的資訊,一旦發現有資訊寫入(ObjectInputStream),即反序列化生成LoggingEvent,通過其中的方法來獲取相應的日誌資訊。
這個SocketServer在原始碼中就有現成的例子,在原始碼中的例子是SimpleSocketServer,其中的原始碼如下:
package org.apache.log4j.net;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
public class SimpleSocketServer {
static Logger cat;
static int port;
public SimpleSocketServer() {
}
public static void main(String[] argv) {
if (argv.length == 2) {
init(argv[0], argv[1]);
} else {
usage("Wrong number of arguments.");
}
try {
cat.info("Listening on port " + port);
ServerSocket serverSocket = new ServerSocket(port);
while(true) {
cat.info("Waiting to accept a new client.");
Socket socket = serverSocket.accept();
cat.info("Connected to client at " + socket.getInetAddress());
cat.info("Starting new socket node.");
(new Thread(new SocketNode(socket, LogManager.getLoggerRepository()), "SimpleSocketServer-" + port)).start();
}
} catch (Exception var3) {
var3.printStackTrace();
}
}
static void usage(String msg) {
System.err.println(msg);
System.err.println("Usage: java " + SimpleSocketServer.class.getName() + " port configFile");
System.exit(1);
}
static void init(String portStr, String configFile) {
try {
port = Integer.parseInt(portStr);
} catch (NumberFormatException var3) {
var3.printStackTrace();
usage("Could not interpret port number [" + portStr + "].");
}
if (configFile.endsWith(".xml")) {
DOMConfigurator.configure(configFile);
} else {
PropertyConfigurator.configure(configFile);
}
}
static {
cat = Logger.getLogger(SimpleSocketServer.class);
}
}
SocketNode原始碼如下:
package org.apache.log4j.net;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.SocketException;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.LoggingEvent;
public class SocketNode implements Runnable {
Socket socket;
LoggerRepository hierarchy;
ObjectInputStream ois;
static Logger logger;
public SocketNode(Socket socket, LoggerRepository hierarchy) {
this.socket = socket;
this.hierarchy = hierarchy;
try {
this.ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
} catch (InterruptedIOException var4) {
Thread.currentThread().interrupt();
logger.error("Could not open ObjectInputStream to " + socket, var4);
} catch (IOException var5) {
logger.error("Could not open ObjectInputStream to " + socket, var5);
} catch (RuntimeException var6) {
logger.error("Could not open ObjectInputStream to " + socket, var6);
}
}
public void run() {
try {
if (this.ois != null) {
while(true) {
LoggingEvent event;
Logger remoteLogger;
do {
event = (LoggingEvent)this.ois.readObject();
remoteLogger = this.hierarchy.getLogger(event.getLoggerName());
} while(!event.getLevel().isGreaterOrEqual(remoteLogger.getEffectiveLevel()));
remoteLogger.callAppenders(event);
}
}
} catch (EOFException var36) {
logger.info("Caught java.io.EOFException closing conneciton.");
} catch (SocketException var37) {
logger.info("Caught java.net.SocketException closing conneciton.");
} catch (InterruptedIOException var38) {
Thread.currentThread().interrupt();
logger.info("Caught java.io.InterruptedIOException: " + var38);
logger.info("Closing connection.");
} catch (IOException var39) {
logger.info("Caught java.io.IOException: " + var39);
logger.info("Closing connection.");
} catch (Exception var40) {
logger.error("Unexpected exception. Closing conneciton.", var40);
} finally {
if (this.ois != null) {
try {
this.ois.close();
} catch (Exception var35) {
logger.info("Could not close connection.", var35);
}
}
if (this.socket != null) {
try {
this.socket.close();
} catch (InterruptedIOException var33) {
Thread.currentThread().interrupt();
} catch (IOException var34) {
;
}
}
}
}
static {
logger = Logger.getLogger(SocketNode.class);
}
}
由於有現成的例子,所以說我們直接呼叫就可以了,其呼叫的方法如下:
java org.apache.log4j.net.SocketServer port configFile directory
我本地的呼叫如下:
F:\Test2\log4j-parent\log4j-SocketAppender\src\main\resources> java -cp log4j-1.2.17.jar org.apache.log4j.net.SocketServer 4560 F:\Test2\log4j-parent\log4j-SocketAppender\src\main\resources\log4j.properties F:\Test2\log4j-parent\log4j-SocketAppender\src\main\resources
SocketClient
在客戶端的使用方式和之前的其它log4j方法本身並沒有太大的不同,所以說直接上程式碼。
log4j.properties配置檔案
log4j.rootCategory=info,stdout,Socket
###################
# Console Appender
# 將資訊輸出到控制檯中
###################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d{yyyy-MM-dd HH:mm:ss} %5p %t %-5l - %m%n
####################
# Socket Appender
# SocketAppender是一個OutputStreamAppender,它將輸出寫到一個由主機和埠指定的遠端目的地。
# 資料可以通過TCP或UDP傳送,可以以任何格式傳送。您可以選擇使用SSL來保護通訊。
####################
log4j.appender.Socket=org.apache.log4j.net.SocketAppender
#指定日誌訊息的輸出最低層次。
log4j.appender.Socket.Threshold=INFO
#遠端主機地址(通常是ip地址)
log4j.appender.Socket.RemoteHost=localhost
#遠端主機的埠號
log4j.appender.Socket.Port=4560
#應用程式的名稱
log4j.appender.Socket.Application=localclient
log4j.appender.Socket.LocationInfo=true
SocketClientTest測試程式碼
package com.lyc.log4j;
import org.apache.log4j.Logger;
import org.junit.Test;
public class SocketClientTest {
private static final Logger log = Logger.getLogger(SocketClientTest.class);
@Test
public void testSocketAppender() throws Exception{
for (int i = 0; i < 10; i++) {
log.warn("this is the message.");
log.debug("this is the message.");
log.info("this is the message.");
}
}
}