使用log4j将日志发送到Java中的Web服务


问题内容

我对Web服务世界还很陌生,但是具有相关知识log4j

我需要实现将日志消息发送到Web服务而不是使用 Web Service附加程序 发送到文件的功能。

我是通过在 Google 上搜索WebServiceAppenderlog4j类别之一来阅读的,但我无法验证这一点。

log4j.appender.CONSOLE=main.WSAppender 
log4j.appender.CONSOLE.endpoint=http://localhost:8080/Logging/services/logging?w‌​sdl 
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();
            }
      }