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
Post a Comment