专栏首页landv[golang]log日志 Logrus的使用

[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, Zerolog, Zap, 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/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • OpenAuth.Net.landv分支之旅开始制作CRM系统

    landv
  • 金蝶K/3 同步用核算项目配置

    landv
  • 《挑战30天C++入门极限》新手入门:C++中布尔类型

    landv
  • 剑指offer No.10 矩形覆盖

    我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

    week
  • 某理财社区与微博Cache模型对比分析

    社交平台由于内容成本较低,重度依赖用户关系,实时互动、动态浏览。对系统整体性能要求较高。新浪微博由于较大的市场占有率,用户体量大,在这一领域有很多经验,作者之前...

    猿天地
  • 图片上传的两种形式

    很早以前的单应用项目上传图片都是很简单的,上传图片后在controller层设置路径并且保存到服务器的某个路径下就行了,数据库中存储路径地址,最后在tomcat...

    风间影月
  • 四个案例解析:数据分析是如何指导产品设计

    两年之前,那时我刚开始做产品,当需要做数据分析时,我总是一头雾水,完全不知道该如何下手。我想做好,我真的非常想做好,可我却真的不知道该怎么做。经过这两年大大小小...

    沉默的白面书生
  • dedecms文章页调用地址(当前文章URL)如何操作?

      我们在建站时经常会在文末加一个本文地址,那么dedecms文章页如何调用当前文章URL呢?这样做的好处是增加文章的唯一标识,更进一步的做法是在head中加个...

    ytkah
  • 案例分享:机器学习如何可以作用在信息安全方面?

    在了解机器学习如何作用在信息安全方面之前,我们要先了解什么是机器学习?通俗得说,机器学习就是“(计算机)无需显式编程即可学习的能力”。跨海量数据集应用数学技术,...

    人工智能的秘密
  • Spring Security (三) 核心配置解读

    上一篇文章《Spring Security(二)--Guides》,通过Spring Security的配置项了解了Spring Security是如何保护我们...

    程序猿DD

扫码关注云+社区

领取腾讯云代金券