使用ELK管理SpringBoot日志
当我们开发一个新项目的时候,一个经常遇到的问题是日志的管理。ELK栈(Elastic,Logstash,Kibana)是一个功能强大且免费的日志管理解决方案。在本文中,将为您展示如何安装、如何设置ELK,如何使用它来管理SpringBoot应用程序中的默认格式的日志。
在本文中,我们设置了一个演示SpringBoot应用程序,并且启用了日志管理,同时使用Logstash配置把日志条目送到了Elasticsearch。
应用程序会把日志存在一个文件中。Logstash将读取并解析日志文件并将日志条目发送给Elasticsearch实例。最后,我们将使用Kibana4(ElasticsearchWeb前端)来搜索和分析日志。
步骤一安装Elasticsearch
下载Elasticsearch,下载地址:https://www.elastic.co/downloads/elasticsearch 解压缩到一个路径(解压缩)
运行Elasticsearch(bin/elasticsearch或bin/elasticsearch.bat在Windows上) 检查它是在使用curl-XGEThttp://localhost:9200运行 下面是如何操作(下面步骤是为OSX编写的,但其它操作系统大致相同)
wgethttps://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.1.zip unzipelasticsearch-1.7.1.zip cdelasticsearch-1.7.1 bin/elasticsearch
现在,Elasticsearch应该已经在运行中了。您可以使用curl命令来验证。在单独的终端窗口中执行Elasticsearch状态页面的GET请求: curl-XGEThttp://localhost:9200 如果一切正常,你应该得到以下结果:
{ "status":200, "name":"Tartarus", "cluster_name":"elasticsearch", "version":{ "number":"1.7.1", "build_hash":"b88f43fc40b0bcd7f173a1f9ee2e97816de80b19", "build_timestamp":"2015-07-29T09:54:16Z", "build_snapshot":false, "lucene_version":"4.10.4" }, "tagline":"YouKnow,forSearch" }
步骤二安装InstallKibana04
下载Kibana,下载地址:https://www.elastic.co/downloads/kibana(请注意你的系统属性,下载与你系统相匹配的版本,链接给出的是OSX系统的)
解压缩文件 运行Kivana(bin/kibana)
通过把浏览器指向Kibana's来检查它是否在运行
下面是具体的做法:
wgethttps://download.elastic.co/kibana/kibana/kibana-4.1.1-darwin-x64.tar.gz tarxvzfkibana-4.1.1-darwin-x64.tar.gz cdkibana-4.1.1-darwin-x64 bin/kibana
将你的浏览器指向http://localhost:5601(如果页面显示正常,说明我做的很好,我们将在稍后配置它)。
步骤三安装Logstash
下载Logstash,下载地址:https://www.elastic.co/downloads/logstash
提取文件(解压缩) wgethttps://download.elastic.co/logstash/logstash/logstash-1.5.3.zip unziplogstash-1.5.3.zip
步骤四配置SpringBoot的日志文件
为了让Logstash传递文件到Elasticsearch,我们必须先配置SpringBoot来把日志条目存储到一个文件中。我们将建立以下传递路径:SpringBootApp——日志文件——Logstash——Elasticsearch。这里还有其它的方法可以完成同样的事情,比如配置logback来使用TCP附加器把日志发送到一个远程的Logstash,以及其它的有些配置。但我更喜欢文件方法,因为这样更简单、很自然(你可以很容易的把它添加到已存在的系统中),并且当Logstash停止工作或者Elasticearch宕机的时候,不会丢失或者破坏任何文件。
不管如何,让我们来配置SpringBoot的日志文件。最简单的方法是在application.properties中配置日志文件。添加下面一行就足够了:
logging.file=application.log 现在,SpringBoot将会在application.log中记录ERROR,WARN和INFO级别的信息,并且当信息量达到10M的时候更迭。
步骤五配置Logstash
通过配置Logstash可以了解SpringBoot的日志文件格式。这部分比较棘手。 我们需要创建一个Logstash配置文件。典型的Logstash配置文件包含三个部分:input、filter、output。每个部分包含执行相关部分处理的插件,例如:从文件中读取日志时间的文件输入插件,或者将日志时间发送到Elasticsearch的elasticseatch输出插件。
input部分定义了Logstash从哪里读取输入数据——在我们的例子中它是一个文件,所以我们将使用一个file插件multilinecodec。这基本上意味着我们的输入文件可能每个条目有多行。
Input部分 下面是输入部分的配置:
input{ file{ type=>"java" path=>"/path/to/application.log" codec=>multiline{ pattern=>"^%{YEAR}-%{MONTHNUM}-%{MONTHDAY}%{TIME}.*" negate=>"true" what=>"previous" } } }
我们将会用到file插件。 type被设置为java——这只是额外的元数据,以备将来使用多种类型的日志文件。 path是日志文件的绝对路径。它必须是绝对的——Logstash对这点很严格。
我们使用multilinecodec意味着多个行可能对应着一个日志事件。 为了检测在逻辑上与前一行分组的行,我们使用检测模式: pattern=>"^%{YEAR}-%{MONTHNUM}-%{MONTHDAY}%{TIME}.*"→每个新的日志事件都需要以日期开始。 negate=>"true"→如果它不以日期开始...... what=>"previous"→...然后,它应该与前一行分组。 文件输入插件,就像配置的一样,将会跟踪日志文件(例如:只读取文件末尾的新条目)。所以,测试的时候,为了让Logstash读取某些内容,您需要生成新的日志条目。
Filter部分 Filter部分包含对日志时间执行中间处理的插件。在我们的例子中国,事件可以是根据上述规则分组的单个日志行货多行日志事件。在Filter部分,我们会做几件事情:
如果一个日志事件包含堆栈跟踪,我们会标记它。这将有助于我们在后面寻找我们所期望的信息。解析出时间戳,日志等级,pid,线程,类名称(记录器实际)和日志信息。指定时间戳的区域和格式——Kibana将会用到它来进行实践的基本搜索。
上面提及的SpringBoot日志格式的过滤器部分看起来是这样的: filter{ #Ifloglinecontainstabcharacterfollowedby'at'thenwewilltagthatentryasstacktrace if[message]=~"\tat"{ grok{ match=>["message","^(\tat)"] add_tag=>["stacktrace"] } } #GrokkingSpringBoot'sdefaultlogformat grok{ match=>["message", "(?%{YEAR}-%{MONTHNUM}-%{MONTHDAY}%{TIME})%{LOGLEVEL:level}%{NUMBER:pid}---\[(?[A-Za-z0-9-]+)\][A-Za-z0-9.]*\.(?[A-Za-z0-9#_]+)\s*:\s+(?.*)", "message", "(?%{YEAR}-%{MONTHNUM}-%{MONTHDAY}%{TIME})%{LOGLEVEL:level}%{NUMBER:pid}---.+?:\s+(?.*)" ] } #Parsingouttimestampswhichareintimestampfieldthankstopreviousgroksection date{ match=>["timestamp","yyyy-MM-ddHH:mm:ss.SSS"] } }
说明 if[message]=~"\tat"→如果消息包含后面跟着at的tab字符(这是ruby语法),那么...... ...使用grok插件来标记堆栈踪迹: match=>["message","^(\tat)"]→当message匹配行的开头,后面跟着tab,之后跟着at,然后是... add_tag=>["stacktrace"]→...用stacktrace标签标记事件。 使用grok插件进行常规的SpringBoot日志消息解析: 第一种模式提取时间戳,级别,pid,线程,类名(实际上是记录器名称)和日志消息。 不幸的是,某些日志消息没有类似于类名的记录器名称(例如,Tomcat日志),因此第二个模式将跳过记录器/类字段并解析出时间戳,级别,pid,线程和日志消息。 使用date插件解析并设置事件日期: match=>["timestamp","yyyy-MM-ddHH:mm:ss.SSS"]→timestamp字段(早先grokked)包含指定格式的时间戳
Output部分 Output部分包含将事件数据发送到特定目标的输出插件。产出是事件管道的最后阶段。我们将把日志事件发送到stdout(控制台输出,用于调试)和Elasticsearch。 与Filter分相比,Output部分非常简单:
filter{ #Ifloglinecontainstabcharacterfollowedby'at'thenwewilltagthatentryasstacktrace if[message]=~"\tat"{ grok{ match=>["message","^(\tat)"] add_tag=>["stacktrace"] } } #GrokkingSpringBoot'sdefaultlogformat grok{ match=>["message", "(?%{YEAR}-%{MONTHNUM}-%{MONTHDAY}%{TIME})%{LOGLEVEL:level}%{NUMBER:pid}---\[(?[A-Za-z0-9-]+)\][A-Za-z0-9.]*\.(?[A-Za-z0-9#_]+)\s*:\s+(?.*)", "message", "(?%{YEAR}-%{MONTHNUM}-%{MONTHDAY}%{TIME})%{LOGLEVEL:level}%{NUMBER:pid}---.+?:\s+(?.*)"
]
}
#Parsingouttimestampswhichareintimestampfieldthankstopreviousgroksection
date{
match=>["timestamp","yyyy-MM-ddHH:mm:ss.SSS"]
}
}
说明:
我们正在使用多个输出:stdout和elasticsearch。
stdout{...}→stdout插件将日志事件打印到标准输出(控制台)。
codec=>rubydebug→使用类似JSON格式的漂亮打印事件。
elasticsearch{...}→elasticsearch插件将日志事件发送到Elasticsearch服务器。
host=>"127.0.0.1"→Elasticsearch所在的主机名在我们的例子中是localhost。
Update5/9/2016:在编写此更新时,Logstash的elasticsearch输出插件的最新版本使用hosts配置参数,而不是host上面的示例中所示。新参数将一组主机(例如elasticsearchcluster)作为值。换句话说,如果您正在使用最新的Logstash版本,请按如下所示配置elasticsearch输出插件:
elasticsearch{
hosts=>["127.0.0.1"]
}
把各个部分放在一起
最后,三个部分——input,filter和output需要复制粘贴到一起并保存在Logstash.conf配置文件中。一旦配置文件就位,并且Elasticsearch运行,我们可以运行Logstash:
elasticsearch{
hosts=>["127.0.0.1"]
}
如果一切顺利,Logstash正在传递日志时间到Elasticsearch。
步骤六配置Kibana
现在是我们再次访问KibanawebUI的时候了,我们已经在第二部中启动了,它应该在http://localhost:5601上运行。
首先,您需要将Kibana指向您选择的elasticsearch索引。Logstash创建索引的名称模式是:logstash-YYYY.MM.DD。在Kibana设置——索引中配置索引。
索引包含基于时间的事件(选择此项)
使用事件时间创建索引名称(选择此项)
索引模式间隔:日
索引名称或模式:[logstash-]YYYY.MM.DD
点击“创建索引”
现在,点击“Discover”标签。在我看来,“Discover”选项卡在Kibana中的确命名不正确-它应该被标记为“Search”而不是“Discover”,因为它允许您执行新的搜索并保存/管理它们。日志事件现在应该显示在主窗口中。如果不是,则再次检查屏幕右上角的时间段过滤器。默认表格默认有2列:Time和_source。为了使列表更有用,我们可以配置显示的列。从左侧的选择菜单中选择级别,类别和日志消息。
好的!您现在已准备好使用ELK堆栈来控制日志,并开始自定义和调整日志管理配置。
您可以从这里下载这篇文章时使用的示例应用程序:https://github.com/knes1/todo。它已被配置为将日志写入文件,并具有上述的Logstash配置(尽管需要调整绝对路径logstash.conf)。