[golang]log日志 Logrus的使用


[golang]log日志 Logrus的使用

Logrus is a structured logger for Go (golang), completely API compatible with the standard library logger.

Logrus is in maintenance-mode. We will not be introducing new features. It's simply too hard to do in a way that won't break many people's projects, which is the last thing you want from your Logging library (again...).

This does not mean Logrus is dead. Logrus will continue to be maintained for security, (backwards compatible) bug fixes, and performance (where we are limited by the interface).

I believe Logrus' biggest contribution is to have played a part in today's widespread use of structured logging in Golang. There doesn't seem to be a reason to do a major, breaking iteration into Logrus V2, since the fantastic Go community has built those independently. Many fantastic alternatives have sprung up. Logrus would look like those, had it been re-designed with what we know about structured logging in Go today. Check out, for example, ZerologZap, and Apex.

Seeing weird case-sensitive problems? It's in the past been possible to import Logrus as both upper- and lower-case. Due to the Go package environment, this caused issues in the community and we needed a standard. Some environments experienced problems with the upper-case variant, so the lower-case was decided. Everything using logrus will need to use the lower-case: github.com/sirupsen/logrus. Any package that isn't, should be changed.

To fix Glide, see these comments. For an in-depth explanation of the casing issue, see this comment.

翻譯

Logrus是Go(golang)的結構化記錄器,與標准庫記錄器完全API兼容。

Logrus處於維護模式。我們不會介紹新功能。以一種不會破壞許多人項目的方式做起來太簡單了,這是您希望從Logging庫中獲得的最后一件事(再次...)。

這並不意味着Logrus已死。 Logrus將繼續保持安全性,(向后兼容)錯誤修復和性能(受接口限制)。

我相信Logrus的最大貢獻是在Golang中當今結構化日志的廣泛使用中發揮了作用。似乎沒有理由對Logrus V2進行重大的迭代迭代,因為夢幻般的Go社區獨立地構建了它們。許多奇妙的選擇如雨后春筍般涌現。如果使用今天我們在Go中了解的結構化日志進行了重新設計,則Logrus看起來將像這樣。檢出,例如Zerolog,Zap和Apex。

看到大小寫敏感的奇怪問題?過去可以將Logrus導入為大寫和小寫形式。由於Go軟件包環境,這在社區中引起了問題,我們需要一個標准。有些環境遇到了大寫字母變體的問題,因此決定了小寫字母。使用logrus的所有內容都將使用小寫字母:github.com/sirupsen/logrus。沒有的任何軟件包都應該更改。

要修復Glide,請參閱以下注釋。有關套管問題的深入說明,請參閱此注釋

Logrus

其是一個結構化后的日志包,API完全兼容標准包logger。docker(moby)源碼中使用logrus來做日志記錄

項目地址

https://github.com/sirupsen/logrus

go get -u -v github.com/sirupsen/logrus

輸出內容格式化

內建日志格式化有:

  • logrus.TextFormatter

當你登錄TTY時,其輸出內容會是彩色標注;如果不在TTY,則需要將ForceColors設置為true

  • logrus.JSONFormatter

以JSON格式為輸出

六個日志等級

log.Debug("Useful debugging information.")
log.Info("Something noteworthy happened!")
log.Warn("You should probably take a look at this.")
log.Error("Something failed but I'm not quitting.")
// 隨后會觸發os.Exit(1)
log.Fatal("Bye.")
// 隨后會觸發panic()
log.Panic("I'm bailing.")

基本實例

第一個example

這是一個使用了fields的例子,可以添加多對field
package main
import (
  log "github.com/sirupsen/logrus"
)
func main() {
  log.WithFields(log.Fields{
    "animal": "walrus",
  }).Info("A walrus appears")
}

第二個example

package main

import (
    "os"

    "github.com/sirupsen/logrus"
)

func init() {
    // 以JSON格式為輸出,代替默認的ASCII格式
    logrus.SetFormatter(&logrus.JSONFormatter{})
    // 以Stdout為輸出,代替默認的stderr
    logrus.SetOutput(os.Stdout)
    // 設置日志等級
    logrus.SetLevel(logrus.WarnLevel)
}
func main() {
    logrus.WithFields(logrus.Fields{
        "animal": "walrus",
        "size":   10,
    }).Info("A group of walrus emerges from the ocean")

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

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

運行:

go run logrus_study.go

<<'COMMENT'
{"level":"warning","msg":"The group's number increased tremendously!","number":122,"omg":true,"time":"2017-09-18T17:53:13+08:00"}
{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,"time":"2017-09-18T17:53:13+08:00"}
COMMENT

Logger

如果多個地方使用logging,可以創建一個logrus實例Logger

package main

import (
    "os"

    "github.com/sirupsen/logrus"
)

var log = logrus.New()


func main() {
    file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
    if err == nil {
        log.Out = file
    } else {
        log.Info("Failed to log to file, using default stderr")
    }

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

執行后會在GOPATH路徑下穿件logrus.log文件,內容如下:

time="2018-09-18T18:09:32+08:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10

Fields

如果有固定Fields,可以創建一個logrus.Entry

requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") # will log request_id and user_ip
requestLogger.Warn("something not great happened")

從函數WithFields中可以看出其會返回*Entry,Entry中會包含一些變量

// WithFields函數
func WithFields(fields Fields) *Entry {
    return std.WithFields(fields)
}

// Entry結構體
type Entry struct {
    Logger *Logger

    // Contains all the fields set by the user.
    Data Fields

    // Time at which the log entry was created
    Time time.Time

    // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
    // This field will be set on entry firing and the value will be equal to the one in Logger struct field.
    Level Level

    // Message passed to Debug, Info, Warn, Error, Fatal or Panic
    Message string

    // When formatter is called in entry.log(), an Buffer may be set to entry
    Buffer *bytes.Buffer
}

Hooks

可以與外面的控件聯合,例如

  • 使用github.com/multiplay/go-slackslack/bearchat一些企業團隊協作平台/軟件聯合使用

  • 使用https://github.com/zbindenren/logrus_mail可以發送email,例如以下實例

go-slack實現bearchat提示

go get -u -v github.com/multiplay/go-slack

import (
    "github.com/sirupsen/logrus"
    "github.com/multiplay/go-slack/chat"
    "github.com/multiplay/go-slack/lrhook"
)
func Bearychat(){
    //cfg必須符合Config里面的變量,
    cfg := lrhook.Config{
        MinLevel:       logrus.InfoLevel,
        Message:    chat.Message{
            Text:   "發生了錯誤",
        },
        Attachment: chat.Attachment{
            //Attach里面有很多字段,這里能夠設置的只有title
            // Field Text - Will be set to that of log entry Message.
            // Field Fields - Will be created to match the log entry Fields.其實bearchart里面沒有field字段
            // Field Color - Will be set according to the LevelColors or UnknownColor if a match is not found..
            Title: "123.txt",
        },
    }
    h := lrhook.New(cfg, "https://hook.bearychat.com/=bw9Y1/incoming/********")
    logrus.SetFormatter(&logrus.JSONFormatter{})
    logrus.AddHook(h)
    //這里就可以使用Warn了
    logrus.Warn("")
}
問題一
但這里有個問題,那就是,lrhook里面config的變量與bearchat里面的變量不對應,導致bearchat定義的的字段不能有效設置
但使用lrhook的好處是,在發生log時會自動發送
解決方法:
使用webhook,構造與規定對應的json,並且可以處理macdown,只需在log發生時,手動調用即可
func Bearyweb() {
    c := webhook.New("https://**************")
    m := &chat.Message{
        Text: "filename",
        Markdown: true,
        Attachments: []*chat.Attachment{
            {
                Title : "world war 2",
                Text  : "*go back* \n**macdown**\n>fjia",
                Color : "#ffa500",
            },
        },
    }
    m.Send(c)
}
問題二:
bearchat里面都是設置對應字段,所以不能像email那樣把log級別自動加上
解決方法:
在將某個字段手動設置為想要的log級別,比如把Attachments:title字段設置為“Warn”,

Hook-Email-logrus_mail.go

安裝go包:

go get github.com/zbindenren/logrus_mail

實例一

package main

import (
    "time"

    "github.com/logrus_mail"
    "github.com/sirupsen/logrus"
)

func main() {
    logger := logrus.New()
    hook, err := logrus_mail.NewMailAuthHook(
        "logrus_email",
        "smtp.gmail.com",
        587,
        "chenjian158978@gmail.com",
        "271802559@qq.com",
        "chenjian158978@gmail.com",
        "xxxxxxx",
    )
    if err == nil {
        logger.Hooks.Add(hook)
    }
    //生成*Entry
    var filename = "123.txt"
    contextLogger := logger.WithFields(logrus.Fields{
        "file":    filename,
        "content": "GG",
    })
    //設置時間戳和message
    contextLogger.Time = time.Now()
    contextLogger.Message = "這是一個hook發來的郵件"
    //只能發送Error,Fatal,Panic級別的log
    contextLogger.Level = logrus.ErrorLevel

    //使用Fire發送,包含時間戳,message
    hook.Fire(contextLogger)
}

實例二

func Email(){
    logger:= logrus.New()
    //parameter"APPLICATION_NAME", "HOST", PORT, "FROM", "TO"
    //首先開啟smtp服務,最后兩個參數是smtp的用戶名和密碼
    hook, err := logrus_mail.NewMailAuthHook("testapp", "smtp.163.com",25,"username@163.com","username@163.com","smtp_name","smtp_password")
    if err == nil {
        logger.Hooks.Add(hook)
    }
    //生成*Entry
    var filename="123.txt"
    contextLogger :=logger.WithFields(logrus.Fields{
        "file":filename,
        "content":  "GG",
    })
    //設置時間戳和message
    contextLogger.Time=time.Now()
    contextLogger.Message="這是一個hook發來的郵件"
    //只能發送Error,Fatal,Panic級別的log
    contextLogger.Level=logrus.FatalLevel

    //使用Fire發送,包含時間戳,message
    hook.Fire(contextLogger)
}

 

Thread safety

默認的Logger在並發寫入的時候由mutex保護,其在調用hooks和寫入logs時被啟用。如果你認為此鎖是沒有必要的,可以添加logger.SetNoLock()來讓鎖失效。

參考博文

  1. sirupsen/logrus
  2. Logrus的使用
  3. 打開docker的調試日志選項及為調試日志添加文件名和行號
  4. zbindenren/logrus_mail
  5. multiplay/go-slack
  6. slack
  7. bearychat
  8. https://o-my-chenjian.com/2017/09/19/Using-Logrus-With-Golang/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM