警告
本文最后更新于 2023-03-03 22:33,文中内容可能已过时。
设置日志级别
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| package main
import (
"github.com/sirupsen/logrus"
)
func main() {
logrus.SetLevel(logrus.TraceLevel)
logrus.Trace("trace msg") // Trace级别显示所有的日志
logrus.Debug("debug msg") // Debug显示debug、info、warn、error、fatal、panic
logrus.Info("info msg")
logrus.Warn("warn msg")
logrus.Error("error msg")
logrus.Fatal("fatal msg")
logrus.Panic("panic msg")
// xx、xxf、xxln的区别
logrus.Info("hello", "world")
logrus.Infof("hello %s", "world") // 支持格式化输出
logrus.Infoln("hello", "world") // 每个参数用空格分割
}
|
设置显示代码行数和文件名
方便定位代码位置
1
| logrus.SetReportCaller(true)
|
设置日志格式(json & text)
1
2
3
4
5
6
7
| // 设置为json格式
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.Info("hello", "world")
// 设置为text格式
logrus.SetFormatter(&logrus.TextFormatter{})
logrus.Info("hello", "world")
|
第三方日志格式
添加自定义字段
注意使用withField或者withFields后,之前设置的就失效了。
1
2
3
4
5
6
7
8
9
10
11
| // 在日志中添加指定的字段
logrus.WithField("service", "myproj").Info("指定自定义字段的日志") // 临时使用
log := logrus.WithField("service", "myproj") // 方便后续使用
log.Info("指定自定义字段的日志")
// 在日志中添加指定的多个字段
log = logrus.WithFields(logrus.Fields{
"key1": "v1",
"key2": "v2",
}) // 直接.Info("xxx")也可以直接调用
log.Info("指定自定义字段的日志")
|
将日志输出到多个地方
1
2
3
4
5
6
7
8
9
10
11
12
13
| // 多个输出目标
writer1 := &bytes.Buffer{} // 内存
writer2 := os.Stdout // 标准输出
writer3, err := os.OpenFile("log.txt", os.O_WRONLY|os.O_CREATE, 0755) // 文件
if err != nil {
log.Fatalf("创建日志文件失败: %v", err)
}
logrus.SetOutput(io.MultiWriter(writer1, writer2, writer3)) // 设置多个输出目标
logrus.Info("info msg") // 写入日志
io.Copy(os.Stdout, writer1) // 读取buffer中的日志,不过没啥必要
|
只要实现了Writer接口就可以作为输出目标,Writer接口定义如下
type Writer interface {
Write(p []byte) (n int, err error)
}
自己创建log实例
默认exported.go中又个std对象,是logrus默认创建好的,上面的代码都是用的std实例,下面我们使用和他一样的方法创建一个log实例
1
2
3
4
| log := logrus.New() // 这里拿到的log和直接使用logrus是相同的方法New出来的
log.SetFormatter(&myLogFormatter{})
log.SetLevel(logrus.DebugLevel)
log.Info("test")
|
自定义格式
自己实现一个Formatter
接口,他的定义如下。
1
2
3
4
5
6
7
8
| /*
Formatter接口需要实现Format方法, 他接收一个Entry类型的参数,这个参数包括日志的所有字段,比如
entry.Message、entry.Time、entry.Level,通过WithField或WithFields添加的字段包含在entry.Data中。
Format方法的返回值是一个byte类型的切片和一个err.
*/
type Formatter interface {
Format(*Entry) ([]byte, error)
}
|
Entry类型包含如下内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| 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: Trace, 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
// Calling method, with package name
Caller *runtime.Frame
// Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
Message string
// When formatter is called in entry.log(), a Buffer may be set to entry
Buffer *bytes.Buffer
// Contains the context set by the user. Useful for hook processing etc.
Context context.Context
// err may contain a field formatting error
err string
}
|
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| package main
import (
"fmt"
"github.com/sirupsen/logrus"
)
// 声明结构体
type myLogFormatter struct {
}
// 实现Format方法
func (m *myLogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
// fmt.Printf("%+v", entry)
log := fmt.Sprintf("Level %s | Msg %s | Time %s \n", entry.Level, entry.Message, entry.Time)
return []byte(log), nil
}
func main() {
log := logrus.New()
log.SetFormatter(&myLogFormatter{})
log.Info("test")
}
|
Hook
添加hook可以再发送日志前执行某些操作,比如遇到Error、panic、fatal时,发送日志到其他地方,添加hook需要实现下面这个接口
1
2
3
4
| type Hook interface {
Levels() []Level // 哪些级别会触发Hook
Fire(*Entry) error // 日志输出前会先执行Fire
}
|
下面是一个例子,将一些错误日志发送到sentry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| // https://github.com/evalphobia/logrus_sentry
import (
"github.com/sirupsen/logrus"
"github.com/evalphobia/logrus_sentry"
)
func main() {
log := logrus.New()
hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
}) // logrus.AllLevels代表所有级别,具体可看源码
if err == nil {
log.Hooks.Add(hook)
}
}
|
三方Hook: https://github.com/sirupsen/logrus/wiki/Hooks
集成第三方日志轮转
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| package main
import (
"fmt"
"time"
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
)
func main() {
log := logrus.New()
// log.SetFormatter(&myLogFormatter{})
log.SetOutput(&lumberjack.Logger{
Filename: "./foo.log",
MaxSize: 1, // 单个文件最大大小, 单位M
MaxBackups: 3, // 最多保留多少个文件
MaxAge: 28, // 每个最多保留多少天
Compress: false, // 启用压缩
LocalTime: true, // 默认使用UTC时间, 改为使用本地时间
})
for {
log.Info("testtesttesttesttesttesttesttesttesttesttesttesttesttesttest")
log.Info("testtesttesttesttesttesttesttesttesttesttesttesttesttesttest")
time.Sleep(time.Microsecond * 500)
}
}
|