3

我想以编程方式在java中使用log4j创建一个自定义appender,它将日志存储在内存中(将定义特定大小,例如DEFAULT_SIZE = 20)&一旦内存已满(内存中有20个日志)创建一个json数组这些日志并将其发送到服务器。除了日志消息,我还想要诸如(类、文件名、行号、方法名、级别等)之类的信息。

帮助表示赞赏.!!!

更新 ::

以下是我为相同开发的源代码。我面临的问题是我得到行号、方法名、文件名作为“?”。我不明白是什么原因。

package com.any.logger;

import java.util.ArrayList;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;

public class Log4jAppender extends AppenderSkeleton {


private static final int DEFAULT_BUFFER_SIZE = 20;
private ArrayList<LoggingEvent> buffer;
private int bufferSize;

public Log4jAppender() {
  this.bufferSize = Log4jAppender.DEFAULT_BUFFER_SIZE;
  this.buffer = new ArrayList<LoggingEvent>();
}


public void close() {

}

public boolean requiresLayout() {

  return false;
}

 @Override
 protected void append(LoggingEvent loggingEvent) {


synchronized (buffer) {
  if (buffer.size() >= bufferSize) {
   try {
      System.out.println("Hello");
      Log4jService service = new Log4jService(new ArrayList<LoggingEvent>  
            (buffer));          
       System.out.println("Buff >");
       service.start();
  } catch (Exception e) {
    System.err.println("Failed to write logs");
    e.printStackTrace();
  } finally {
    buffer.clear();
  }
  }
}

  buffer.add(loggingEvent);
}

}



package com.any.logger;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.log4j.Level;
import org.apache.log4j.spi.LoggingEvent;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

@SuppressWarnings("rawtypes")
public class Log4jService implements Runnable {

private ArrayList<LoggingEvent> buffer;
private Thread t;
private boolean flag;

public Log4jService(ArrayList<LoggingEvent> buffer) {
    this.buffer = new ArrayList<LoggingEvent>(buffer);
    this.flag = false;
}

public void start() {
   if (!flag) {

     this.flag = true;
     this.t = new Thread(this);
     this.t.start();
}
}

 public void run() {
    if (flag) {
     String json = getLogJson(buffer);
    }
 }

   /**
    * Method to get the json log
    * 
    * @param logEvents
    *            arrayList of log events
    * @return an String which is json file
    * @throws JSONException
   */

   private String getLogJson(ArrayList<LoggingEvent> logEvents) {

   System.out.println("In getLogJson");

   JSONObject logger = new JSONObject();

   try {

         JSONArray logs = new JSONArray();

         String message = "";
         String time = "";
String level = "";
String tag = "";
String file = "";
String exceptionName = "";
String exceptionReason = "";
String line = "";
String clas = "";
String method = "";

int index = 0;

SimpleDateFormat formatter=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");         
for (Iterator i = logEvents.iterator(); i.hasNext();) {
LoggingEvent logEvent = (LoggingEvent) i.next();

boolean chk=logEvent.locationInformationExists();

System.out.println("Check :: "+chk);

clas=logEvent.getClass().toString();
JSONObject log = new JSONObject();


message = logEvent.getMessage().toString();
time = String.valueOf(formatter.format(logEvent.getTimeStamp()));
level = logEvent.getLevel().toString();


    if (chk) {
    System.out.println("hello");
    file = logEvent.getLocationInformation().getFileName();
    line = logEvent.getLocationInformation().getLineNumber();
    method = logEvent.getLocationInformation().getMethodName();
}

if (logEvent.getLevel() == Level.ERROR || logEvent.getLevel() ==  
            Level.FATAL) {  
    exceptionReason = message;
}

log.put("message", message);

log.put("time", time);
log.put("level", level);
log.put("tag", tag);
log.put("file", file);
log.put("exceptionName", exceptionName);
log.put("exceptionReason", exceptionReason);
log.put("line", line);
log.put("class", clas);
log.put("method", method);

logs.put(index, log);

index++;
}

JSONObject logsObj = new JSONObject();
logsObj.put("logs", logs);

logger.put("log", logsObj);

System.out.println("Logs Array :: " + logsObj);
System.out.println("Logger Object :: " + logger);
} catch (Exception e) {
e.printStackTrace();
}

return logger.toString();
}
}
4

1 回答 1

0

我会查看 log4j2 的源代码,并使用现有的 appender 作为我的自定义 appender 的模板。SocketAppender 和 TCPSocketManager 可能是很好的起点。

http://logging.apache.org/log4j/2.0/log4j-core/xref/org/apache/logging/log4j/core/net/TCPSocketManager.html

目前缓冲基于字节数,而不是事件计数。如果您遵循现有的 appender/manager 模式,那么在您的自定义 appender 管理器中,您将需要有足够大的缓冲区并每 20 个事件刷新一次。(也许在一些超时后也刷新?你可能只会得到 19 个事件,之后什么都没有......)你也可以在 appender 中进行缓冲,在那里保留一个事件对象列表,然后只调用将它们传递给要写入的管理器在达到某个阈值后。

SocketAppender 的默认布局将使用 java 序列化。您需要推出自己的 JasonLayout。日志事件对象包含您提到的所有详细信息。

于 2013-05-27T15:09:33.573 回答