# JsonLayout
## 1、项目说明
本项目通过自定义Layout实现log4j的JSON输出格式。
### 1.1、运行环境
* JDK 1.7+
### 1.2、配置示例
> log4j.appender.jsonLog.layout = com.zhph.log4j.layout.JsonLayout
> log4j.appender.jsonLog.layout.customFields = class,method,line,message
**其中:**
* **_com.zhph.log4j.layout.JsonLayout_** 是 JsonLayout 的类全名;
* **_customFields_** 可配可不配,不配时输出全部字段,如果配置则只输出配置的字段,字段间以英文逗号分割。
### 1.3、customFields的所有可配字段
1. **logger** String,Logger的名称
2. **timeMillis** long,时间戳
3. **time** String,时间戳,格式为yyyy-MM-dd HH:mm:ss
4. **level** String,日志级别,如ERROR等
5. **thread** String,线程名
6. **file** String,类文件名
7. **class** String,类全名
8. **method** String,方法名
9. **line** String,行数
10. **message** String,日志消息
11. **throwable** Object,异常信息
12. **userName** String,PC的用户名
13. **computerName** String,PC名称
14. **userDomain** String,PC用户的域
15. **localHostName** String,主机名
16. **localCanonicalHostName** String,规范的主机名
17. **localHostAddress** String,主机地址
18. **localHashCode** Long,主机的hash
## 2、更新说明
### v1.1 2017/06/23
* 添加了属性 **prefix** 以便配置消息前缀,缺省时为空
* 添加了属性 **suffix** 以便配置消息后缀,缺省时为空
* 示例:
> log4j.appender.jsonLog.layout.prefix =
> log4j.appender.jsonLog.layout.suffix = ,
### v1.2 2017/08/10
* 更正的日志时间显示问题
### v1.3 2018/01/31
* 增加了主机的相关信息,以支持用以区分集群下的各个节点
* 使日志输出与配置顺序保持一致
## 3、应用示例
### 3.1、缺省配置
缺省配置指的是不配置指定的字段以及前后缀,如:
![缺省配置](https://git.oschina.net/uploads/images/2017/0626/143829_8959c520_896911.png "缺省配置")
对应的日志输入内容:
> {"class":"com.zhph.log4j.layout.TestClass","file":"TestClass.java","level":"ERROR","line":"11","logger":"testJsonLog","message":"这是日志消息内容","method":"test01","thread":"main","throwable":{"cause":null,"class":"java.lang.Exception","localizedMessage":"这里是异常信息内容","message":"这里是异常信息内容","suppressed":[],"throwableStrRep":["java.lang.Exception: 这里是异常信息内容","\tat com.zhph.log4j.layout.TestClass.test01(TestClass.java:11)","\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)","\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)","\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)","\tat java.lang.reflect.Method.invoke(Method.java:606)","\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)","\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)","\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)","\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)","\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)","\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)","\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)","\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)","\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)","\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)","\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)","\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)","\tat org.junit.runners.ParentRunner.run(ParentRunner.java:292)","\tat org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)","\tat org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)","\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)","\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)","\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)","\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)"]},"time":"2017-06-26 14:40:33","timeMillis":1498459233725}
格式化处理后:
```
{
"class":"com.zhph.log4j.layout.TestClass",
"file":"TestClass.java",
"level":"ERROR",
"line":"11",
"logger":"testJsonLog",
"message":"这是日志消息内容",
"method":"test01",
"thread":"main",
"throwable":{
"cause":null,
"class":"java.lang.Exception",
"localizedMessage":"这里是异常信息内容",
"message":"这里是异常信息内容",
"suppressed":[
],
"throwableStrRep":[
"java.lang.Exception: 这里是异常信息内容",
" at com.zhph.log4j.layout.TestClass.test01(TestClass.java:11)",
" at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
" at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)",
" at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
" at java.lang.reflect.Method.invoke(Method.java:606)",
" at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)",
" at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)",
" at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)",
" at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)",
" at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)",
" at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)",
" at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)",
" at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)",
" at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)",
" at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)",
" at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)",
" at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)",
" at org.junit.runners.ParentRunner.run(ParentRunner.java:292)",
" at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)",
" at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)",
" at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)",
" at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)",
" at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)",
" at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)"
]
},
"time":"2017-06-26 14:40:33",
"timeMillis":1498459233725
}
```
### 3.2、自定义配置
自定义配置是指自定义要显示的日志信息字段,如:
![自定义配置](https://git.oschina.net/uploads/images/2017/0626/144434_6a8f2171_896911.png "自定义配置")
对应的日志输入内容:
> {"class":"com.zhph.log4j.layout.TestClass","line":"11","message":"这是日志消息内容","method":"test01"}
格式化处理后:
```
{
"class":"com.zhph.log4j.layout.TestClass",
"line":