Write logs in JSON format using jackson


import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.demo.logger.model.MyModel;

public class SplunkJsonLayout extends Layout {

private final Gson gson = new GsonBuilder().create();
    private final String hostname = getHostname().toLowerCase();
    private final String username = System.getProperty("user.name").toLowerCase();
 
    private Level minimumLevelForSlowLogging = Level.ALL;
    private List<String> mdcFieldsToLog = Collections.emptyList();

    @Override
public void activateOptions() {
// TODO Auto-generated method stub

}
@Override
public String format(LoggingEvent event) {
Map<String,Object> map = new LinkedHashMap<>();
        map.put("timestamp", event.timeStamp);
        map.put("date", new Date(event.timeStamp));
        map.put("hostname", hostname);
        map.put("username", username);
        map.put("level", event.getLevel().toString());
        map.put("thread", event.getThreadName());
        map.put("ndc",event.getNDC());
        if (event.getLevel().isGreaterOrEqual(minimumLevelForSlowLogging)) {
            map.put("classname", event.getLocationInformation().getClassName());
            map.put("filename", event.getLocationInformation().getFileName());
            map.put("linenumber", safeParseInt(event.getLocationInformation().getLineNumber()));
            map.put("methodname", event.getLocationInformation().getMethodName());
        }
        if(isJSONValid(event.getRenderedMessage())){
        map.put("message", safeToJSON(event.getRenderedMessage()));
        }
        else{
        map.put("message", safeToString(event.getRenderedMessage()));
        }
     
        map.put("throwable", formatThrowable(event) );
     
        for (String mdcKey : mdcFieldsToLog) {
            if (!map.containsKey(mdcKey)) {
                map.put(mdcKey, safeToString(event.getMDC(mdcKey)));
            }
        }
     
        after(event,map);
        return gson.toJson(map)+"\n";
}
public boolean isJSONValid(String test) {
    try {
        new JSONObject(test);
    } catch (JSONException ex) {
        // edited, to include @Arthur's comment
        // e.g. in case JSONArray is valid as well...
        try {
            new JSONArray(test);
        } catch (JSONException ex1) {
            return false;
        }
    }
    return true;
}

@Override
public boolean ignoresThrowable() {
// TODO Auto-generated method stub
return false;
}

private static String safeToString(Object obj) {
        if (obj==null) return null;
        try {
            return obj.toString();
        } catch (Throwable t) {
            return "Error getting message: "+ t.getMessage();
        }
    }

private static String safeToJSON(Object obj) {
        if (obj==null) return null;
        try {
        //ObjectMapper mapper = new ObjectMapper();
        //SplunkModel student = mapper.readValue(obj.toString(), SplunkModel.class);
        //String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
       
        JsonParser parser = new JsonParser();
            JsonObject json = parser.parse(obj.toString()).getAsJsonObject();

            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            String jsonString = gson.toJson(json);
            return jsonString;
        } catch (Throwable t) {
            return "Error getting message: "+ t.getMessage();
        }

    }

private static Integer safeParseInt(String obj) {
        try {
            return Integer.parseInt(obj.toString());
        } catch (NumberFormatException t) {
            return null;
        }
    }

private String formatThrowable(LoggingEvent le) {
        if (le.getThrowableInformation() == null ||
                le.getThrowableInformation().getThrowable()==null)
            return null;
     
        return mkString(le.getThrowableStrRep(),"\n");
    }

private String mkString(Object[] parts,String separator) {
        StringBuilder sb = new StringBuilder();
        for (int i=0 ; ; i++) {
            sb.append(parts[i]);
            if (i==parts.length-1)
                return sb.toString();
            sb.append(separator);
        }
    }

  private static String getHostname() {
        String hostname;
        try {
            hostname = java.net.InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            hostname = "Unknown, "+e.getMessage();
        }
        return hostname;
    }

  /**
     * Method called near the end of formatting a LoggingEvent in case users
     * want to override the default object fields.
     * @param le the event being logged
     * @param r the map which will be output.
     */
    public void after(LoggingEvent le, Map<String,Object> r) {
     
    }
}

---------------------------------------------------------------------
public class DemoClass{
    private static Log logger = LogFactory.getLog(HelloWorldWebScript.class);
 
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
 
    protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {
   
        Map<String, Object> model = new HashMap<String, Object>();
     
        model.put("fromJava", "HelloFromJava");
        logger.info("this is a String message");
        SplunkModel splunkModel = new SplunkModel("Info", "Message from Bean..........");
        String jsonString = gson.toJson(splunkModel);
        logger.error(jsonString);
        int i = 2/0;
        System.out.println(i);
       
        return model;
    }
}
----------------------------------------------------------------------------------
# Set root logger level to error
log4j.rootLogger=info, Console, File

###### Console appender definition #######

# All outputs currently set to be a ConsoleAppender.
log4j.appender.Console=org.apache.log4j.ConsoleAppender
#log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout=com.demo.logger.layout.json.SplunkJsonLayout

# use log4j NDC to replace %x with tenant domain / username
log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} %x %-5p [%c{3}] [%t] %m%n
#log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c] %m%n

###### File appender definition #######
log4j.appender.File=org.apache.log4j.DailyRollingFileAppender
log4j.appender.File.File=alfresco.log
log4j.appender.File.Append=true
log4j.appender.File.DatePattern='.'yyyy-MM-dd
#log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout=com.demo.logger.layout.json.SplunkJsonLayout
log4j.appender.File.layout.ConversionPattern=%d{yyyy-MM-dd} %d{ABSOLUTE} %-5p [%c] [%t] %m%n

###### File appender definition #######
log4j.appender.Splunk=org.apache.log4j.DailyRollingFileAppender
log4j.logger.com.logger=debug, Splunk
log4j.appender.Splunk.File=${catalina.base}/splunk.log
log4j.appender.Splunk.Append=true
log4j.appender.Splunk.layout=com.demo.logger.layout.json.SplunkJsonLayout


Comments

Popular posts from this blog

Install Alfresco Content Service 6.0 on ubuntu 16 using distribution zip

Lucene and fts-search

Call javascript webscript from contoller