在log4j中创建一个自定义appender,它将日志存储在内存中

在log4j中创建一个自定义appender,它将日志存储在内存中,log4j,Log4j,我想以编程方式使用java中的log4j创建一个自定义appender,该appender将日志存储在内存中(将为其定义一定的大小,例如,假设DEFAULT_size=20)&一旦内存已满(内存中有20个日志),就创建这些日志的json数组并将其发送到服务器。除了日志消息之外,我还需要诸如(类、文件名、行号、方法名、级别等)之类的信息 谢谢你的帮助 更新:: 下面是我为同样的目的开发的源代码。我面临的问题是我得到的行号,方法名,文件名为“?”。我不明白是什么原因 package com.any.

我想以编程方式使用java中的log4j创建一个自定义appender,该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();
}
}
package com.any.logger;
导入java.util.ArrayList;
导入org.apache.log4j.AppenderSkeleton;
导入org.apache.log4j.spi.LoggingEvent;
公共类Log4jAppender扩展了AppenderSkeleton{
私有静态最终整数默认缓冲区大小=20;
私有数组列表缓冲区;
私有int缓冲区大小;
公共日志4jappender(){
this.bufferSize=Log4jAppender.DEFAULT_BUFFER_SIZE;
this.buffer=新的ArrayList();
}
公众假期结束(){
}
公共布尔值requiresLayout(){
返回false;
}
@凌驾
受保护的无效附加(LoggingEvent LoggingEvent){
已同步(缓冲区){
if(buffer.size()>=bufferSize){
试一试{
System.out.println(“你好”);
Log4jService service=newlog4jservice(newarraylist
(缓冲);
System.out.println(“Buff>”);
service.start();
}捕获(例外e){
System.err.println(“未能写入日志”);
e、 printStackTrace();
}最后{
buffer.clear();
}
}
}
buffer.add(loggingEvent);
}
}
包com.any.logger;
导入java.text.simpleDataFormat;
导入java.util.ArrayList;
导入java.util.Iterator;
导入org.apache.log4j.Level;
导入org.apache.log4j.spi.LoggingEvent;
导入org.json.JSONArray;
导入org.json.JSONException;
导入org.json.JSONObject;
@抑制警告(“原始类型”)
公共类Log4jService实现Runnable{
私有数组列表缓冲区;
私有线程t;
私有布尔标志;
公共Log4jService(ArrayList缓冲区){
this.buffer=新的数组列表(buffer);
this.flag=false;
}
公开作废开始(){
如果(!标志){
this.flag=true;
this.t=新线程(this);
这个.t.start();
}
}
公开募捐{
国际单项体育联合会(旗){
字符串json=getLogJson(缓冲区);
}
}
/**
*方法获取json日志
* 
*@param logEvents
*日志事件的arrayList
*@返回一个字符串,该字符串是json文件
*@JSONException
*/
私有字符串getLogJson(ArrayList logEvents){
System.out.println(“In-getLogJson”);
JSONObject logger=新的JSONObject();
试一试{
JSONArray日志=新的JSONArray();
字符串消息=”;
字符串时间=”;
字符串级别=”;
字符串标签=”;
字符串文件=”;
字符串exceptionName=“”;
字符串exceptionReason=“”;
字符串行=”;
字符串clas=“”;
字符串方法=”;
int指数=0;
SimpleDataFormat格式化程序=新的SimpleDataFormat(“yyyy-MM-dd HH:MM:ss”);
for(迭代器i=logEvents.Iterator();i.hasNext();){
LoggingEvent logEvent=(LoggingEvent)i.next();
布尔值chk=logEvent.locationInformationExists();
System.out.println(“检查:”+chk);
clas=logEvent.getClass().toString();
JSONObject log=新的JSONObject();
message=logEvent.getMessage().toString();
time=String.valueOf(formatter.format(logEvent.getTimeStamp());
level=logEvent.getLevel().toString();
如果(chk){
System.out.println(“你好”);
file=logEvent.getLocationInformation().getFileName();
line=logEvent.getLocationInformation().getLineNumber();
方法=logEvent.getLocationInformation().getMethodName();
}
如果(logEvent.getLevel()==Level.ERROR | | logEvent.getLevel()==
级别。致命){
例外原因=消息;
}
log.put(“消息”,消息);
log.put(“时间”,time);
log.put(“level”,level);
log.put(“tag”,tag);
log.put(“文件”,file);
log.put(“exceptionName”,exceptionName);
log.put(“exceptionReason”,exceptionReason);
log.put(“行”,行);
log.put(“类”,clas);
log.put(“方法”,method);
logs.put(索引,log);
索引++;
}
JSONObject logsObj=新的JSONObject();
logsObj.put(“logs”,logs);
logger.put(“log”,logsObj);
System.out.println(“日志数组::”+logsObj);
System.out.println(“记录器对象::”+记录器);
}捕获(例外e){
e、 printStackTrace();
}
返回logger.toString();
}
}

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

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


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

Hii Remko Popma,首先是thanx的建议,其次是我已经用我的源代码编辑了这个问题。如果你能看一眼并能帮我解决这个问题,我将不胜感激。嗨,Ankit,我看到你正在使用log4j-1.2。。。我更熟悉2.0。一件事:Appender可以配置为不获取LocationInfo(AsyncAppender有一个配置选项)。你的定制附加器呢?创建日志事件对象时,它(或其父类)是否获取位置信息?是的,我正在使用log4j-1.2.17。。。这就是我所陷入的困境。我有log4j.properties文件,其中我指定了log4j.appender.CONSOLE.layout.LocationInfo=true,但它不是giv