Go微服務 - 第十部分 - 集中化日誌

第十部分: Go微服務 - 集中化日誌

本文介紹咱們的Go微服務基於Logrus、Docker Gelf日誌驅動以及Loggly服務(Logging as a Service)的日誌策略。html

  • Logrus: Go語言中的結構化、可插拔日誌功能。
  • Docker Gelf日誌驅動器: 是一種方便的格式,能夠被不少工具理解,例如Graylog, Logstash, Fluentd等等。
  • Loggly: 這是一個日誌數據管理的SaaS解決方案。使用它能夠將日誌從整個基礎設施的深處帶到一個能夠跟蹤活動和分析趨勢的地方。最重要的是,Loggly是一種託管服務,你不須要任何額外的硬件或軟件就可使用Loggly,而且能夠動態根據操做進行擴展。

簡介

日誌。你根本不知道你會失去多少, 直到你這樣作。爲你的團隊制定關於記錄什麼,何時記錄以及如何記錄,多是產生可維護應用程序的關鍵因素之一。而後,微服務就發生了。linux

雖然對於單體應用來講處理一些日誌文件一般都是可管理的(雖然存在例外...), 但考慮到對於基於微服務的應用程序來講,一樣可能使用數百個甚至數千個服務容器來產生日誌。若是沒有一個蒐集和彙總日誌的解決方案,基本上考慮不了變得更大的時候的問題了。git

謝天謝地,不少聰明人已經想到這一點 - 叫作ELK的著名棧可能就是開源社區中最著名的一個。它是ElasticSearch, LogStash和Kibana構成的Elastic Stack(ELK), 推薦能夠在駐機和雲主機上使用。然而ELK的文章遍地都是,因此本文咱們基於四個部分來探索集中日誌記錄解決方案LaaS:github

  • Logrus: Go語言的日誌框架。
  • Docker Gelf驅動器: Greylog Extended Log格式的日誌驅動器。
  • Gelftail: 本文中將要構建的輕量級日誌聚合器。
  • Loggly: 一個LaaS提供商。 提供相似的管理和做用日誌數據做爲相似服務的能力。

解決方案概覽

clipboard.png

源代碼

https://github.com/walkerqiao...golang

一般咱們的Go微服務直到如今都是使用的fmt或log包打的日誌,通常都輸出到stdout或stderr。咱們但願能更好的控制日誌級別和格式。在Java世界,咱們不少(大部分)都使用log4j、logback、slf4j之類的框架來處理日誌。本文咱們選擇使用Logrus做爲日誌API, 它大致上提供了我剛提到的關於日誌級別、格式化仍是鉤子API一樣類型的功能。docker

使用logrus

使用logrus很好的特性就是它實現了目前咱們用於日誌的fmt, log相同的接口。這就意味着咱們或多或少的可使用logrus做爲無需太多改變的替換。首先確保你的GOPATH設置正確,而後使用下面的命令獲取logrus:json

go get github.com/sirupsen/logrus

更新代碼

咱們使用老派方式來操做。對於common, accountservice, vipservice分別使用IDE或文本編輯器作全局搜索替換。 fmt.和log.替換爲logrus.。那麼如今就會出現不少logrus.Println和logrus.Pringf調用。 即使經過這樣的方式不錯,可是我仍是建議使用logrus更通常化的嚴格支持,例如INFO, WARN, DEBUG之類的。例如:框架

fmt                                 log                             logrus
Println                             Println                         Infoln
printf                              Printf                          Infof
Error                                                               Errorln

有一個例外,fmt.Error用於產生錯誤實例。不要替換fmt.Error。elasticsearch

使用goimports更新imports

鑑於咱們已經使用logrus替換了大量的log.Println和fmt.Println(和其餘日誌函數),咱們就有大量無用的import,這樣會產生編譯錯誤。與其一個文件一個文件的修改,不如咱們使用一個小工具來幫咱們作到這些。 這個工具就是goimports, 能夠經過下面的方式安裝:編輯器

go get golang.org/x/tools/cmd/goimports

安裝完後,這個命令工具在$GOPATH/bin目錄。 接下來能夠進入accountservice, vipservice, 執行下面的命令:

