下载地址: github.com/sirupsen/logrus
简单使用
- WithFields 添加字段 Logrus鼓励通过日志字段进行谨慎的结构化日志记录,而不是冗长的、不可解析的错误消息
package main
import (
log "github.com/sirupsen/logrus"
"os"
)
type s struct {
Name string
Age int
}
func main() {
a := s{
Name: "小乙",
Age: 10,
}
// 设置日志等级
log.SetLevel(log.DebugLevel)
// 设置日志打到那里去
log.SetOutput(os.Stdout)
// 设置filename
log.SetReportCaller(true)
// 设置format text
//log.SetFormatter(&log.TextFormatter{
//
// TimestampFormat: "2006-01-02 15:04:05",
//})
log.SetFormatter(&log.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
log.Debug("调试信息")
log.Info("提示信息")
log.Warn("警告信息")
log.Error("错误信息")
log.Infof("[格式化打印结构体:%+v]", a)
log.WithFields(log.Fields{
"user_id": 123,
"ip": "1.1.1.1",
"request_id": "asdwdadmaskmdlasmldkmwqlkdkmakldm",
}).Info("用户登录成功")
}
全局的logger init函数
- 设置level
- 设置output
- 设置format
- 新建g/log.go
package g
import (
"github.com/sirupsen/logrus"
"os"
)
var Logger = logrus.New()
func InitLogger(level string) {
switch level {
case "info":
Logger.SetLevel(logrus.InfoLevel)
case "debug":
Logger.SetLevel(logrus.DebugLevel)
case "warn":
Logger.SetLevel(logrus.WarnLevel)
}
Logger.SetOutput(os.Stdout)
// 设置filename
Logger.SetReportCaller(true)
// 设置format text
//log.SetFormatter(&log.TextFormatter{
//
// TimestampFormat: "2006-01-02 15:04:05",
//})
Logger.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
}
- 使用
g.InitLogger("info")
g.Logger.Println("测试")
hook使用
hook字段说明
- Levels 代表在哪几个级别下应用这个hook
- Fire 代表 执行哪个函数
type Hook interface {
Levels() []Level
Fire(*Entry) error
}
日志发送钉钉样例
钉钉机器人发送群消息
package main
import (
"bytes"
"encoding/json"
"fmt"
logger "github.com/sirupsen/logrus"
"net/http"
)
type dingHook struct {
apiUrl string //钉钉 群机器人token url
levels []logger.Level
atMobiles []string // at谁
appName string // 模块前缀
jsonBodies chan []byte //异步发送内容队列
closeChan chan bool //主进程关闭消息通道
}
//- Levels 代表在哪几个级别下应用这个hook
func (dh *dingHook) Levels() []logger.Level {
return dh.levels
}
//- Fire 代表 执行具体什么逻辑
func (dh *dingHook) Fire(e *logger.Entry) error {
msg, _ := e.String()
dh.DirectSend(msg)
return nil
}
// 同步发送钉钉的函数
func (dh *dingHook) DirectSend(msg string) {
dm := dingMsg{
MsgType: "text",
}
dm.Text.Content = fmt.Sprintf("[日志告警log]\n[app=%s]\n"+
"[日志详情:%s]", dh.appName, msg)
dm.At.AtMobiles = dh.atMobiles
bs, err := json.Marshal(dm)
if err != nil {
logger.Errorf("[消息json.marshal失败][error:%v][msg:%v]", err, msg)
return
}
res, err := http.Post(dh.apiUrl, "application/json", bytes.NewBuffer(bs))
if err != nil {
logger.Errorf("[消息发送失败][error:%v][msg:%v]", err, msg)
return
}
if res != nil && res.StatusCode != 200 {
logger.Errorf("[钉钉返回错误][StatusCode:%v][msg:%v]", res.StatusCode, msg)
return
}
}
// 定义发钉钉信息的字段
/*
{
"at": {
"atMobiles":[
"180xxxxxx"
],
"atUserIds":[
"user123"
],
"isAtAll": false
},
"text": {
"content":"我就是我, @XXX 是不一样的烟火"
},
"msgtype":"text"
}
*/
type dingMsg struct {
MsgType string `json:"msgtype"`
Text struct {
Content string `json:"content"`
} `json:"text"`
At struct {
AtMobiles []string `json:"atMobiles"`
} `json:"at"`
}
func main() {
dh := &dingHook{
apiUrl: "https://oapi.dingtalk.com/robot/send?access_token=xxxxx",
levels: []logger.Level{logger.WarnLevel, logger.InfoLevel},
atMobiles: []string{"xxxx"},
appName: "live",
jsonBodies: make(chan []byte),
closeChan: make(chan bool),
}
//dh.DirectSend("直接发送一波看看")
level := logger.InfoLevel
logger.SetLevel(level)
// 设置filename
logger.SetReportCaller(true)
logger.SetFormatter(&logger.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
// 添加hook
logger.AddHook(dh)
logger.Info("这是我自己hook的logrus")
}
总结如何使用 logrus的hook功能
- 要去实现先Fire 和Levels方法 —> 实现那个hook接口
- 你的处理逻辑在Fire中
- 比如发送到redis 、es 、钉钉、logstash
- addHook,直接打印日志发送就可以了
原理追踪
- logrus.Info 对应{指定的GOPATH路径}\pkg\mod\github.com\sirupsen\logrus@v1.8.1\entry.go
func (entry *Entry) Info(args ...interface{}) {
entry.Log(InfoLevel, args...)
}
- D:\go_path\pkg\mod\github.com\sirupsen\logrus@v1.8.1\entry.go +241
newEntry.fireHooks()
- D:\go_path\pkg\mod\github.com\sirupsen\logrus@v1.8.1\hooks.go
// Fire all the hooks for the passed level. Used by `entry.log` to fire
// appropriate hooks for a log entry.
func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
for _, hook := range hooks[level] {
if err := hook.Fire(entry); err != nil {
return err
}
}
return nil
}