介紹 Golang 日誌處理

介紹 Golang 日誌處理

本文介紹Go語言的Log包及其API,通過示例讓你輕鬆掌握日誌處理。

1. 概述

日誌文件一般用於記錄操作系統或其他軟件運行時發生的事件,或通信軟件不同用戶之間的消息。日誌記錄是一種記錄日誌的行爲,在最簡單的情況下,信息被寫入單個日誌文件。

很多分佈式應用使用Go語言,主要利用其併發特性,如:channel、goroutine等。如果你也複雜構建或支持Go應用,那良好的日誌策略可以幫助你理解用戶行爲、本地錯誤、監控應用性能等。

在GoLang的log包中,實現了簡單的日誌功能。定義了Logger類型及格式化輸出方法,如:Print[f|ln], Fatal[f|ln], Panic[f|ln] ,這些方法使用起來很方便。

Golang Log提供了豐富的選項,下面我們將討論其中的幾個。

2. 使用Go標準日誌庫

Golang內置了標準日誌庫log,缺省的logger無需任何配置就能夠寫錯誤信息及時間戳。在實際開發中通常需要通過簡單的日誌快速獲得反饋,而不是需要豐富的結構化日誌。如果需要更強大的庫,需引入第三方包。

2.1. 在控制檯輸出日誌

下面通過示例進行說明。

// testLog.go

package main

import (
    "errors"
    "fmt"
    "log"
)

func division(x float32, y float32) (float32, error) {
    if y == 0 {
        return 0, errors.New("can't divide by zero")
    }

    return x / y, nil
}

func main() {

    var x float32 = 11
    var y float32

    res, err := division(x, y)

    if err != nil {
        log.Print(err)
    }

    fmt.Println(res)
}

輸出結果如下,第一行是錯誤信息,第二行是res的默認值爲0.

2019/11/28 18:50:19 can't divide by zero
0

上面代碼首先引入三個包:errors,fmt,log。然後定義division函數,其接收兩個參數,函數體中檢查除數是否爲0,如何是返回錯誤信息。

在函數調用時,我們設定y作爲除數,但沒有賦值缺省爲0,因此生成錯誤信息並打印在控制檯上。

標準日誌信息包括消息的發生日期和時間,標準錯誤信息。每個日誌信息在單獨一行顯示,如果錯誤消息沒有以換行符結尾,標準日誌會增加換行符。

Fatal函數寫日誌信息後調用os.Exit(1)。Painic函數在寫日誌信息後調用painc函數。

2.2. 文件存儲日誌

上面示例日誌在控制檯中打印。實際應用中日誌一般需存儲在文件中,下面看示例:

package main

import (
	"errors"
	"fmt"
	"log"
	"os"
)

func division(x float32, y float32) (float32, error) {
	if y == 0 {
		return 0, errors.New("can't divide by zero")
	}

	return x / y, nil
}

func main() {
	var x float32 = 11
	var y float32 

	res, exception := division(x, y)
	file, err := os.OpenFile("info.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	log.SetOutput(file)

	if err != nil {
		log.Fatal(err)
	}

	if exception != nil {
		log.Print(exception)
	}

	defer file.Close()

	fmt.Println(res)
}

這回控制檯僅輸出0,錯誤日誌在當前目錄中文件info.log中。打開文件能看到內容:

2020/04/25 14:38:41 can't divide by zero

Go中的os包意在統一所有操作系統的訪問接口,對於不通用的特性在特定系統包syscall中。如果打開文件代碼幾乎能夠自解釋,創建日誌文件並寫入日誌。最後關閉文件。

3. Github 包logrus格式化日誌

logrus
是爲結構化日誌設計的日誌包,非常適合JSON中進行日誌記錄。JSON格式使機器能夠快速解析您的Golang日誌。

Json格式是標準格式,增加新增的字段,解析器也很容易解析。使用logrus包可以通過WithFields方法定義標準至json日誌。其提供了不同的日誌級別,如: Info(), Warn(), and Error()。

logrus庫自動在json中插入標準字段及你的自定義字段。要使用受限要現在並安裝,命令如下:

go get github.com/Sirupsen/logrus

現在在代碼中導入包進行測試:

package main

import (
    log "github.com/sirupsen/logrus"
)

func main() {
    log.WithFields(log.Fields{
        "Best Song": "Sunflower",
    }).Info("One of the best song")
}

輸出爲:

level=info msg="One of the best song" Best Song=Sunflower

請注意,它與stdlib日誌記錄器完全兼容,因此您可以在任何地方用日誌“github.com/sirupsen/logrus”替換您的日誌導入,重複利用其Logrus的靈活性。你可以定製你想要的一切:

package main

import (
	"os"

	log "github.com/sirupsen/logrus"
)

func init() {
	// Log as JSON instead of the default ASCII formatter.
	log.SetFormatter(&log.JSONFormatter{})

	// Output to stdout instead of the default stderr
	// Can be any io.Writer, see below for File example
	log.SetOutput(os.Stdout)

	// Only log the warning severity or above.
	log.SetLevel(log.WarnLevel)
}

func main() {
	log.WithFields(log.Fields{
		"animal": "walrus",
		"size":   10,
	}).Info("A group of walrus emerges from the ocean")

	log.WithFields(log.Fields{
		"omg":    true,
		"number": 122,
	}).Warn("The group's number increased tremendously!")

	log.WithFields(log.Fields{
		"omg":    true,
		"number": 100,
	}).Fatal("The ice breaks!")

	// A common pattern is to re-use fields between logging statements by re-using
	// the logrus.Entry returned from WithFields()
	contextLogger := log.WithFields(log.Fields{
		"common": "this is a common field",
		"other":  "I also should be logged always",
	})

	contextLogger.Info("I'll be logged with common and other field")
	contextLogger.Info("Me too")
}

輸出:

{"level":"warning","msg":"The group's number increased tremendously!","number":1
22,"omg":true,"time":"2020-04-25T15:24:07+08:00"}
{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,"time":"2020-04
-25T15:24:07+08:00"}

總結

寫日誌首要任務是先找一個合適庫,然後計劃在哪裏調用日誌代碼,如何存儲,存儲多久,如何分析日誌。最佳實踐:

  1. 一般建議應用程序的主流程中調用日誌,不要在goroutine中使用。
  2. 最好把日誌寫在本地,即使後面要集中至中央服務進行處理。
  3. 可以使用預定義的消息使日誌信息更加標準、規範。
  4. 發送日誌至中央平臺進行集中分析處理。
  5. 使用HTTP頭和唯一ID記錄用戶訪問微服務的行爲。

本文通過示例介紹了Go的標準庫log包,以及第三方庫logrus。通過示例說明如何使用日誌,最後順便總結下使用日誌最佳實踐。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章