cd $GOPATH/src/github.com/callistaenterprise/goblog/accountservice
$GOPATH/bin/goimports -w **/*.go

執行goimports會自動爲全部的文件添加未import的語句,同時會去掉無用的import語句。

而後能夠對咱們全部的微服務代碼進行這樣的操做,包括common目錄。

而後運行go build確保每一個服務都能正常編譯。

配置logrus

若是咱們不配置logrus, 它將直接以純文本的形式輸出日誌內容。例如:

logrus.Infof("Starting our service...")

// 輸出內容
INFO[0000] Starting our service...

這裏0000是服務啓動的時間。不是咱們所想要的,我想要一個datetime類型的。 所以咱們須要提供一個格式。

func init() {
    logrus.SetFormatter(&logrus.TextFormatter{
        TimestampFormat: "2006-01-02T15:04:05.000",
        FullTimestamp: true,
    })
}

init函數最適合幹這種事情了。設置以後,咱們的日誌輸出就以下所示:

INFO[2017-07-17T13:22:49.164] Starting our service...

要比剛纔好些。 然而,在咱們微服務用例中,咱們但願日誌日誌語句更容易解析,這樣咱們能夠將它們發送到咱們的選擇的LaaS上, 讓日誌索引、排序、聚合等等。所以當咱們不在單例模式(-profile=dev)下運行微服務時,咱們將但願使用JSON格式。

咱們再次修改init函數, 這樣它將使用json格式替代除非有-profile=dev標誌傳入。

func init() {
    profile := flag.String("profile", "test", "Environment profile")
    if *profile == "dev" {
        logrus.SetFormatter(&logrus.TextFormatter{
            TimestampFormat: "2006-01-02T15:04:05.000",
            FullTimestamp: true,
        })
    } else {
        logrus.SetFormatter(&logrus.JSONFormatter{})
    }
}

輸出內容以下:

{"level":"info","msg":"Starting our service...","time":"2017-07-17T16:03:35+02:00"}

就是這樣,你能夠閱讀logrus的文檔得到更全面的例子。

應該清楚的是,標準的logrus日誌不支持來你在其餘平臺使用的細粒度的控制,例如經過配置修改某些給定包以調試模式進行日誌。然而,能夠建立範圍話的日誌實例,使得更細粒度的配置成爲可能,例如:

var LOGGER = logrus.Logger{}   // <-- Create logger instance

func init() {
    // Some other init code...
    
    // Example 1 - using global logrus API
    logrus.Infof("Successfully initialized")
    
    // Example 2 - using logger instance
    LOGGER.Infof("Successfully initialized")
}

這裏只是示例代碼,倉庫中是不存在的。

經過使用LOGGER實例,就能夠配置更細粒度的應用級別的日誌。然而,我已經選擇使用全局日誌,使用logrus.X做爲本文中代碼使用的日誌記錄。

2. Docker Gelf驅動器

Gelf是什麼? 它是Greylog Extended Log Format的首字母縮寫,是logstash的標準格式。
基本上來講,他的日誌數據以JSON格式的數據。在Docker上下文,咱們能夠配置Docker Swarm模式服務使用各類不一樣驅動器來進行日誌, 實際上意味着在某個容器中寫到stdout, stderr的東西會被Docker引擎撿起,交給日誌驅動器來處理。 這些處理包括添加大量容器、Swarm節點、服務等相關的元數據。這些都是針對docker的。大概樣子以下:

{
    "version":"1.1",
    "host":"swarm-manager-0",
    "short_message":"Starting HTTP service at 6868",
    "timestamp":1.487625824614e+09,
    "level":6,
    "_command":"./vipservice-linux-amd64 -profile=test",
    "_container_id":"894edfe2faed131d417eebf77306a0386b43027e0bdf75269e7f9dcca0ac5608",
    "_container_name":"vipservice.1.jgaludcy21iriskcu1fx9nx2p",
    "_created":"2017-02-20T21:23:38.877748337Z",
    "_image_id":"sha256:1df84e91e0931ec14c6fb4e559b5aca5afff7abd63f0dc8445a4e1dc9e31cfe1",
    "_image_name":"someprefix/vipservice:latest",
    "_tag":"894edfe2faed"
}

讓咱們看看如何修改copyall.sh腳本中的docker service create讓它支持Gelf驅動的:

docker service create \
--log-driver=gelf \
--log-opt gelf-address=udp://192.168.99.100:12202 \
--log-opt gelf-compression-type=none \
--name=accountservice --replicas=1 --network=my_network -p=6767:6767 someprefix/accountservice
  • --log-driver=gelf: 告訴Docker使用gelf驅動器。
  • --log-opt gelf-address=udp://192.168.99.100:12202: 告訴Docker朝哪裏發送全部日誌語句。在gelf的狀況中,咱們使用UDP協議,並告訴Docker將日誌語句發送定義的IP:port的服務。這個服務通常就是相似logstash的東西,可是咱們這個例子中,咱們使用了下一節構建的輕量日誌聚合服務。
  • --log-op gelf-compression-type: 告訴Docker在發送日誌語句以前是否須要壓縮。 爲了簡單起見,本文不對日誌語句進行壓縮。

3. 日誌集合和使用Gelftail進行日誌聚合

4. Loggly

總結

本文咱們看了集中化日誌方面的東西 - 爲何它很重要,如何對Go微服務進行格式化日誌,如何使用容器編排裏邊的日誌驅動器在日誌狀態上傳到LaaS提供商以前對日誌進行預處理。

下一節,是時候使用Netflix Hystrix爲咱們微服務添加斷路器和彈性(resilience)。

中英文對照

  • 日誌即服務: Logging as a Service(LaaS).
  • ELK: Electic Search、LogStash、Kibana三個首字母組合。一般三個配合使用,構成ELK協議棧。

參考連接

  • Logrus: Go語言中的結構化、可插拔日誌功能。
  • Elastic Stack: 集中化、轉換和儲存你的數據。是一個開源的、服務端數據處理流水線,它同時從多個源中採集數據,轉換它,而後將它發送到你最喜歡的Stash中(對於咱們來講天然是Elastic Search)。
  • Kibana: Kibana可讓你可視化你的Elastic Search(彈性搜索)數據,並瀏覽Elastic Stack,這樣你就能夠了解爲何在凌晨兩點的時候被分頁來理解雨季對你季度數字的影響。
  • ElasticSearch: Elastic Stack的核心。具備解決不斷壯大用例的分佈式、RESTful搜索和分析引擎能力。做爲Elastic Stack的核心,它集中化存儲數據,所以你能夠發現預期和發現意外狀況。
  • Docker Gelf日誌驅動器: 是一種方便的格式,能夠被不少工具理解,例如Graylog, Logstash, Fluentd等等。
  • Loggly: 這是一個日誌數據管理的SaaS解決方案。使用它能夠將日誌從整個基礎設施的深處帶到一個能夠跟蹤活動和分析趨勢的地方。最重要的是,Loggly是一種託管服務,你不須要任何額外的硬件或軟件就可使用Loggly,而且能夠動態根據操做進行擴展。
  • 英文第10部分
  • 系列文章首頁
  • 下一節
相關文章
相關標籤/搜索