1、采集tomcat确實比之前的需求複雜很多,我在搭建了一個tomcat的環境,然後産生如下報錯先貼出來:
Jan 05, 2017 10:53:35 AM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Jan 05, 2017 10:53:35 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8088"]
Jan 05, 2017 10:53:35 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Jan 05, 2017 10:53:35 AM org.apache.coyote.AbstractProtocol init
SEVERE: Failed to initialize end point associated with ProtocolHandler ["ajp-bio-8009"]
java.net.BindException: Address already in use (Bind failed) :8009
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:413)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:665)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:452)
at org.apache.catalina.startup.Catalina.load(Catalina.java:667)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:400)
... 16 more
2、分析我們需要的結構:
通過上面的分析,我們需要的資料有:時間戳、類名、日志資訊。
我們需要的操作就是先把相同時間和的多行日志資料合并到同一個事件裡面再分析。
###提示,因為tomcat日志比較困難,我們可以參考預設的日志結構:
[[email protected] patterns]# pwd
/test/logstash-5.0.0/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.0.2/patterns
[[email protected] patterns]# cat java
JAVACLASS (?:[a-zA-Z$_][a-zA-Z$_0-9]*\.)*[a-zA-Z$_][a-zA-Z$_0-9]*
#Space is an allowed character to match special cases like 'Native Method' or 'Unknown Source'
JAVAFILE (?:[A-Za-z0-9_. -]+)
#Allow special , methods
JAVAMETHOD (?:()|[a-zA-Z$_][a-zA-Z$_0-9]*)
#Line number is optional in special cases 'Native method' or 'Unknown source'
JAVASTACKTRACEPART %{SPACE}at %{JAVACLASS:class}\.%{JAVAMETHOD:method}\(%{JAVAFILE:file}(?::%{NUMBER:line})?\)
# Java Logs
JAVATHREAD (?:[A-Z]{2}-Processor[\d]+)
JAVACLASS (?:[a-zA-Z0-9-]+\.)+[A-Za-z0-9$]+
JAVAFILE (?:[A-Za-z0-9_.-]+)
JAVASTACKTRACEPART at %{JAVACLASS:class}\.%{WORD:method}\(%{JAVAFILE:file}:%{NUMBER:line}\)
JAVALOGMESSAGE (.*)
# MMM dd, yyyy HH:mm:ss eg: Jan 9, 2014 7:13:13 AM
CATALINA_DATESTAMP %{MONTH} %{MONTHDAY}, 20%{YEAR} %{HOUR}:?%{MINUTE}(?::?%{SECOND}) (?:AM|PM)
# yyyy-MM-dd HH:mm:ss,SSS ZZZ eg: 2014-01-09 17:32:25,527 -0800
TOMCAT_DATESTAMP 20%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{HOUR}:?%{MINUTE}(?::?%{SECOND}) %{ISO8601_TIMEZONE}
CATALINALOG %{CATALINA_DATESTAMP:timestamp} %{JAVACLASS:class} %{JAVALOGMESSAGE:logmessage}
# 2014-01-09 20:03:28,269 -0800 | ERROR | com.example.service.ExampleService - something compeletely unexpected happened...
TOMCATLOG %{TOMCAT_DATESTAMP:timestamp} \| %{LOGLEVEL:level} \| %{JAVACLASS:class} - %{JAVALOGMESSAGE:logmessage}
通過對比我們可以很簡單的先把日志相同時間的合并:
[[email protected] etc]# cat tomcat.conf
input{stdin{}}
filter {
multiline {
pattern => "(^%{CATALINA_DATESTAMP})"
negate => true
what => "previous"
}
if "_grokparsefailure" in [tags] {
drop { }
}
grok {
match => [ "message", "%{CATALINALOG}" ]
}
date {
match => [ "timestamp", "yyyy-MM-dd HH:mm:ss,SSS Z", "MMM dd, yyyy HH:mm:ss a" ]
}
}
output{stdout{codec=>rubydebug}}
##先看測試資料,要比較小一點的:
Jan 05, 2017 10:53:35 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 728 ms
Jan 05, 2017 10:53:35 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Jan 05, 2017 10:53:35 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.73
測試效果:
"@timestamp" => 2017-01-05T03:45:46.749Z,
"@version" => "1",
"host" => "controller",
"message" => "Jan 05, 2017 10:53:35 AM org.apache.catalina.startup.Catalina load\nINFO: Initialization processed in 728 ms",
"tags" => [
[0] "multiline"
]
}
{
"@timestamp" => 2017-01-05T03:45:46.760Z,
"@version" => "1",
"host" => "controller",
"message" => "Jan 05, 2017 10:53:35 AM org.apache.catalina.core.StandardService startInternal\nINFO: Starting service Catalina",
"tags" => [
[0] "multiline"
]
}
{
"@timestamp" => 2017-01-05T03:45:46.780Z,
"@version" => "1",
"host" => "controller",
"message" => "Jan 05, 2017 10:53:35 AM org.apache.catalina.core.StandardEngine startInternal\nINFO: Starting Servlet Engine: Apache Tomcat/7.0.73",
"tags" => [
[0] "multiline"
]
}
3、 之前用的都是系統預設的catalina檔案管理日志,通過簡化的方式我們可以使用log4j的方式。
1、 安裝log4j:
1、下載下傳與Tomcat相應版本的tomcat-juli.jar 和 tomcat-juli-adapters.jar,及log4j-1.2.17.jar,放在tomcat/lib目錄中 附上網址:http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.73/bin/extras/ 下載下傳時注意你的 TOMCAT 版本
再将tomcat-juli.jar 複制到tomcat/bin目錄中,替換掉原來的
2、修改 Tomcat 的 conf/context.xml 檔案,将改為這步很重要。很多人會忘。
3、建立log4j.properties放在tomcat/lib中
[[email protected] lib]# cat log4j.properties
log4j.rootLogger=info,Console,R
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
#log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.appender.Console.layout.ConversionPattern=%d{yy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=${catalina.home}/logs/tomcat.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy.MM.dd HH:mm:ss} %5p %c{1}(%L):? %m%n
log4j.logger.org.apache=info, R
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=DEBUG, R
log4j.logger.org.apache.catalina.core=info, R
log4j.logger.org.apache.catalina.session=info, R
4、重新開機看到log目錄下生成tomcat.log檔案說明已經安裝成功了。
5、log4j當然可以指定生成日志檔案的格式:
log4j.appender.R.layout.ConversionPattern={"debug_level":"%p","debug_timestamp":"%d{ISO8601}","debug_thread":"%t","debug_file":"%F", "debug_line":"%L","debug_message":"%m"}%n
##生成日志之後直接解析成json即可。
6、當然也有一個比較優秀的插件,也是我們推薦的方式:log4j-jsonevent-layout:
這玩意兒的作用相當于我們在nginx中幹的事兒,直接将log4j的日志格式定義成json的,有助于性能提升~
7、安裝:
先上傳一下幾個包,已經從官方打包了幾個jar包,确實的話很容易失敗和報錯:
commons-lang-2.6.jar
jsonevent-layout-1.8-SNAPSHOT.jar
json-smart-1.1.1.jar
7、 修改log4j.properties,直接把日志發送到Logstash:
[[email protected] lib]# cat log4j.properties
log4j.rootCategory=info, RollingLog ###為了友善出日志我們用Info,線上大家可以用WARN
log4j.appender.RollingLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.RollingLog.Threshold=TRACE
log4j.appender.RollingLog.File=${catalina.home}/logs/api.log
log4j.appender.RollingLog.DatePattern=.yyyy-MM-dd
log4j.appender.RollingLog.layout=net.logstash.log4j.JSONEventLayoutV1
###備注:重新開機後我們生成了相關日志在api.log下面,下面我們用json格式可以直接解析他了。
看一下我們需要做的比對檔案:
[[email protected] etc]# cat tomcat_log4j_layout.conf
input {
file {
codec => json
path => "/usr/local/src/apache-tomcat-7.0.73/logs/api.log"
type => "log4j"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
output{
if[type] == "log4j"{
redis {
host => "192.168.0.46"
port => 6379
data_type => "list"
key => "logstash:log4j"
}
}
}