使用log4j将日志发送到Java中的Web服务
问题内容:
我对Web服务世界还很陌生,但是具有相关知识log4j
。
我需要实现将日志消息发送到Web服务而不是使用 Web Service附加程序 发送到文件的功能。
我是通过在 Google 上搜索WebServiceAppender
该log4j
类别之一来阅读的,但我无法验证这一点。
log4j.appender.CONSOLE=main.WSAppender
log4j.appender.CONSOLE.endpoint=http://localhost:8080/Logging/services/logging?wsdl
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%p [%t] %c{2} (%M:%L) :: %m%n
WSAppender.java extends AppenderSkeleton, can't resolve endpoint, hostname in append()
if (endpoint == null) {
System.out.println("no endpoint set. Check configuration file");
System.out.println("[" + hostname + "] " + this.layout.format(event));
return;
}
问题答案:
当您扩展该类时,AppenderSkeleton
我假设您应该使用public void activateOptions()
应重写的方法来初始化您的webservice类。我已经编写了DatabaseAppender和JmsAppender
log4j记录器,并且我总是发现我必须初始化该方法中的db连接或jms连接或您的Web服务属性public void activateOptions()
。
然后,像往常一样在该append(LoggingEvent)
方法中,您只需调用Web服务。
可能我建议实现一个BlockingQueue来存储所有LoggingEvent对象,以便在收到大量日志消息时将它们排队并异步发送到Web服务。
更新以包括模板Log4j类
尝试使用以下模板。我在重要部分添加了评论。基本上在activateOptions和processEvent方法中,您将在此初始化“连接”并发送事件对象。可以是DB,JMS,WebService等。
package mypackage;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
public class WebServiceAppender extends AppenderSkeleton {
private static final BlockingQueue<LoggingEvent> loggingEventQueue = new LinkedBlockingQueue<LoggingEvent>();
private static WebServiceAppender instance;
private static Thread thread = null;
//Your custom properties for your web service
private String property1;
private String property2;
private String property3;
static {
thread = new Thread(new Runnable() {
public void run() {
processQueue();
}
});
thread.setDaemon(true);
thread.start();
}
private static void processQueue() {
while(true) {
try {
LoggingEvent event = loggingEventQueue.poll(1L, TimeUnit.SECONDS);
if (event != null) {
instance.processEvent(event);
}
}
catch(InterruptedException e) {
// No operations.
}
}
}
private final void processEvent(LoggingEvent loggingEvent) {
if(loggingEvent != null) {
//Send the loggingEvent object or you can
//get data out of it and package it in another
//java class and send that, to your web service.
//Web Service is invoked here
}
}
public synchronized void close() {
// The synchronized modifier avoids concurrent append and close operations
if(this.closed) {
return;
}
closeWS();
thread.interrupt();
LogLog.debug("Closing appender [" + name + "].");
this.closed = true;
}
private void closeWS() {
try {
//Close the webservice connection
//or whatever here.
}
catch(Exception ex) {
LogLog.error("Error while closing WebServiceAppender [" + name + "].", ex);
}
}
public boolean requiresLayout() {
//Does not need a layout because
//we are sending serialized events
//to an external source
return false;
}
@Override
public void activateOptions() {
instance = this;
try {
LogLog.debug("Getting web service properties.");
if(property1 != null) {
//Do something with your property
}
if(property2 != null) {
//Do something with your property
}
if(property3 != null) {
//Do something with your property
}
//Initialize your web-service connection and objects here
LogLog.debug("Web Service created.");
}
catch(Exception ex) {
LogLog.error("Error while activating options for WebServiceAppender [" + name + "].", ex);
}
}
/*
* These methods are set from the log4j properties file like:
* log4j.appender.WS=mypackage.WebServiceAppender
* log4j.appender.WS.property1=bla
* log4j.appender.WS.property2=ble
* log4j.appender.WS.property3=blo
*/
public final String getProperty1() {
return property1;
}
public final String getProperty2() {
return property2;
}
public final String getProperty3() {
return property3;
}
public final void setProperty1(String property1) {
this.property1 = property1;
}
public final void setProperty2(String property2) {
this.property2 = property2;
}
public final void setProperty3(String property3) {
this.property3 = property3;
}
@Override
protected void append(LoggingEvent event) {
loggingEventQueue.add(event);
}
@Override
public void finalize() {
close();
super.finalize();
}
}