2013-05-27 2 views
1

Я хочу создать пользовательский appender, используя log4j в java программно, который хранит журнал в памяти (Определенный размер будет определен, например, для DEFAULT_SIZE = 20) &, как только память заполнена (в памяти 20 журналов) создается массив json из этих журналов и отправляется на сервер. Наряду с сообщением журнала я также хочу получить информацию, такую ​​как (класс, имя файла, номер строки, имя метода, уровень и т. Д.)Создайте пользовательский appender в log4j, который хранит журнал в памяти

Помощь приветствуется. !!!

Обновлено ::

Ниже приведен исходный код, разработанный мной для того же. Проблема, с которой я столкнулся, - это получить номер строки, имя метода, имя файла как «?». Я не понимаю, в чем причина.

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(); 
} 
} 

ответ

0

Я бы посмотрел исходный код для log4j2 и использовал существующий appender в качестве шаблона для моего пользовательского приложения. SocketAppender и TCPSocketManager могут быть хорошими местами для запуска.

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

В настоящее время буферизации на основе количества байт, а не количество событий. Если вы будете следовать существующему шаблону appender/manager, то в вашем пользовательском менеджере приложений вам понадобится достаточно большой буфер и сбросить каждые 20 событий. (Возможно, вы также можете сбрасывать после некоторого тайм-аута? Вы можете получить только 19 событий и ничего после этого ...) Вы также можете сделать буферизацию в приложении, сохранить там список объектов событий и только позвонить передать их менеджеру написанный после достижения определенного порогового значения.

Макет по умолчанию для SocketAppender будет использовать сериализацию java. Вам нужно бросить свой собственный JasonLayout. Объект события журнала содержит все указанные вами сведения.

+0

Hii Remko Popma, прежде всего спасибо за предложения, а во-вторых, я отредактировал вопрос с моим исходным кодом. Если у вас есть возможность взглянуть на него и помочь мне, это будет оценено по достоинству. –

+0

Привет Анкит, я вижу, вы используете log4j-1.2 ... Я больше знаком с 2.0. Одна вещь: appenders могут быть настроены так, чтобы не принимать LocationInfo (для этого AsyncAppender имеет параметр конфигурации). Как насчет вашего пользовательского приложения? Является ли он (или его родительский класс) информацией о местоположении при создании объекта события журнала? –

+0

Я использую log4j-1.2.17 ... Вот что я в ловушке. У меня есть файл log4j.properties, где я указываю log4j.appender.CONSOLE.layout.LocationInfo = true, но он не дает мне правильный output.I не знаю, где я неправильно это неправильно. –

Смежные вопросы