本文 Tomcat 版本為 8.0.36翎蹈。
首先要搞清楚一點走趋,開發(fā)打的業(yè)務(wù)日志要么讓開發(fā)打成 json 格式稽煤,要么使用 Logstash 進(jìn)行解析,不可能有通用的產(chǎn)品可以完成妖谴,因為每個公司開發(fā)打印的日志的標(biāo)準(zhǔn)都不一樣窿锉。這里改變的只是 tomcat 本身的日志格式。
tomcat 自身的日志有:
catalina.2018-01-05.log
host-manager.2018-01-05.log
localhost.2018-01-05.log
manager.2018-01-05.log
localhost_access_log.2018-01-05.log
catalina.out 包括 tomcat 本身和開發(fā)打印的應(yīng)用日志膝舅,不做討論嗡载。
Tomcat 日志的訪問日志是在 server.xml 中配置的,配置成 json 格式也十分方便仍稀,而對于其他日志想要配置成 json 格式就十分不便了鼻疮。對于這些日志,tomcat 提供了兩種記錄的方式琳轿,一種是默認(rèn)的 java.util.logging
判沟,另一種就是 log4j
。默認(rèn)的方式無法記錄成 json(至少我沒找到方式)崭篡,而通過 log4j 可以挪哄,因為 Logstash 提供了一個插件。
首先我們要做的就是將 tomcat 日志的記錄的方式改為 log4j琉闪,修改的方式在此迹炼。這是官方文檔的翻譯,你也可以直接看官方文檔颠毙。
需要注意的是:
- log4j 的 jar 包一定要是 1.2.X 版本的斯入,不要下載最新版;
- 示例的
log4j.properties
中指定的日志文件是 catalina蛀蜜,而非 catalina.out刻两。
所有 jar 包都可以在 https://mvnrepository.com/ 這里下載。
如果沒有改變官方給出的 log4j.properties 的日志記錄格式滴某,那么配置成功后磅摹,tomcat/logs/catalina 的輸出和之前的 catalina.out 一樣。下一步就是使用 Logstash 提供的插件霎奢,這個怎么用呢户誓?很簡單,首先去上面給出的 maven 倉庫中下載 jar 包(最好使用 1.6 版)幕侠,然后放入 tomcat/lib 目錄下帝美,接著修改 log4j.properties:
log4j.rootCategory=WARN, RollingLog
log4j.appender.RollingLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.RollingLog.Threshold=TRACE
log4j.appender.RollingLog.File=api.log
log4j.appender.RollingLog.DatePattern=.yyyy-MM-dd
log4j.appender.RollingLog.layout=net.logstash.log4j.JSONEventLayoutV1
為了可以直接效果,可以將日志級別改為 INFO
晤硕。這個時候如果直接使用的話悼潭,會有下面的報錯:
Using CATALINA_BASE: /tmp/tomcat
Using CATALINA_HOME: /tmp/tomcat
Using CATALINA_TMPDIR: /tmp/tomcat/temp
Using JRE_HOME: /usr/local/jdk1.7.0_79
Using CLASSPATH: /tmp/tomcat/bin/bootstrap.jar:/tmp/tomcat/bin/tomcat-juli.jar
log4j:WARN Error during default initialization
java.lang.NoClassDefFoundError: org/apache/commons/lang/time/FastDateFormat
at net.logstash.log4j.JSONEventLayoutV0.<clinit>(JSONEventLayoutV0.java:36)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:379)
at org.apache.log4j.helpers.OptionConverter.instantiateByClassName(OptionConverter.java:336)
at org.apache.log4j.helpers.OptionConverter.instantiateByKey(OptionConverter.java:123)
at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:764)
at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:735)
at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:615)
at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:502)
at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:547)
at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:483)
at org.apache.log4j.LogManager.<clinit>(LogManager.java:127)
at org.apache.log4j.Logger.getLogger(Logger.java:104)
at org.apache.juli.logging.impl.Log4JLogger.getLogger(Log4JLogger.java:262)
at org.apache.juli.logging.impl.Log4JLogger.<init>(Log4JLogger.java:108)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.apache.juli.logging.impl.LogFactoryImpl.createLogFromClass(LogFactoryImpl.java:1025)
at org.apache.juli.logging.impl.LogFactoryImpl.discoverLogImplementation(LogFactoryImpl.java:844)
at org.apache.juli.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:541)
at org.apache.juli.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:292)
at org.apache.juli.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:269)
at org.apache.juli.logging.LogFactory.getLog(LogFactory.java:657)
at org.apache.catalina.startup.Catalina.<clinit>(Catalina.java:820)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:379)
at org.apache.catalina.startup.Bootstrap.init(Bootstrap.java:268)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang.time.FastDateFormat
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 36 more
需要下載以下包,放入 tomcat/lib 目錄下:
commons-lang-2.4
json-smart-1.1.1
junit-4.8.1
然后就可以在 api.log 中看到效果了:
{"@fields":{"level":"INFO","threadName":"localhost-startStop-1","mdc":{},"file":"HostConfig.java","class":"org.apache.catalina.startup.HostConfig","line_number":"1143","method":"deployDirectory","loggerName":"org.apache.catalina.startup.HostConfig"},"@timestamp":"2018-01-05T01:36:38.263Z","@message":"Deployment of web application directory \/tmp\/tomcat\/webapps\/manager has finished in 64 ms","@source_host":"SUC-IAS-JOB-02.UAT"}
{"@fields":{"level":"INFO","threadName":"main","mdc":{},"file":"AbstractProtocol.java","class":"org.apache.coyote.AbstractProtocol","line_number":"471","method":"start","loggerName":"org.apache.coyote.http11.Http11NioProtocol"},"@timestamp":"2018-01-05T01:36:38.265Z","@message":"Starting ProtocolHandler [\"http-nio-9021\"]","@source_host":"SUC-IAS-JOB-02.UAT"}
{"@fields":{"level":"INFO","threadName":"main","mdc":{},"file":"AbstractProtocol.java","class":"org.apache.coyote.AbstractProtocol","line_number":"471","method":"start","loggerName":"org.apache.coyote.ajp.AjpNioProtocol"},"@timestamp":"2018-01-05T01:36:38.270Z","@message":"Starting ProtocolHandler [\"ajp-nio-8009\"]","@source_host":"SUC-IAS-JOB-02.UAT"}
{"@fields":{"level":"INFO","threadName":"main","mdc":{},"file":"Catalina.java","class":"org.apache.catalina.startup.Catalina","line_number":"642","method":"start","loggerName":"org.apache.catalina.startup.Catalina"},"@timestamp":"2018-01-05T01:36:38.272Z","@message":"Server startup in 695 ms","@source_host":"SUC-IAS-JOB-02.UAT"}