自定义了一个将日志转换为json格式的 java.util.logging.Formatter
,主要模仿java.util.logging.XMLFormatter
类,初步测试能使用
package com.demon.test.testlogger;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.ResourceBundle;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
public class JsonFormatter extends Formatter {
@Override
public String format(LogRecord record) {
StringBuilder sb = new StringBuilder(500);
sb.append("{");
appendJson(sb, "date", "" + appendISO8601(record.getMillis()));
appendJson(sb, "millis", "" + record.getMillis());
appendJson(sb, "sequence", "" + record.getSequenceNumber());
String name = record.getLoggerName();
if (name != null) {
appendJson(sb, "name", name);
}
appendJson(sb, "level", record.getLevel().toString());
if (record.getSourceClassName() != null) {
appendJson(sb, "class", escape(record.getSourceClassName()));
}
if (record.getSourceMethodName() != null) {
appendJson(sb, "method", escape(record.getSourceMethodName()));
}
appendJson(sb, "thread", "" + record.getThreadID());
if (record.getMessage() != null) {
// Format the message string and its accompanying parameters.
String message = formatMessage(record);
appendJson(sb, "message", escape(message));
}
// If the message is being localized, output the key, resource
// bundle name, and params.
ResourceBundle bundle = record.getResourceBundle();
try {
if (bundle != null && bundle.getString(record.getMessage()) != null) {
appendJson(sb, "key", escape(record.getMessage()));
appendJson(sb, "catalog", escape(record.getResourceBundleName()));
}
} catch (Exception ex) {
// The message is not in the catalog. Drop through.
}
Object parameters[] = record.getParameters();
// // Check to see if the parameter was not a messagetext format
// // or was not null or empty
if (parameters != null && parameters.length != 0 && record.getMessage().indexOf("{") == -1) {
StringBuilder jsonArray = new StringBuilder();
for (int i = 0; i < parameters.length; i++) {
try {
jsonArray.append(escape(parameters[i].toString()));
} catch (Exception ex) {
jsonArray.append("???");
}
}
removeLastChar(sb);
appendJsonArray(sb, "param", jsonArray.toString());
}
if (record.getThrown() != null) {
// Report on the state of the throwable.
Throwable th = record.getThrown();
sb.append("\"exception\":{");
appendJson(sb, "message", escape(th.toString()));
StackTraceElement trace[] = th.getStackTrace();
StringBuilder frame_sbu = new StringBuilder();
for (int i = 0; i < trace.length; i++) {
StackTraceElement frame = trace[i];
frame_sbu.append("{");
appendJson(frame_sbu, "class", frame.getClassName());
appendJson(frame_sbu, "method", frame.getMethodName());
appendJson(frame_sbu, "line", "" + frame.getLineNumber());
removeLastChar(frame_sbu);
frame_sbu.append("},");
}
removeLastChar(frame_sbu);
appendJsonArray(sb, "frame", frame_sbu.toString());
removeLastChar(frame_sbu);
sb.append("}");
}
removeLastChar(sb);
sb.append("}\n");
return sb.toString();
}
/* 移除最后一个字符 */
private void removeLastChar(StringBuilder sb) {
int index = sb.lastIndexOf(",");
if (index != -1 && index == sb.length() - 1) {
// 删除最后一个 ,
sb.deleteCharAt(index);
}
}
/* 拼接Json */
private void appendJson(StringBuilder sb, String tag, String data) {
sb.append("\"" + tag + "\":\"" + data + "\",");
}
private void appendJsonArray(StringBuilder sb, String tag, String data) {
sb.append("\"" + tag + "\":[" + data + "],");
}
// Append to the given StringBuilder an escaped version of the
// given text string where XML special characters have been escaped.
// For a null string we append "<null>"
private String escape(String text) {
StringBuffer sb = new StringBuffer();
if (text == null) {
text = "";
}
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (ch == '<') {
sb.append("<");
} else if (ch == '>') {
sb.append(">");
} else if (ch == '&') {
sb.append("&");
} else {
sb.append(ch);
}
}
return sb.toString();
}
// Append the time and date in ISO 8601 format
private String appendISO8601(long millis) {
StringBuilder sb = new StringBuilder();
GregorianCalendar cal = new GregorianCalendar();
cal.setTimeInMillis(millis);
sb.append(cal.get(Calendar.YEAR));
sb.append('-');
a2(sb, cal.get(Calendar.MONTH) + 1);
sb.append('-');
a2(sb, cal.get(Calendar.DAY_OF_MONTH));
sb.append('T');
a2(sb, cal.get(Calendar.HOUR_OF_DAY));
sb.append(':');
a2(sb, cal.get(Calendar.MINUTE));
sb.append(':');
a2(sb, cal.get(Calendar.SECOND));
return sb.toString();
}
// Append a two digit number.
private void a2(StringBuilder sb, int x) {
if (x < 10) {
sb.append('0');
}
sb.append(x);
}
}
自测代码:
package com.demon.test.testlogger;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.logging.XMLFormatter;
class JsonFormatterTest {
public static void main(String[] args) {
ConsoleHandler console = new ConsoleHandler();
console.setLevel(Level.ALL);
Logger log = Logger.getGlobal();
log.addHandler(console);
log.setLevel(Level.ALL);
System.out.println("--------------------");
console.setFormatter(new XMLFormatter());
log.log(Level.CONFIG, "msg_XMLFormatter", new JsonFormatterTest().getException());
log.logp(Level.CONFIG, JsonFormatterTest.class.getName(), "main", "msg_XMLFormatter",new JsonFormatterTest().getException());
System.out.println("--------------------");
console.setFormatter(new SimpleFormatter());
log.log(Level.CONFIG, "msg_SimpleFormatter", new JsonFormatterTest().getException());
log.logp(Level.CONFIG, JsonFormatterTest.class.getName(), "main", "msg_SimpleFormatter",new JsonFormatterTest().getException());
System.out.println("--------------------");
console.setFormatter(new JsonFormatter());
log.log(Level.CONFIG, "msg_JsonFormatter", new JsonFormatterTest().getException());
log.logp(Level.CONFIG, JsonFormatterTest.class.getName(), "main", "msg_JsonFormatter",new JsonFormatterTest().getException());
}
public Exception getException() {
try {
test();
return null;
} catch (Exception e) {
return e;
}
}
public void test() {
test1();
}
public void test1() {
throw new RuntimeException("炸了");
}
}
解析后 效果:
{
"date": "2017-12-20T20:18:15",
"millis": "1513772295335",
"sequence": "4",
"name": "global",
"level": "CONFIG",
"class": "com.demon.test.testlogger.JsonFormatterTest",
"method": "main",
"thread": "1",
"message": "msg_JsonFormatter",
"exception": {
"message": "java.lang.RuntimeException: 炸了",
"frame": [
{
"class": "com.demon.test.testlogger.JsonFormatterTest",
"method": "test1",
"line": "60"
},
{
"class": "com.demon.test.testlogger.JsonFormatterTest",
"method": "test",
"line": "56"
},
{
"class": "com.demon.test.testlogger.JsonFormatterTest",
"method": "getException",
"line": "48"
},
{
"class": "com.demon.test.testlogger.JsonFormatterTest",
"method": "main",
"line": "41"
}
]
}
}