你居然還去伺服器上撈日誌,搭個日誌收集系統難道不香麼!
摘要
ELK日誌收集系統進階使用,本文主要講解如何打造一個線上環境真實可用的日誌收集系統。有了它,你就可以和去伺服器上撈日誌說再見了!
ELK環境安裝
ELK是指Elasticsearch、Kibana、Logstash這三種服務搭建的日誌收集系統,具體搭建方式可以參考《SpringBoot應用整合ELK實現日誌收集》。這裡僅提供最新版本的docker-compose指令碼和一些安裝要點。
docker-compose指令碼
-
version: '3'
-
services:
-
elasticsearch:
-
image: elasticsearch:6.4.0
-
container_name: elasticsearch
-
environment:
-
- "cluster.name=elasticsearch" #設定叢集名稱為elasticsearch
-
- "discovery.type=single-node" #以單一節點模式啟動
-
- "ES_JAVA_OPTS=-Xms512m -Xmx512m" #設定使用jvm記憶體大小
-
- TZ=Asia/Shanghai
-
volumes:
-
- /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins #外掛檔案掛載
-
- /mydata/elasticsearch/data:/usr/share/elasticsearch/data #資料檔案掛載
-
ports:
-
- 9200:9200
-
- 9300:9300
-
kibana:
-
image: kibana:6.4.0
-
container_name: kibana
-
links:
-
- elasticsearch:es #可以用es這個域名訪問elasticsearch服務
-
depends_on:
-
- elasticsearch #kibana在elasticsearch啟動之後再啟動
-
environment:
-
- "elasticsearch.hosts=http://es:9200" #設定訪問elasticsearch的地址
-
- TZ=Asia/Shanghai
-
ports:
-
- 5601:5601
-
logstash:
-
image: logstash:6.4.0
-
container_name: logstash
-
environment:
-
- TZ=Asia/Shanghai
-
volumes:
-
- /mydata/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf #掛載logstash的配置檔案
-
depends_on:
-
- elasticsearch #kibana在elasticsearch啟動之後再啟動
-
links:
-
- elasticsearch:es #可以用es這個域名訪問elasticsearch服務
-
ports:
-
- 4560:4560
-
- 4561:4561
-
- 4562:4562
-
- 4563:4563
安裝要點
- 使用
docker-compose
命令執行所有服務:
docker-compose up -d
- 第一次啟動可能會發現Elasticsearch
無法啟動
,那是因為/usr/share/elasticsearch/data
目錄沒有訪問許可權,只需要修改/mydata/elasticsearch/dat
a目錄的許可權,再重新啟動;
chmod 777 /mydata/elasticsearch/data/
- Logstash需要安裝
json_lines
外掛。
-
logstash-plugin install logstash-codec-json_lines
-
複製程式碼
分場景收集日誌
這裡為了方便我們檢視日誌,提出一個分場景收集日誌的概念,把日誌分為以下四種。
- 除錯日誌:最全日誌,包含了應用中所有
DEBUG
級別以上的日誌,僅在開發、測試環境中開啟收集; - 錯誤日誌:只包含應用中所有
ERROR
級別的日誌,所有環境只都開啟收集; - 業務日誌:在我們應用
對應包下
列印的日誌,可用於檢視我們自己在應用中列印的業務日誌; - 記錄日誌:每個介面的
訪問記錄
,可以用來檢視介面執行效率,獲取介面訪問引數。
Logback配置詳解
要實現上面的分場景收集日誌,主要通過Logback的配置來實現,我們先來了解下Logback的配置吧!
完全配置
在SpringBoot中,如果我們想要自定義Logback的配置,需要自行編寫
logback-spring.xml
檔案,下面是我們這次要使用的完全配置。
-
<?xml version="1.0" encoding="UTF-8"?>
-
<!DOCTYPE configuration>
-
<configuration>
-
<!--引用預設日誌配置-->
-
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
-
<!--使用預設的控制檯日誌輸出實現-->
-
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
-
<!--應用名稱-->
-
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="springBoot"/>
-
<!--日誌檔案儲存路徑-->
-
<property name="LOG_FILE_PATH" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/logs}"/>
-
<!--LogStash訪問host-->
-
<springProperty name="LOG_STASH_HOST" scope="context" source="logstash.host" defaultValue="localhost"/>
-
<!--DEBUG日誌輸出到檔案-->
-
<appender name="FILE_DEBUG"
-
class="ch.qos.logback.core.rolling.RollingFileAppender">
-
<!--輸出DEBUG以上級別日誌-->
-
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-
<level>DEBUG</level>
-
</filter>
-
<encoder>
-
<!--設定為預設的檔案日誌格式-->
-
<pattern>${FILE_LOG_PATTERN}</pattern>
-
<charset>UTF-8</charset>
-
</encoder>
-
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
<!--設定檔案命名格式-->
-
<fileNamePattern>${LOG_FILE_PATH}/debug/${APP_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
-
<!--設定日誌檔案大小,超過就重新生成檔案,預設10M-->
-
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
-
<!--日誌檔案保留天數,預設30天-->
-
<maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
-
</rollingPolicy>
-
</appender>
-
<!--ERROR日誌輸出到檔案-->
-
<appender name="FILE_ERROR"
-
class="ch.qos.logback.core.rolling.RollingFileAppender">
-
<!--只輸出ERROR級別的日誌-->
-
<filter class="ch.qos.logback.classic.filter.LevelFilter">
-
<level>ERROR</level>
-
<onMatch>ACCEPT</onMatch>
-
<onMismatch>DENY</onMismatch>
-
</filter>
-
<encoder>
-
<!--設定為預設的檔案日誌格式-->
-
<pattern>${FILE_LOG_PATTERN}</pattern>
-
<charset>UTF-8</charset>
-
</encoder>
-
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
<!--設定檔案命名格式-->
-
<fileNamePattern>${LOG_FILE_PATH}/error/${APP_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
-
<!--設定日誌檔案大小,超過就重新生成檔案,預設10M-->
-
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
-
<!--日誌檔案保留天數,預設30天-->
-
<maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
-
</rollingPolicy>
-
</appender>
-
<!--DEBUG日誌輸出到LogStash-->
-
<appender name="LOG_STASH_DEBUG" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
-
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-
<level>DEBUG</level>
-
</filter>
-
<destination>${LOG_STASH_HOST}:4560</destination>
-
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
-
<providers>
-
<timestamp>
-
<timeZone>Asia/Shanghai</timeZone>
-
</timestamp>
-
<!--自定義日誌輸出格式-->
-
<pattern>
-
<pattern>
-
{
-
"project": "mall-tiny",
-
"level": "%level",
-
"service": "${APP_NAME:-}",
-
"pid": "${PID:-}",
-
"thread": "%thread",
-
"class": "%logger",
-
"message": "%message",
-
"stack_trace": "%exception{20}"
-
}
-
</pattern>
-
</pattern>
-
</providers>
-
</encoder>
-
<!--當有多個LogStash服務時,設定訪問策略為輪詢-->
-
<connectionStrategy>
-
<roundRobin>
-
<connectionTTL>5 minutes</connectionTTL>
-
</roundRobin>
-
</connectionStrategy>
-
</appender>
-
<!--ERROR日誌輸出到LogStash-->
-
<appender name="LOG_STASH_ERROR" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
-
<filter class="ch.qos.logback.classic.filter.LevelFilter">
-
<level>ERROR</level>
-
<onMatch>ACCEPT</onMatch>
-
<onMismatch>DENY</onMismatch>
-
</filter>
-
<destination>${LOG_STASH_HOST}:4561</destination>
-
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
-
<providers>
-
<timestamp>
-
<timeZone>Asia/Shanghai</timeZone>
-
</timestamp>
-
<!--自定義日誌輸出格式-->
-
<pattern>
-
<pattern>
-
{
-
"project": "mall-tiny",
-
"level": "%level",
-
"service": "${APP_NAME:-}",
-
"pid": "${PID:-}",
-
"thread": "%thread",
-
"class": "%logger",
-
"message": "%message",
-
"stack_trace": "%exception{20}"
-
}
-
</pattern>
-
</pattern>
-
</providers>
-
</encoder>
-
<!--當有多個LogStash服務時,設定訪問策略為輪詢-->
-
<connectionStrategy>
-
<roundRobin>
-
<connectionTTL>5 minutes</connectionTTL>
-
</roundRobin>
-
</connectionStrategy>
-
</appender>
-
<!--業務日誌輸出到LogStash-->
-
<appender name="LOG_STASH_BUSINESS" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
-
<destination>${LOG_STASH_HOST}:4562</destination>
-
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
-
<providers>
-
<timestamp>
-
<timeZone>Asia/Shanghai</timeZone>
-
</timestamp>
-
<!--自定義日誌輸出格式-->
-
<pattern>
-
<pattern>
-
{
-
"project": "mall-tiny",
-
"level": "%level",
-
"service": "${APP_NAME:-}",
-
"pid": "${PID:-}",
-
"thread": "%thread",
-
"class": "%logger",
-
"message": "%message",
-
"stack_trace": "%exception{20}"
-
}
-
</pattern>
-
</pattern>
-
</providers>
-
</encoder>
-
<!--當有多個LogStash服務時,設定訪問策略為輪詢-->
-
<connectionStrategy>
-
<roundRobin>
-
<connectionTTL>5 minutes</connectionTTL>
-
</roundRobin>
-
</connectionStrategy>
-
</appender>
-
<!--介面訪問記錄日誌輸出到LogStash-->
-
<appender name="LOG_STASH_RECORD" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
-
<destination>${LOG_STASH_HOST}:4563</destination>
-
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
-
<providers>
-
<timestamp>
-
<timeZone>Asia/Shanghai</timeZone>
-
</timestamp>
-
<!--自定義日誌輸出格式-->
-
<pattern>
-
<pattern>
-
{
-
"project": "mall-tiny",
-
"level": "%level",
-
"service": "${APP_NAME:-}",
-
"class": "%logger",
-
"message": "%message"
-
}
-
</pattern>
-
</pattern>
-
</providers>
-
</encoder>
-
<!--當有多個LogStash服務時,設定訪問策略為輪詢-->
-
<connectionStrategy>
-
<roundRobin>
-
<connectionTTL>5 minutes</connectionTTL>
-
</roundRobin>
-
</connectionStrategy>
-
</appender>
-
<!--控制框架輸出日誌-->
-
<logger name="org.slf4j" level="INFO"/>
-
<logger name="springfox" level="INFO"/>
-
<logger name="io.swagger" level="INFO"/>
-
<logger name="org.springframework" level="INFO"/>
-
<logger name="org.hibernate.validator" level="INFO"/>
-
<root level="DEBUG">
-
<appender-ref ref="CONSOLE"/>
-
<!--<appender-ref ref="FILE_DEBUG"/>-->
-
<!--<appender-ref ref="FILE_ERROR"/>-->
-
<appender-ref ref="LOG_STASH_DEBUG"/>
-
<appender-ref ref="LOG_STASH_ERROR"/>
-
</root>
-
<logger name="com.macro.mall.tiny.component" level="DEBUG">
-
<appender-ref ref="LOG_STASH_RECORD"/>
-
</logger>
-
<logger name="com.macro.mall" level="DEBUG">
-
<appender-ref ref="LOG_STASH_BUSINESS"/>
-
</logger>
-
</configuration>
配置要點解析
使用預設的日誌配置
一般我們不需要自定義控制檯輸出,可以採用預設配置,具體配置參考
console-appender.xml
,該檔案在spring-boot-${version}.jar
下面。
-
<!--引用預設日誌配置-->
-
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
-
<!--使用預設的控制檯日誌輸出實現-->
-
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
springProperty
該標籤可以從SpringBoot的配置檔案中獲取配置屬性,比如說在不同環境下我們的Logstash服務地址是不一樣的,我們就可以把該地址定義在
application.yml
來使用。
例如在application-dev.yml
中定義了這些屬性:
-
logstash:
-
host: localhost
在logback-spring.xml
中就可以直接這樣使用:
-
<!--應用名稱-->
-
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="springBoot"/>
-
<!--LogStash訪問host-->
-
<springProperty name="LOG_STASH_HOST" scope="context" source="logstash.host" defaultValue="localhost"/>
filter
在Logback中有兩種不同的過濾器,用來過濾日誌輸出。
ThresholdFilter:臨界值過濾器,過濾掉低於指定臨界值的日誌,比如下面的配置將過濾掉所有低於INFO級別的日誌。
-
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-
<level>INFO</level>
-
</filter>
LevelFilter:級別過濾器,根據日誌級別進行過濾,比如下面的配置將過濾掉所有非ERROR級別的日誌。
-
<filter class="ch.qos.logback.classic.filter.LevelFilter">
-
<level>ERROR</level>
-
<onMatch>ACCEPT</onMatch>
-
<onMismatch>DENY</onMismatch>
-
</filter>
appender
Appender可以用來控制日誌的輸出形式,主要有下面三種。
- ConsoleAppender:控制日誌輸出到控制檯的形式,比如在
console-appender.xml
中定義的預設控制檯輸出。
-
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-
<encoder>
-
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
-
</encoder>
-
</appender>
- RollingFileAppender:控制日誌輸出到檔案的形式,可以控制日誌檔案生成策略,比如檔名稱格式、超過多大重新生成檔案以及刪除超過多少天的檔案。
-
<!--ERROR日誌輸出到檔案-->
-
<appender name="FILE_ERROR"
-
class="ch.qos.logback.core.rolling.RollingFileAppender">
-
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
<!--設定檔案命名格式-->
-
<fileNamePattern>${LOG_FILE_PATH}/error/${APP_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
-
<!--設定日誌檔案大小,超過就重新生成檔案,預設10M-->
-
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
-
<!--日誌檔案保留天數,預設30天-->
-
<maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
-
</rollingPolicy>
-
</appender>
- LogstashTcpSocketAppender:控制日誌輸出到Logstash的形式,可以用來配置Logstash的地址、訪問策略以及日誌的格式。
-
<!--ERROR日誌輸出到LogStash-->
-
<appender name="LOG_STASH_ERROR" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
-
<destination>${LOG_STASH_HOST}:4561</destination>
-
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
-
<providers>
-
<timestamp>
-
<timeZone>Asia/Shanghai</timeZone>
-
</timestamp>
-
<!--自定義日誌輸出格式-->
-
<pattern>
-
<pattern>
-
{
-
"project": "mall-tiny",
-
"level": "%level",
-
"service": "${APP_NAME:-}",
-
"pid": "${PID:-}",
-
"thread": "%thread",
-
"class": "%logger",
-
"message": "%message",
-
"stack_trace": "%exception{20}"
-
}
-
</pattern>
-
</pattern>
-
</providers>
-
</encoder>
-
<!--當有多個LogStash服務時,設定訪問策略為輪詢-->
-
<connectionStrategy>
-
<roundRobin>
-
<connectionTTL>5 minutes</connectionTTL>
-
</roundRobin>
-
</connectionStrategy>
-
</appender>
logger
只有配置到logger節點上的appender才會被使用,logger用於配置哪種條件下的日誌被列印,root是一種特殊的appender,下面介紹下日誌劃分的條件。
- 除錯日誌:所有的DEBUG級別以上日誌;
- 錯誤日誌:所有的ERROR級別日誌;
- 業務日誌:
com.macro.mall
包下的所有DEBUG級別以上日誌; - 記錄日誌:
com.macro.mall.tiny.component.WebLogAspect
類下所有DEBUG級別以上日誌,該類是統計介面訪問資訊的AOP切面類。
控制框架輸出日誌
還有一些使用框架內部的日誌,DEBUG級別的日誌對我們並沒有啥用處,都可以設定為了INFO以上級別。
-
<!--控制框架輸出日誌-->
-
<logger name="org.slf4j" level="INFO"/>
-
<logger name="springfox" level="INFO"/>
-
<logger name="io.swagger" level="INFO"/>
-
<logger name="org.springframework" level="INFO"/>
-
<logger name="org.hibernate.validator" level="INFO"/>
Logstash配置詳解
接下來我們需要配置下Logstash,讓它可以分場景收集不同的日誌,下面詳細介紹下使用到的配置。
完全配置
-
input {
-
tcp {
-
mode => "server"
-
host => "0.0.0.0"
-
port => 4560
-
codec => json_lines
-
type => "debug"
-
}
-
tcp {
-
mode => "server"
-
host => "0.0.0.0"
-
port => 4561
-
codec => json_lines
-
type => "error"
-
}
-
tcp {
-
mode => "server"
-
host => "0.0.0.0"
-
port => 4562
-
codec => json_lines
-
type => "business"
-
}
-
tcp {
-
mode => "server"
-
host => "0.0.0.0"
-
port => 4563
-
codec => json_lines
-
type => "record"
-
}
-
}
-
filter{
-
if [type] == "record" {
-
mutate {
-
remove_field => "port"
-
remove_field => "host"
-
remove_field => "@version"
-
}
-
json {
-
source => "message"
-
remove_field => ["message"]
-
}
-
}
-
}
-
output {
-
elasticsearch {
-
hosts => ["es:9200"]
-
action => "index"
-
codec => json
-
index => "mall-tiny-%{type}-%{+YYYY.MM.dd}"
-
template_name => "mall-tiny"
-
}
-
}
配置要點
- input:使用不同埠收集不同型別的日誌,從4560~4563開啟四個埠;
- filter:對於記錄型別的日誌,直接將JSON格式的message轉化到source中去,便於搜尋檢視;
- output:按型別、時間自定義索引格式。
SpringBoot配置
在SpringBoot中的配置可以直接用來覆蓋Logback中的配置,比如
logging.level.root
就可以覆蓋<root>
節點中的level
配置。
- 開發環境配置:application-dev.yml
-
logstash:
-
host: localhost
-
logging:
-
level:
-
root: debug
- 測試環境配置:application-test.yml
-
logstash:
-
host: 192.168.3.101
-
logging:
-
level:
-
root: debug
- 生產環境配置:application-prod.yml
-
logstash:
-
host: logstash-prod
-
logging:
-
level:
-
root: info
Kibana進階使用
進過上面ELK環境的搭建和配置以後,我們的日誌收集系統終於可以用起來了,下面介紹下在Kibana中的使用技巧!
- 首先啟動我們的測試Demo,然後通用呼叫介面(可以使用Swagger),產生一些日誌資訊;
- 呼叫完成後在
Management->Kibana->Index Patterns
中可以建立Index Patterns
,Kibana服務訪問地址:http://192.168.3.101:5601
- 建立完成後可以在
Discover
中檢視所有日誌,除錯日誌只需直接檢視mall-tiny-debug*
模式的日誌即可;
- 對於日誌搜尋,kibana有非常強大的提示功能,可以通過搜尋欄右側的
Options
按鈕開啟;
- 記錄日誌只需直接檢視
mall-tiny-record*
模式的日誌即可,如果我們想要搜尋uri為/brand/listAll
的記錄日誌,只需在搜尋欄中輸入uri : "/brand/listAll"
;
- 錯誤日誌,只需直接檢視
mall-tiny-error*
模式的日誌即可;
- 業務日誌,只需直接檢視
mall-tiny-business*
模式的日誌即可,這裡我們可以檢視一些SQL日誌的輸出;
- 如果日誌太大了,可以通過
Elasticsearch->Index Management
選擇刪除即可。
專案原始碼地址