# logx [English](readme.md) | 简体中文 ## logx 配置 ```go type LogConf struct { ServiceName string `json:",optional"` Mode string `json:",default=console,options=[console,file,volume]"` Encoding string `json:",default=json,options=[json,plain]"` TimeFormat string `json:",optional"` Path string `json:",default=logs"` Level string `json:",default=info,options=[info,error,severe]"` Compress bool `json:",optional"` KeepDays int `json:",optional"` StackCooldownMillis int `json:",default=100"` MaxBackups int `json:",default=0"` MaxSize int `json:",default=0"` Rotation string `json:",default=daily,options=[daily,size]"` } ``` - `ServiceName`:设置服务名称,可选。在 `volume` 模式下,该名称用于生成日志文件。在 `rest/zrpc` 服务中,名称将被自动设置为 `rest`或`zrpc` 的名称。 - `Mode`:输出日志的模式,默认是 `console` - `console` 模式将日志写到 `stdout/stderr` - `file` 模式将日志写到 `Path` 指定目录的文件中 - `volume` 模式在 docker 中使用,将日志写入挂载的卷中 - `Encoding`: 指示如何对日志进行编码,默认是 `json` - `json`模式以 json 格式写日志 - `plain`模式用纯文本写日志,并带有终端颜色显示 - `TimeFormat`:自定义时间格式,可选。默认是 `2006-01-02T15:04:05.000Z07:00` - `Path`:设置日志路径,默认为 `logs` - `Level`: 用于过滤日志的日志级别。默认为 `info` - `info`,所有日志都被写入 - `error`, `info` 的日志被丢弃 - `severe`, `info` 和 `error` 日志被丢弃,只有 `severe` 日志被写入 - `Compress`: 是否压缩日志文件,只在 `file` 模式下工作 - `KeepDays`:日志文件被保留多少天,在给定的天数之后,过期的文件将被自动删除。对 `console` 模式没有影响 - `StackCooldownMillis`:多少毫秒后再次写入堆栈跟踪。用来避免堆栈跟踪日志过多 - `MaxBackups`: 多少个日志文件备份将被保存。0代表所有备份都被保存。当`Rotation`被设置为`size`时才会起作用。注意:`KeepDays`选项的优先级会比`MaxBackups`高,即使`MaxBackups`被设置为0,当达到`KeepDays`上限时备份文件同样会被删除。 - `MaxSize`: 当前被写入的日志文件最大可占用多少空间。0代表没有上限。单位为`MB`。当`Rotation`被设置为`size`时才会起作用。 - `Rotation`: 日志轮转策略类型。默认为`daily`(按天轮转)。 - `daily` 按天轮转。 - `size` 按日志大小轮转。 ## 打印日志方法 ```go type Logger interface { // Error logs a message at error level. Error(...interface{}) // Errorf logs a message at error level. Errorf(string, ...interface{}) // Errorv logs a message at error level. Errorv(interface{}) // Errorw logs a message at error level. Errorw(string, ...LogField) // Info logs a message at info level. Info(...interface{}) // Infof logs a message at info level. Infof(string, ...interface{}) // Infov logs a message at info level. Infov(interface{}) // Infow logs a message at info level. Infow(string, ...LogField) // Slow logs a message at slow level. Slow(...interface{}) // Slowf logs a message at slow level. Slowf(string, ...interface{}) // Slowv logs a message at slow level. Slowv(interface{}) // Sloww logs a message at slow level. Sloww(string, ...LogField) // WithContext returns a new logger with the given context. WithContext(context.Context) Logger // WithDuration returns a new logger with the given duration. WithDuration(time.Duration) Logger } ``` - `Error`, `Info`, `Slow`: 将任何类型的信息写进日志,使用 `fmt.Sprint(...)` 来转换为 `string` - `Errorf`, `Infof`, `Slowf`: 将指定格式的信息写入日志 - `Errorv`, `Infov`, `Slowv`: 将任何类型的信息写入日志,用 `json marshal` 编码 - `Errorw`, `Infow`, `Sloww`: 写日志,并带上给定的 `key:value` 字段 - `WithContext`:将给定的 ctx 注入日志信息,例如用于记录 `trace-id`和`span-id` - `WithDuration`: 将指定的时间写入日志信息中,字段名为 `duration` ## 与第三方日志库集成 - zap - 实现:[https://github.com/zeromicro/zero-contrib/blob/main/logx/zapx/zap.go](https://github.com/zeromicro/zero-contrib/blob/main/logx/zapx/zap.go) - 使用示例:[https://github.com/zeromicro/zero-examples/blob/main/logx/zaplog/main.go](https://github.com/zeromicro/zero-examples/blob/main/logx/zaplog/main.go) - logrus - 实现:[https://github.com/zeromicro/zero-contrib/blob/main/logx/logrusx/logrus.go](https://github.com/zeromicro/zero-contrib/blob/main/logx/logrusx/logrus.go) - 使用示例:[https://github.com/zeromicro/zero-examples/blob/main/logx/logrus/main.go](https://github.com/zeromicro/zero-examples/blob/main/logx/logrus/main.go) 对于其它的日志库,请参考上面示例实现,并欢迎提交 `PR` 到 [https://github.com/zeromicro/zero-contrib](https://github.com/zeromicro/zero-contrib) ## 将日志写到指定的存储 `logx`定义了两个接口,方便自定义 `logx`,将日志写入任何存储。 - `logx.NewWriter(w io.Writer)` - `logx.SetWriter(write logx.Writer)` 例如,如果我们想把日志写进kafka,而不是控制台或文件,我们可以像下面这样做。 ```go type KafkaWriter struct { Pusher *kq.Pusher } func NewKafkaWriter(pusher *kq.Pusher) *KafkaWriter { return &KafkaWriter{ Pusher: pusher, } } func (w *KafkaWriter) Write(p []byte) (n int, err error) { // writing log with newlines, trim them. if err := w.Pusher.Push(strings.TrimSpace(string(p))); err != nil { return 0, err } return len(p), nil } func main() { pusher := kq.NewPusher([]string{"localhost:9092"}, "go-zero") defer pusher.Close() writer := logx.NewWriter(NewKafkaWriter(pusher)) logx.SetWriter(writer) // more code } ``` 完整代码:[https://github.com/zeromicro/zero-examples/blob/main/logx/tokafka/main.go](https://github.com/zeromicro/zero-examples/blob/main/logx/tokafka/main.go) ## 过滤敏感字段 如果我们需要防止 `password` 字段被记录下来,我们可以像下面这样实现。 ```go type ( Message struct { Name string Password string Message string } SensitiveLogger struct { logx.Writer } ) func NewSensitiveLogger(writer logx.Writer) *SensitiveLogger { return &SensitiveLogger{ Writer: writer, } } func (l *SensitiveLogger) Info(msg interface{}, fields ...logx.LogField) { if m, ok := msg.(Message); ok { l.Writer.Info(Message{ Name: m.Name, Password: "******", Message: m.Message, }, fields...) } else { l.Writer.Info(msg, fields...) } } func main() { // setup logx to make sure originalWriter not nil, // the injected writer is only for filtering, like a middleware. originalWriter := logx.Reset() writer := NewSensitiveLogger(originalWriter) logx.SetWriter(writer) logx.Infov(Message{ Name: "foo", Password: "shouldNotAppear", Message: "bar", }) // more code } ``` 完整代码:[https://github.com/zeromicro/zero-examples/blob/main/logx/filterfields/main.go](https://github.com/zeromicro/zero-examples/blob/main/logx/filterfields/main.go) ## 更多示例 [https://github.com/zeromicro/zero-examples/tree/main/logx](https://github.com/zeromicro/zero-examples/tree/main/logx) ## Give a Star! ⭐ 如果你正在使用或者觉得这个项目对你有帮助,请 **star** 支持,感谢!