目錄html
一般使用的日誌框架有 Log4J 等。java
如何在 Spring Boot 中添加日誌框架呢?Spring Boot 自帶了一款名爲 Spring Boot Logging 的插件,它已經爲咱們提供了日誌實現。linux
Spring Boot 使用 Commons Logging 做爲內部的日誌框架,而它是一個日誌接口,在實際應用中,咱們須要爲該接口提供相應的日誌實現。Spring 的默認日誌實現是 Java.Util.Logging,它是 JDK 自帶的日誌包,通常場景下不多被用到。Spring Boot 也提供了 Log4J, Logback 這類流行的日誌實現,咱們只要添加簡單的配置,就能開啓對這些日誌的實現。nginx
在 Java 應用程序中,日誌通常分爲 5 個級別: ERROR,WARN,INFO,DEBUG,TRACE。redis
Spring Boot Logging 默認輸出到 INFO
級別,若是但願日誌能夠輸出到 DEBUG
級別,須要在 application.yml
中添加以下配置spring
logging: level: root: DEBUG
在 java 文件中添加docker
import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... private static Logger logger = LoggerFactory.getLogger(HelloController.class); ... logger.debug("log ...");
就能夠在運行代碼時看到 debug 級別的日誌了。shell
若是不想關注 Spring Boot 框架的日誌,則可將日誌級別統一設置成 ERROR
,此時只會輸出 ERROR
級別的日誌。隨後,將 Spring Boot 應用程序指定的包設置成 DEBUG
級別的日誌,就能看到只有指定包的日誌了。json
logging: level: root: ERROR demo: msa: DEBUG
默認狀況下日誌框架會將日誌輸出到控制檯中,須要在 application.yml
文件中加入下面配置,才能將日誌輸出到文件中。瀏覽器
logging: level: root: ERROR demo: msa: DEBUG file: hello.log
首先須要在 pom.xml
中添加以下 Maven 配置,就能在 Spring Boot 中集成 Log4J。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
在第一段中,先排除掉默認的 Logback 日誌功能。在第二段的 dependency 配置中,咱們自行添加 spring-boot-starter-log4j2
依賴,它是 Spring Boot 提供的 Log4J 插件。
配置完成 Maven 依賴配置後,下面須要在 resources
目錄下添加 log4j2.xml
文件,具體內容以下
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appenders> <File name="file" fileName="${sys:user.home}/logs/hello.log"> <PatternLayout pattern="%d{HH:mm:ss:SSS} %p %c (%L) - %m%n"/> </File> </appenders> <loggers> <root level="ERROR"> <appender-ref ref="file"/> </root> <logger name="demo.msa" level="DEBUG" /> </loggers> </configuration>
這個配置文件分紅兩部分, appenders
和 loggers
。經過以上配置,就將 Log4j 集成到 Spring Boot 應用中。雖然日誌已經成功輸出到了文件中,但咱們的微服務是以 Docker 容器的方式來運行的,此時輸出的日誌文件仍然和應用程序在一個 Docker
容器中,咱們得想辦法將日誌文件輸出到 Docker 容器外。也就是將數據和程序分離,以便後續更方便的獲取並分析日誌內容。
最經常使用的方法就是,經過 Docker 數據卷的方式,將文件路徑掛載到 Docker 容器上,這樣日誌文件天然與 Docker 文件分離了。啓動命令以下
[tomcat@ ~]$ docker run -v ~/logs:/root/logs -d -p 18080:8081 demo.msa/mesa-hello:0.0.1-SNAPSHOT
這樣就能夠隨時在宿主機上查看 Docker 容器內部的日誌了。但咱們還須要到文件中去查看,使用 docker logs 的方式獲取日誌內容則不會有此限制,一塊兒來看下。
使用 docker logs
命令能夠隨時查看 Docker 容器內部應用程序運行時產生的日誌,這樣就能夠避免首先進入 Docker 容器,在打開應用程序的過程了。
Docker logs 的執行過程以下: 它會監控容器中操做系統的標準輸出設備 (STDOUT
), 一旦 STDOUT
有產生,就會將這些數據傳輸到另外一個設備中,該設備在 Docker 的世界中被稱爲日誌驅動(Logging Driver)。
以 nginx 爲例,經過下面 Docker 命令啓動 Nginx 容器
docker run -d -p 80:80 --name nginx nginx
打開瀏覽器,在地址欄輸入 http://localhost:80
,就能夠看到 nginx 的首頁。這時就可使用 docker logs
命令,查看 Nginx 容器的日誌。
docker logs -f nginx
其中 -f
是指監控日誌尾部的意思。
由此看出,只要 Docker 容器內部的應用程序在控制檯中有日誌輸出,就能經過 docker logs
命令來查看響應的日誌。那麼 Docker 是如何作到的呢?
首先來執行下 命令
docker info |grep "Logging Driver"
能夠獲得 Docker 當前設置的日誌驅動類型,就是 json-file
。
json-file
表示 JSON 文件,就是說 Docker 容器內部的應用程序輸出的日誌,將自動寫入一個 JSON 文件中,並存放在 /var/lib/docker/containers/<container_id>
目錄中 <container_id>-json.log
,它就是要找的日誌文件。
json-file
只是 Docker 日誌驅動的一個默認選項,除了這個選項,咱們還能夠顯式的指定其餘的類型:
none
不輸出任何日誌syslog
容器輸出的日誌寫入宿主機的 Syslog
中咱們能夠在 docker run
命令中經過 --log-driver
參數來設置具體的 Docker 日誌驅動。而且能夠經過 --log-opt
參數來指定對應日誌驅動的相關選項。就拿默認的 json-file 來講,能夠這樣來啓動 Docker 容器。
docker run -d -p 80:80 --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 --name nginx nginx:1.14
--log-opt
參數有兩個選項:
max-file
表示 JSON 文件最多爲 3 個max-size
表示 JSON 文件最大爲 10M,超過 10M 會自動生成新文件在上面這些日誌驅動類型,最爲經常使用的是 Syslog, 它是 Linux 的日誌系統,不少日誌分析工具均可以從 Syslog 獲取日誌。好比流行的 ELK 日誌中心,它包括下面 3 個部分
在這 3 個組件中, Logstash 用於收集日誌, Syslog 寫入的日誌可轉發到 Logstash 中,隨後會存儲到 Elasticsearch 中。
默認狀況下,Linux 操做系統已經安裝了 syslog 軟件包,叫作 Rsyslog。Rsyslog 是 syslog 標準的一種實現。
能夠經過下面命令能夠查看 Rsyslog 是否已經安裝。
rsyslogd -v
若是要開啓 Rsyslog 服務,必須對 Rsyslog進行配置,打開配置文件
vi /etc/rsyslog.conf
手工開啓(去掉配置前面的註釋),啓動 TCP 連接的 Rsyslog 的 514 端口。
# Provides TCP syslog reception $ModLoad imtcp $InputTCPServerRun 514
配置文件修改完畢後,手工重啓 Rsyslog 服務。
service rsyslog restart or systemctl restart rsyslog
檢查下本地是否對外開啓了 514 端口。
[root@ ~]# netstat -anpt |grep 514 tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN 63516/rsyslogd tcp 0 0 :::514 :::* LISTEN 63516/rsyslogd
下面就啓動 Nginx 容器,並選擇 Syslog 做爲日誌驅動。
docker run -d -p 80:80 --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --name nginx nginx
其中
--log-driver
表示指定 Syslog 爲日誌驅動--log-opt
指定了 Docker 環境能夠經過 TCP 協議鏈接本地的 514 端口可使用下面命令來查看 linux 系統日誌文件,該文件的內容就是 Syslog 所生成的日誌
tail -f /var/log/messages
一般會在一臺宿主機上同時運行多個 Docker 容器,若是每一個容器都經過 Syslog 來聚合日誌,那麼在系統日誌文件經過 Docker 容器的 ID 是很難識別出是哪一個容器的。如何能區分某條日誌是來自哪一個容器呢?
Docker 日誌驅動已經爲咱們提供了支持,只須要在 --log-opt
參數中添加一個 tag 選項,並在這個選項上給出恰當的命名,就能更好的識別出相應的日誌。
docker run -d -p 80:80 --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="nginx" nginx:1.14
將 tag 選項設置成 nginx (容器名稱),就能在日誌中看到帶有 nginx 的標識,這樣咱們能夠更加容易的識別這條日誌來自 Nginx 容器。
若是不指定 tag 選項,則默認的 tag 爲容器 ID 的前 12 個字符。也能夠在 tag 選項中使用 Docker 已經提供的模板標籤,可將這些標籤理解爲 tag 選項中的佔位符。
{{.ID}}
: 容器 ID 的前 12 個字符{{.FullID}}
容器 ID 的完整名稱{{.Name}}
容器名稱{{.ImageID}}
容器鏡像 ID 的前 12 個字符{{.ImageName}}
容器鏡像名稱下面將這些 tag 標籤來個大融合
docker run -d -p 80:80 -v /etc/localtime:/etc/localtime --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" nginx:1.14
docker run -d -p 80:80 -v /etc/localtime:/etc/localtime --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" nginx:1.14
重點是 -v /etc/localtime:/etc/localtime
固然還有其餘方法,可參考這篇連接 http://www.cnblogs.com/zengming/p/10190317.html
Docker 容器中的應用程序 Application 將日誌吸入到標準輸出設備 STDOUT
, Docker Daemon 負責從 STDOUT 中獲取日誌,並將日誌寫入對應的日誌驅動中。
當應用程序的日誌從 Docker 容器內部寫入宿主機的 Syslog 中後,後面咱們要作的就是將 Syslog 中的日誌轉發到 ELK 平臺的 Logstash 中,從而創建咱們須要的日誌中心
Elastic 官方推出了 6 款開源產品
Logstash 是一款開源的數據收集引擎,它既提供了實時管道數據能力,也提供了靈活的插件機制。咱們能夠自由選擇已有的插件,也能自行開發所需的插件。咱們使用 Logstash 更多的時候都在作參數配置,以實現咱們所需的功能。
從系統架構的角度來看,它提供了 3 個內部組件,分別是輸入組件,過濾組件,輸出組件,並且每一個組件都提供了插件機制。能夠將這些組件及其插件想象成一個管道(pipeline),數據從數據源(Data Source)流向 INPUTS,FILTERS,OUTPUT,最終到達 Elasticsearch 中存儲。
上面 3 個組件包含的經常使用插件以下: