使用
logrus 通過 formatter 來定義輸出日志的格式,具體例子如下:
package main
import (
log "github.com/Sirupsen/logrus"
)
func main() {
formatter := &log.TextFormatter{
// 不需要彩色日志
DisableColors: true,
// 定義時間戳格式
TimestampFormat: "2006-01-02 15:04:05",
}
log.SetFormatter(formatter)
log.Printf("hello world")
}
打印的日志內容如下:
time="2019-11-07 17:41:20" level=info msg="hello world"
說明:
- time: 日志的打印時間
- level: 日志的等級
- msg: 日志內容
分析
本身 formatter 是接口類型,只要實現該結構我們就可以自定義日志輸出格式:
// Any additional fields added with `WithField` or `WithFields` are also in
// `entry.Data`. Format is expected to return an array of bytes which are then
// logged to `logger.Out`.
type Formatter interface {
Format(*Entry) ([]byte, error)
}
logrus 提供了兩種默認的日志輸出格式, TextFormatter
和JSONFormatter
.上面的示例使用的就是TextFormatter
.
TextFormatter
type TextFormatter struct {
// Set to true to bypass checking for a TTY before outputting colors.
ForceColors bool
//不使用彩色日志
DisableColors bool
// Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/
EnvironmentOverrideColors bool
// 是否打印時間戳
DisableTimestamp bool
// Enable logging the full timestamp when a TTY is attached instead of just
// 是否按照時間戳格式打印,置為false則只打印從程序啟動到打印日志的時間差(單位:秒)
FullTimestamp bool
// 時間戳格式
TimestampFormat string
// 設置 fields 不排序
DisableSorting bool
// 設置 fields 的排序規則
SortingFunc func([]string)
// Disables the truncation of the level text to 4 characters.
DisableLevelTruncation bool
// QuoteEmptyFields will wrap empty fields in quotes if true
QuoteEmptyFields bool
// 是否打印日志到終端
isTerminal bool
// fieldMap
// As an example:
// formatter := &TextFormatter{
// FieldMap: FieldMap{
// FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
// FieldKeyMsg: "@message"}}
FieldMap FieldMap
// 設置 func 和 file 這兩個 field的輸出格式
CallerPrettyfier func(*runtime.Frame) (function string, file string)
terminalInitOnce sync.Once
}
TextFormatter
實現 Formatter
接口
// Format renders a single log entry
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
data := make(Fields)
for k, v := range entry.Data {
data[k] = v
}
// prefixFieldClashes 刪除默認的 4 個 field,防止沖突(msg, level, time, logrus_error)
prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
keys := make([]string, 0, len(data))
for k := range data {
keys = append(keys, k)
}
// 拼接待打印日志的各個元素
var funcVal, fileVal string
// 拼接元素過程省略 ...
f.terminalInitOnce.Do(func() { f.init(entry) })
// 修改時間戳
timestampFormat := f.TimestampFormat
if timestampFormat == "" {
timestampFormat = defaultTimestampFormat
}
// 以下省略 ...
// 打印換行符
b.WriteByte('\n')
return b.Bytes(), nil
}
JSONFormatter
// JSONFormatter formats logs into parsable json
type JSONFormatter struct {
// TimestampFormat sets the format used for marshaling timestamps.
TimestampFormat string
// DisableTimestamp allows disabling automatic timestamps in output
DisableTimestamp bool
// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
DataKey string
// FieldMap allows users to customize the names of keys for default fields.
// As an example:
// formatter := &JSONFormatter{
// FieldMap: FieldMap{
// FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
// FieldKeyMsg: "@message",
// FieldKeyFunc: "@caller",
// },
// }
FieldMap FieldMap
// CallerPrettyfier can be set by the user to modify the content
// of the function and file keys in the json data when ReportCaller is
// activated. If any of the returned value is the empty string the
// corresponding key will be removed from json fields.
CallerPrettyfier func(*runtime.Frame) (function string, file string)
// PrettyPrint will indent all json logs
PrettyPrint bool
}
JSONFormatter
的實現方式與TextFormatter
類同,這里就不再贅述。總之logrus
的formatter
實現比較簡單,常用參數也在注釋里進行了詳細的說明。
自定義 Formatter
這里我們自定義一個 formatter
,這個 formatter
會在打印的日志前后分別加上前綴和后綴。
package main
import (
"bytes"
"fmt"
log "github.com/Sirupsen/logrus"
)
func main() {
// 初始化自定義 formatter
formatter := &MyFormatter{
Prefix: "prefix",
Suffix: "suffix",
}
log.SetFormatter(formatter)
log.Infoln("hello world")
}
// MyFormatter 自定義 formatter
type MyFormatter struct {
Prefix string
Suffix string
}
// Format implement the Formatter interface
func (mf *MyFormatter) Format(entry *log.Entry) ([]byte, error) {
var b *bytes.Buffer
if entry.Buffer != nil {
b = entry.Buffer
} else {
b = &bytes.Buffer{}
}
// entry.Message 就是需要打印的日志
b.WriteString(fmt.Sprintf("%s - %s - %s", mf.Prefix, entry.Message, mf.Suffix))
return b.Bytes(), nil
}
打印結果如下:
prefix - hello world - suffix