您的日志就是您的数据:logstash + elasticsearch
今天的帖子的主題與日常的編碼和開發無關,但是涵蓋了一個非常重要的主題:我們的應用程序日志文件。 我們的應用程序確實會生成大量日志,如果處理正確,則非常有助于解決問題。 如果您啟動并運行一個應用程序并沒什么大不了,但是如今,應用程序(特別是Web應用程序)可以在數百臺服務器上運行。 有了這樣的規模,找出問題所在就成為了挑戰。 擁有某種視圖將所有正在運行的應用程序中的所有日志聚合到單個儀表板中,這樣我們就可以看到由碎片構成的整體畫面,這不是很好嗎? 請歡迎: Logstash ,日志聚合框架。
盡管它不是唯一可用的解決方案,但我發現Logstash易于使用且易于集成。 首先,我們甚至不需要在應用程序方面做任何事情, Logstash可以為我們完成所有工作。 讓我介紹一個示例項目:具有某些多線程活動的獨立Java應用程序。 使用出色的Logback庫(配置為SLF4J可以無縫替換)對配置文件進行日志記錄。 POM文件看起來非常簡單:
而且只有一個名為Starter的 Java類,它使用Executors服務同時執行一些工作。 當然,每個線程都會進行一些日志記錄,并且有時會引發異常。
package com.example.logstash;import java.util.ArrayList; import java.util.Collection; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException;import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class Starter {private final static Logger log = LoggerFactory.getLogger( Starter.class );public static void main( String[] args ) {final ExecutorService executor = Executors.newCachedThreadPool();final Collection< Future< Void > > futures = new ArrayList< Future< Void > >();final Random random = new Random();for( int i = 0; i < 10; ++i ) {futures.add( executor.submit(new Callable< Void >() {public Void call() throws Exception {int sleep = Math.abs( random.nextInt( 10000 ) % 10000 );log.warn( 'Sleeping for ' + sleep + 'ms' );Thread.sleep( sleep );return null;}}));}for( final Future< Void > future: futures ) {try {Void result = future.get( 3, TimeUnit.SECONDS );log.info( 'Result ' + result );} catch (InterruptedException | ExecutionException | TimeoutException ex ) {log.error( ex.getMessage(), ex );} }} }這個想法不僅要演示簡單的單行日志事件,還要演示著名的Java堆棧跟蹤。 當每個線程睡眠隨機的時間間隔時,每當從底層的Future對象請求計算結果并花費3秒鐘以上的時間返回時,都會引發TimeoutException。 最后一部分是Logback配置( logback.xml ):
<configuration scan="true" scanperiod="5 seconds"><appender name="FILE" class="ch.qos.logback.core.FileAppender"><file>/tmp/application.log</file><append>true</append><encoder><pattern>[%level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern></encoder></appender><root level="INFO"><appender-ref ref="FILE"></appender-ref></root> </configuration>而且我們很高興去! 請注意,文件路徑/tmp/application.log對應于Windows上的c:\ tmp \ application.log 。 運行我們的應用程序將用以下內容填充日志文件:
[WARN] 2013-02-19 19:26:03.175 [pool-2-thread-1] com.example.logstash.Starter - Sleeping for 2506ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-4] com.example.logstash.Starter - Sleeping for 9147ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-9] com.example.logstash.Starter - Sleeping for 3124ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-3] com.example.logstash.Starter - Sleeping for 6239ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-5] com.example.logstash.Starter - Sleeping for 4534ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-10] com.example.logstash.Starter - Sleeping for 1167ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-7] com.example.logstash.Starter - Sleeping for 7228ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-6] com.example.logstash.Starter - Sleeping for 1587ms [WARN] 2013-02-19 19:26:03.175 [pool-2-thread-8] com.example.logstash.Starter - Sleeping for 9457ms [WARN] 2013-02-19 19:26:03.176 [pool-2-thread-2] com.example.logstash.Starter - Sleeping for 1584ms [INFO] 2013-02-19 19:26:05.687 [main] com.example.logstash.Starter - Result null [INFO] 2013-02-19 19:26:05.687 [main] com.example.logstash.Starter - Result null [ERROR] 2013-02-19 19:26:08.695 [main] com.example.logstash.Starter - null java.util.concurrent.TimeoutException: nullat java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:258) ~[na:1.7.0_13]at java.util.concurrent.FutureTask.get(FutureTask.java:119) ~[na:1.7.0_13]at com.example.logstash.Starter.main(Starter.java:43) ~[classes/:na] [ERROR] 2013-02-19 19:26:11.696 [main] com.example.logstash.Starter - null java.util.concurrent.TimeoutException: nullat java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:258) ~[na:1.7.0_13]at java.util.concurrent.FutureTask.get(FutureTask.java:119) ~[na:1.7.0_13]at com.example.logstash.Starter.main(Starter.java:43) ~[classes/:na] [INFO] 2013-02-19 19:26:11.696 [main] com.example.logstash.Starter - Result null [INFO] 2013-02-19 19:26:11.696 [main] com.example.logstash.Starter - Result null [INFO] 2013-02-19 19:26:11.697 [main] com.example.logstash.Starter - Result null [INFO] 2013-02-19 19:26:12.639 [main] com.example.logstash.Starter - Result null [INFO] 2013-02-19 19:26:12.639 [main] com.example.logstash.Starter - Result null [INFO] 2013-02-19 19:26:12.639 [main] com.example.logstash.Starter - Result null現在,讓我們看看Logstash可以為我們做些什么。 從下載部分,我們獲得了單個JAR文件: logstash-1.1.9-monolithic.jar 。 這就是我們現在所需要的。 不幸的是,由于Windows上的這個錯誤,我們必須將logstash-1.1.9-monolithic.jar擴展到festash-1.1.9-monolithic文件夾中。 Logstash剛剛三個概念: 輸入 濾波器和輸出 。 這些在文檔中有很好的解釋。 在我們的例子中,輸入是應用程序的日志文件c:\ tmp \ application.log 。 但是輸出是什么? ElasticSearch似乎是一個很好的選擇:讓我們的日志可以隨時索引和搜索。 讓我們下載并運行它:
elasticsearch.bat -Des.index.store.type=memory -Des.network.host=localhost現在我們準備好集成Logstash了 ,它應該拖尾我們的日志文件,并將其直接提供給ElasticSearch 。 以下配置完全可以做到這一點( logstash.conf ):
input {file {add_field => [ 'host', 'my-dev-host' ]path => 'c:\tmp\application.log'type => 'app'format => 'plain'} }output {elasticsearch_http {host => 'localhost'port => 9200 type => 'app'flush_size => 10} }filter {multiline {type => 'app'pattern => '^[^\[]'what => 'previous' } }乍一看可能看起來不太清楚,但讓我解釋一下是什么。 因此,輸入為c:\ tmp \ application.log ,這是一個純文本文件( format =>'plain' )。 類型=>'app'用作簡單標記,因此可以通過具有相同類型的過濾器將不同類型的輸入路由到輸出。 add_field => ['host','my-dev-host']允許向傳入流fe主機名中注入其他任意數據。
輸出非常清晰:通過HTTP的ElasticSearch ,端口9200(默認設置)。 過濾器需要一點魔術,所有這些都是由于Java堆棧跟蹤。 多行過濾器會將堆棧跟蹤粘貼到其所屬的log語句,因此將其存儲為單個(大)多行。 讓我們運行Logstash :
java -cp logstash-1.1.9-monolithic logstash.runner agent -f logstash.conf大! 現在,每當我們運行應用程序時, Logstash都會監視日志文件,對其進行過濾,然后將其直接發送到ElasticSearch 。 很酷,但是我們如何進行搜索或至少查看我們擁有什么樣的數據? 雖然ElasticSearch有真棒REST API,我們可以用另一種優秀的項目, Kibana ,web用戶界面前端為ElasticSearch 。 安裝非常簡單,無縫。 經過一些必要的步驟后,我們啟動了Kibana并開始運行:
ruby kibana.rb默認情況下, Kibana在端口5601上提供了可用的Web UI,讓我們將瀏覽器指向它,即http:// localhost:5601 / ,我們應該看到類似的內容(請單擊圖像放大):
我們所有的日志語句(由主機名補充)都在那里。 異常(帶有堆棧跟蹤)與相關的log語句結合在一起。 日志級別,時間戳,所有內容均已顯示。 借助ElasticSearch ,可以立即使用全文搜索。
一切都很棒,但是我們的應用程序非常簡單。 這種方法是否可以跨多服務器/多應用程序部署工作? 我很確定它將正常工作。 Logstash與Redis , ZeroMQ , RabbitMQ … 的集成允許捕獲來自數十個不同來源的日志并將其合并到一個位置。 非常感謝Logstash伙計們!
參考: 您的日志就是您的數據:來自Andry Redko {devmind}博客的JCG合作伙伴 Andrey Redko的logstash + elasticsearch 。
翻譯自: https://www.javacodegeeks.com/2013/02/your-logs-are-your-data-logstash-elasticsearch.html
總結
以上是生活随笔為你收集整理的您的日志就是您的数据:logstash + elasticsearch的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 东风日产奇骏经典荣冠版车型上市:2.0L
- 下一篇: 膨胀的JavaBeans –不要在您的A