概要
帶着問題去看教程:
-
不是用logstash來監聽我們的日志,我們可以使用logback配置來使用TCP appender通過TCP協議將日志發送到遠程Logstash實例。
-
我們可以使用Logstash指向多個日志文件。
-
我們可以在logstash配置文件中使用更復雜的過濾器,以根據需要執行更多操作。
-
我們可以使用遠程ELK集群指向我們的日志文件,或者將日志推入,這在將所有應用程序部署到雲中時基本上是必需的。
-
在logstash中創建不同的索引模式。
通過使用微服務,我們已經能夠克服許多遺留問題,並且它允許我們創建穩定的分布式應用程序,並對代碼,團隊規模,維護,發布周期,雲計算等進行所需的控制。但它也引入了一些挑戰。其他領域,例如分布式日志管理和查看在許多服務中分布的完整事務的日志和一般的分布式調試的能力。
實際上,挑戰在於微服務是相互隔離的,它們不共享公共數據庫和日志文件。隨着微服務數量的增加以及我們使用自動化持續集成工具實現雲部署,當我們遇到任何問題時,非常有必要對組件進行一些調試。
感謝開源運動。我們已經擁有了一系列工具,如果一起使用可以發揮魔力。一組如此受歡迎的工具是Elastic Search,Logstash和Kibana - 一起稱為ELK Stack 。它們用於實時搜索,分析和可視化日志數據。
ELK Stack
-
Elasticsearch是一個基於JSON的分布式搜索和分析引擎,專為水平可擴展性,最高可靠性和易管理性而設計。
-
Logstash是一個動態數據收集管道,具有可擴展的插件生態系統和強大的Elasticsearch協同作用。
-
Kibana通過UI 提供數據可視化。
ELK Stack架構
Logstash根據我們設置的過濾條件處理應用程序日志文件,並將這些日志發送到Elasticsearch。通過Kibana,我們可以在需要時查看和分析這些日志。
ELK配置
所有這三個工具都基於JVM,在開始安裝之前,請驗證JDK是否已正確配置。檢查標准JDK 1.8安裝,JAVA_HOME並且PATH已經完成設置。
Elasticsearch
-
從此下載頁面下載最新版本的Elasticsearch 並將其解壓縮到任何文件夾中。
-
bin\elasticsearch.bat從命令提示符運行。 -
默認情況下,它將從http:// localhost:9200
Kibana
-
從下載頁面下載最新的發行版並解壓縮到任何文件夾中。
-
config/kibana.yml在編輯器中打開並設置elasticsearch.url為指向您的Elasticsearch實例。在我們的例子中,我們將使用本地實例取消注釋elasticsearch.url: "http://localhost:9200" -
bin\kibana.bat從命令提示符運行。 -
成功啟動后,Kibana將啟動默認端口
5601,Kibana UI將在http:// localhost:5601上提供
Logstash
-
從下載頁面下載最新的發行版並解壓縮到任何文件夾中。
-
logstash.conf根據配置說明創建一個文件。在實際演示時間內,我們將再次進行精確配置。現在運行
bin/logstash -f logstash.conf以啟動logstash
ELK堆棧未啟動並正在運行。現在我們需要創建一些微服務並指向API日志路徑的logstash。
創建微服務
創建Spring Boot項目
讓我們使用spring boot創建一個應用程序,以縮短開發時間。請按照這些步驟啟動此服務。
添加REST端點
添加一個RestController類會暴露一些端點一樣/elk,/elkdemo,/exception。實際上我們只會測試幾個日志語句,因此可以根據您的選擇隨意添加/修改日志。
package
com.example.howtodoinjava.elkexamplespringboot;
import
java.io.PrintWriter;
import
java.io.StringWriter;
import
java.util.Date;
import
org.apache.log4j.Level;
import
org.apache.log4j.Logger;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.context.annotation.Bean;
import
org.springframework.core.ParameterizedTypeReference;
import
org.springframework.http.HttpMethod;
import
org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RestController;
import
org.springframework.web.client.RestTemplate;
@SpringBootApplication
public
class
ElkExampleSpringBootApplication {
public
static
void
main(String[] args) {
SpringApplication.run(ElkExampleSpringBootApplication.
class
, args);
}
}
@RestController
class
ELKController {
private
static
final
Logger LOG = Logger.getLogger(ELKController.
class
.getName());
@Autowired
RestTemplate restTemplete;
@Bean
RestTemplate restTemplate() {
return
new
RestTemplate();
}
@RequestMapping
(value =
"/elkdemo"
)
public
String helloWorld() {
String response =
"Hello user ! "
+
new
Date();
LOG.log(Level.INFO,
"/elkdemo - > "
+ response);
return
response;
}
@RequestMapping
(value =
"/elk"
)
public
String helloWorld1() {
String response = restTemplete.exchange(
"http://localhost:8080/elkdemo"
, HttpMethod.GET,
null
,
new
ParameterizedTypeReference() {
}).getBody();
LOG.log(Level.INFO,
"/elk - > "
+ response);
try
{
String exceptionrsp = restTemplete.exchange(
"http://localhost:8080/exception"
, HttpMethod.GET,
null
,
new
ParameterizedTypeReference() {
}).getBody();
LOG.log(Level.INFO,
"/elk trying to print exception - > "
+ exceptionrsp);
response = response +
" === "
+ exceptionrsp;
}
catch
(Exception e) {
// exception should not reach here. Really bad practice :)
}
return
response;
}
@RequestMapping
(value =
"/exception"
)
public
String exception() {
String rsp =
""
;
try
{
int
i =
1
/
0
;
// should get exception
}
catch
(Exception e) {
e.printStackTrace();
LOG.error(e);
StringWriter sw =
new
StringWriter();
PrintWriter pw =
new
PrintWriter(sw);
e.printStackTrace(pw);
String sStackTrace = sw.toString();
// stack trace as a string
LOG.error(
"Exception As String :: - > "
+sStackTrace);
rsp = sStackTrace;
}
return
rsp;
}
}
|
配置Spring引導記錄
application.properties在resources文件夾下打開並添加以下配置條目。
logging.file=elk-example.log
spring.application.name = elk-example
|
驗證微服務生成的日志
通過瀏覽http:// localhost:8080 / elk,mvn clean install使用命令java -jar target\elk-example-spring-boot-0.0.1-SNAPSHOT.jar和測試來執行最終的maven構建並啟動應用程序。
不要害怕看到屏幕上的大堆棧跟蹤,因為有意識地看看ELK如何處理異常消息。
轉到應用程序根目錄並驗證是否elk-example.log已創建日志文件,並對端點執行幾次訪問,並驗證日志文件中是否添加了日志。
Logstash配置
我們需要創建一個logstash配置文件,以便它監聽日志文件並將日志消息推送到彈性搜索。以下是示例中使用的logstash 配置,請根據您的設置更改日志路徑。
input {
file {
type =>
"java"
path =>
"F:/Study/eclipse_workspace_mars/elk-example-spring-boot/elk-example.log"
codec => multiline {
pattern =>
"^%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME}.*"
negate =>
"true"
what =>
"previous"
}
}
}
filter {
#If log line contains tab character followed by
'at'
then we will tag that entry as stacktrace
if
[message] =~
"\tat"
{
grok {
match => [
"message"
,
"^(\tat)"
]
add_tag => [
"stacktrace"
]
}
}
grok {
match => [
"message"
,
"(?<timestamp>%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME}) %{LOGLEVEL:level} %{NUMBER:pid} --- \[(?<thread>[A-Za-z0-9-]+)\] [A-Za-z0-9.]*\.(?<class>[A-Za-z0-9#_]+)\s*:\s+(?<logmessage>.*)"
,
"message"
,
"(?<timestamp>%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME}) %{LOGLEVEL:level} %{NUMBER:pid} --- .+? :\s+(?<logmessage>.*)"
]
}
date {
match => [
"timestamp"
,
"yyyy-MM-dd HH:mm:ss.SSS"
]
}
}
output {
stdout {
codec => rubydebug
}
# Sending properly parsed log events to elasticsearch
elasticsearch {
hosts => [
"localhost:9200"
]
}
}
|
Kibana配置
在查看Kibana中的日志之前,我們需要配置索引模式。我們可以配置logstash-*為默認配置。我們總是可以在logstash端更改此索引模式並在Kibana中進行配置。為簡單起見,我們將使用默認配置。
索引模式管理頁面如下所示。通過這種配置,我們將Kibana指向您選擇的Elasticsearch索引。Logstash使用名稱模式創建索引。logstash-YYYY.MM.DD我們可以在Kibana控制台http:// localhost:5601 / app / kibana中執行所有這些配置,然后轉到左側面板中的Management鏈接。

驗證ELK
現在,當所有組件都啟動並運行時,讓我們驗證整個生態系統。
轉到應用程序並測試端點幾次以便生成日志,然后轉到Kibana控制台,看看日志是否正確堆疊在Kibana中,還有許多額外的功能,比如我們可以過濾,查看內置的不同圖表等。
以下是Kibana中生成的日志的視圖。

