使用

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 提供了两种默认的日志输出格式, TextFormatterJSONFormatter.上面的示例使用的就是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类同,这里就不再赘述。总之logrusformatter实现比较简单,常用参数也在注释里进行了详细的说明。

自定义 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

logrus 剖析之 formatter的更多相关文章

  1. logrus 剖析之滚动日志

    在实际开发过程中,为了节省磁盘,日志需要按照时间或者大小维度进行切割分成多分,归档过期的日志,删除久远的日志.这个就是在日常开发中经常遇见的日志滚动(log rotation) 那么在 logrus ...

  2. logrus 剖析之 hook

    logrus 通过实现 Hook接口扩展 hook 机制,可以根据需求将日志分发到任意的存储介质, 比如 es, mq 或者监控报警系统,及时获取异常日志.可以说极大的提高了日志系统的可扩展性. ho ...

  3. logrus日志框架

    目录 logrus介绍 logrus配置 日志打印 HOOK机制 Gin日志 Fatal处理 线程安全 logrus介绍 golang标准库的日志框架非常简单,仅仅提供了print,panic和fat ...

  4. WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)

    原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序) 基于HTTP-GET的元数据发布方式与基于WS-MEX原理类似,但是ServiceMetad ...

  5. WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化

    原文:WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制 ...

  6. WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构

    原文:WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构 细算起来,已经有好几个月没有真正的写过文章了.近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析>的写作,一直 ...

  7. logrus学习笔记

    logrus源码:https://github.com/sirupsen/logrus 1.logrus.Entry结构 1.1 类型 type Entry struct { Logger *Logg ...

  8. Go中的日志及第三方日志包logrus

    有别的语言使用基础的同学工作中都会接触到日志的使用,Go中自然也有log相关的实现.Go log模块主要提供了3类接口,分别是 "Print .Panic .Fatal ",对每一 ...

  9. Go第三方日志库logrus

    日志是程序中必不可少的一个环节,由于Go语言内置的日志库功能比较简洁,我们在实际开发中通常会选择使用第三方的日志库来进行开发.本文介绍了logrus这个日志库的基本使用. logrus介绍 Logru ...

随机推荐

  1. ArrayList 集合:库存管理

    import java.util.ArrayList; import java.lang.Integer; import java.util.Scanner; import java.util.Ran ...

  2. Django基础之redirect()

    参数可以是: 一个模型: 将调用模型的get_absolute_url()函数 一个视图, 可以带有函数: 可以使用urlresolvers.reverse来反向解析名称 一个绝对的或相对的URL, ...

  3. 解析.msh或.cas文件

    代码如下:

  4. 2015-2016-2《Java程序设计》团队博客4

    一.类结构图 这一周将所有的类都进行了实现,以下是这周实现的类图:         二.项目进展 目前已经将所有代码都编写完成,正在进行整体测试.虽然期间遇到了一些问题,但我们一起进行了讨论,并查找了 ...

  5. [代码质量] Maintainability Index (MI)

    转载自: http://www.projectcodemeter.com/cost_estimation/help/GL_maintainability.htm ProjectCodeMeter Ma ...

  6. SDM439平台出现部分机型SD卡不能识别mmc1: error -110 whilst initialising SD card【学习笔记】

    SDM439平台出现部分机型SD卡不能识别mmc1: error -110 whilst initialising SD card 打印了如下的log: - ::>[ after ms - :: ...

  7. JdkDynamicAopProxy与CglibAopProxy介绍

    继续上一篇的介绍 1.上一篇分析到createAopProxy方法,创建Aop代理对象 protected final synchronized AopProxy createAopProxy() { ...

  8. mqtt 与 MQ 的区别

    mqtt 与 MQ 的区别: mqtt:一种通信协议,类似人类交谈中的汉语.英语.俄语中的一种语言规范MQ:一种通信通道,也叫消息队列,类似人类交谈中的用电话.email.微信的一种通信方式json: ...

  9. 关于Objective-C新增的__kindof关键字

    Objective-C随着Xcode 7的升级带来了许多新特性,当然此次更新最最大的就是引入了Objective-C的轻量级泛型,确切地说是Objective-C类的轻量级泛型.除此之外,还有一个小特 ...

  10. 013-在 Shell 脚本中调用另一个 Shell 脚本的三种方式

    如下: fork: 如果脚本有执行权限的话,path/to/foo.sh.如果没有,sh path/to/foo.sh. exec: exec path/to/foo.sh source: sourc ...