搭建Elasticsearch Logstash Kibana 日誌系統
分散式系統下由於日誌檔案分佈在不同的系統上,分析比較麻煩,通過搭建elk日誌系統,可快速排查日誌資訊。
Elasticsearch是大資料處理框架,使用的分散式儲存,可儲存海量資料;基於Lucense的搜尋引擎,實時高效的搜尋資料。
Logstash是一款強大的資料處理工具,它可以實現資料傳輸,格式處理,格式化輸出,還有強大的外掛功能,常用於日誌處理。
Kibana是為Elasticsearch設計的開源分析和視覺化平臺。
一、安裝Elasticsearch
通過https://www.elastic.co/downloads/past-releases#elasticsearch
二、安裝Kibana(版本必須與Elasticsearch保持一致)
通過https://www.elastic.co/downloads/past-releases#kibana官網下載7.1.0版本,安裝完成後修改kibana.yml檔案,中文顯示:i18n.locale: "zh-CN",es地址:
elasticsearch.hosts: ["http://127.0.0.1:9200"] 配置完成後訪問 http://127.0.0.1:5601
三、安裝Logstash
通過https://www.elastic.co/downloads/past-releases#logstash官網下載7.1.0版本,安裝完成後執行 logstash -e 'input { stdin {} } output { stdout{} }' 隨便輸入可見到傳輸資料,見到如下則安裝成功。
mac:~ mac$ logstash -e 'input { stdin {} } output { stdout{} }' Sending Logstash logs to /usr/local/logstash-7.1.0/logs which is now configured via log4j2.properties [2020-08-12T10:58:38,529][WARN ][logstash.config.source.multilocal] Ignoring the 'pipelines.yml' file because modules or command line options are specified [2020-08-12T10:58:38,554][INFO ][logstash.runner ] Starting Logstash {"logstash.version"=>"7.1.0"} [2020-08-12T10:58:45,121][INFO ][logstash.javapipeline ] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>4, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50, "pipeline.max_inflight"=>500, :thread=>"#<Thread:0x6f18e33d run>"} [2020-08-12T10:58:45,211][INFO ][logstash.javapipeline ] Pipeline started {"pipeline.id"=>"main"} The stdin plugin is now waiting for input: [2020-08-12T10:58:45,291][INFO ][logstash.agent ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]} [2020-08-12T10:58:45,707][INFO ][logstash.agent ] Successfully started Logstash API endpoint {:port=>9600}
hhh { "@version" => "1", "message" => "hhh", "@timestamp" => 2020-08-12T02:58:53.889Z, "host" => "mac.local" }
四、建立Spring Boot專案
引入pom依賴
<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>5.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.6.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.0.13</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-access</artifactId> <version>1.0.13</version> </dependency> <dependency> <groupId>org.logback-extensions</groupId> <artifactId>logback-ext-spring</artifactId> <version>0.1.2</version> <scope>compile</scope> </dependency>
建立logback-spring.xml,需要修改服務IP地址
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="10 seconds"> <include resource="org/springframework/boot/logging/logback/base.xml"/> <contextName>logback</contextName> <!-- name的值是變數的名稱,value的值時變數定義的值。通過定義的值會被插入到logger上下文中。定義後,可以使“${}”來使用變數。 --> <property name="log.path" value="/data/log"/> <!--0. 日誌格式和顏色渲染 --> <!-- 彩色日誌依賴的渲染類 --> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/> <!-- 彩色日誌格式 --> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <!--1. 輸出到控制檯--> <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <!--配置logStash 服務地址--> <destination>127.0.0.1:8888</destination> <!-- 日誌輸出編碼 --> <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"> <providers> <timestamp> <timeZone>UTC</timeZone> </timestamp> <pattern> <pattern> { "time": "%d{yyyy-MM-dd HH:mm:ss}", "logLevel": "%level", "class": "%logger{40}", "rest": "%message" } </pattern> </pattern> </providers> </encoder> </appender> <!--2. 輸出到文件--> <!-- 2.1 level為 DEBUG 日誌,時間滾動輸出 --> <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在記錄的日誌文件的路徑及文件名 --> <file>${log.path}/demo_debug.log</file> <!--日誌文件輸出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> <!-- 設定字符集 --> </encoder> <!-- 日誌記錄器的滾動策略,按日期,按大小記錄 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日誌歸檔 --> <fileNamePattern>${log.path}/web-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日誌文件保留天數--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日誌文件只記錄debug級別的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>debug</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 2.2 level為 INFO 日誌,時間滾動輸出 --> <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在記錄的日誌文件的路徑及文件名 --> <file>${log.path}/demo_info.log</file> <!--日誌文件輸出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> <!-- 日誌記錄器的滾動策略,按日期,按大小記錄 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 每天日誌歸檔路徑以及格式 --> <fileNamePattern>${log.path}/web-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日誌文件保留天數--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日誌文件只記錄info級別的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>info</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 2.3 level為 WARN 日誌,時間滾動輸出 --> <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在記錄的日誌文件的路徑及文件名 --> <file>${log.path}/demo_warn.log</file> <!--日誌文件輸出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> <!-- 此處設定字符集 --> </encoder> <!-- 日誌記錄器的滾動策略,按日期,按大小記錄 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.path}/web-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日誌文件保留天數--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日誌文件只記錄warn級別的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>warn</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 2.4 level為 ERROR 日誌,時間滾動輸出 --> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在記錄的日誌文件的路徑及文件名 --> <file>${log.path}/demo_error.log</file> <!--日誌文件輸出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> <!-- 此處設定字符集 --> </encoder> <!-- 日誌記錄器的滾動策略,按日期,按大小記錄 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.path}/web-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日誌文件保留天數--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日誌文件只記錄ERROR級別的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- <logger>用來設定某一個包或者具體的某一個類的日誌列印級別、 以及指定<appender>。<logger>僅有一個name屬性, 一個可選的level和一個可選的addtivity屬性。 name:用來指定受此logger約束的某一個包或者具體的某一個類。 level:用來設定列印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 還有一個特俗值INHERITED或者同義詞NULL,代表強制執行上級的級別。 如果未設定此屬性,那麼當前logger將會繼承上級的級別。 addtivity:是否向上級logger傳遞列印資訊。預設是true。 <logger name="org.springframework.web" level="info"/> <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/> --> <!-- 使用mybatis的時候,sql語句是debug下才會列印,而這裡我們只配置了info,所以想要檢視sql語句的話,有以下兩種操作: 第一種把<root level="info">改成<root level="DEBUG">這樣就會列印sql,不過這樣日誌那邊會出現很多其他訊息 第二種就是單獨給dao下目錄配置debug模式,程式碼如下,這樣配置sql語句會列印,其他還是正常info級別: 【logging.level.org.mybatis=debug logging.level.dao=debug】 --> <!-- root節點是必選節點,用來指定最基礎的日誌輸出級別,只有一個level屬性 level:用來設定列印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 不能設定為INHERITED或者同義詞NULL。預設是DEBUG 可以包含零個或多個元素,標識這個appender將會新增到這個logger。 --> <!-- 4. 最終的策略 --> <!-- 4.1 開發環境:列印控制檯--> <!--<springProfile name="test">--> <!--<logger name="com.sdcm.pmp" level="debug"/>--> <!--</springProfile>--> <root level="info"> <appender-ref ref="LOGSTASH"/> <appender-ref ref="DEBUG_FILE"/> <appender-ref ref="INFO_FILE"/> <appender-ref ref="WARN_FILE"/> <appender-ref ref="ERROR_FILE"/> </root> <!-- 4.2 生產環境:輸出到文件 <springProfile name="pro"> <root level="info"> <appender-ref ref="CONSOLE" /> <appender-ref ref="DEBUG_FILE" /> <appender-ref ref="INFO_FILE" /> <appender-ref ref="ERROR_FILE" /> <appender-ref ref="WARN_FILE" /> </root> </springProfile> --> </configuration>
配置 logstash 的 logstash-sample.conf檔案,這裡主要是配置資料來源、處理、輸出,通過 logstash -f /usr/local/logstash-7.1.0/config/logstash-sample.conf 以當前配置檔案啟動。
# Sample Logstash configuration for creating a simple # Beats -> Logstash -> Elasticsearch pipeline. input{ #檔案輸入 #file { # path => "/data/log/newjetta/demo_info.log" # codec => "json" #} #網路傳輸,監聽IP與埠 tcp{ host => "127.0.0.1" port => 8888 type => "tcplog" } } filter { #輸入資料json格式化 json { source => "message" remove_field => ["message"] } #multiline { # pattern => "^\20" # negate => false # what => "previous" #} } output{ #顯示傳輸的資料,除錯用 stdout { codec => rubydebug } #輸出到es elasticsearch { hosts => ["http://127.0.0.1:9200"] index => "log-%{+YYYY.MM.dd}" } }
可以看到日誌資訊