logger configurations
type LogConf struct {
ServiceName string
Mode string
Encoding string
TimeFormat string
Path string
Level string
Compress bool
KeepDays int
StackCooldownMillis int
MaxBackups int
MaxSize int
Rotation string
}
ServiceName: set the service name, optional. onvolumemode, the name is used to generate the log files. Withinrest/zrpcservices, the name will be set to the name ofrestorzrpcautomatically.Mode: the mode to output the logs, default isconsole.consolemode writes the logs tostdout/stderr.filemode writes the logs to the files specified byPath.volumemode is used in docker, to write logs into mounted volumes.
Encoding: indicates how to encode the logs, default isjson.jsonmode writes the logs in json format.plainmode writes the logs with plain text, with terminal color enabled.
TimeFormat: customize the time format, optional. Default is2006-01-02T15:04:05.000Z07:00.Path: set the log path, default tologs.Level: the logging level to filter logs. Default isinfo.info, all logs are written.error,infologs are suppressed.severe,infoanderrorlogs are suppressed, onlyseverelogs are written.
Compress: whether or not to compress log files, only works withfilemode.KeepDays: how many days that the log files are kept, after the given days, the outdated files will be deleted automatically. It has no effect onconsolemode.StackCooldownMillis: how many milliseconds to rewrite stacktrace again. It’s used to avoid stacktrace flooding.MaxBackups: represents how many backup log files will be kept. 0 means all files will be kept forever. Only take effect whenRotationissize. NOTE: the level of optionKeepDayswill be higher. Even thoughMaxBackupssets 0, log files will still be removed if theKeepDayslimitation is reached.MaxSize: represents how much space the writing log file takes up. 0 means no limit. The unit isMB. Only take effect whenRotationissize.Rotation: represents the type of log rotation rule. Default isdaily.dailyrotate the logs by day.sizerotate the logs by size of logs.
Logging methods
type Logger interface {
// Error logs a message at error level.
Error(...any)
// Errorf logs a message at error level.
Errorf(string, ...any)
// Errorv logs a message at error level.
Errorv(any)
// Errorw logs a message at error level.
Errorw(string, ...LogField)
// Info logs a message at info level.
Info(...any)
// Infof logs a message at info level.
Infof(string, ...any)
// Infov logs a message at info level.
Infov(any)
// Infow logs a message at info level.
Infow(string, ...LogField)
// Slow logs a message at slow level.
Slow(...any)
// Slowf logs a message at slow level.
Slowf(string, ...any)
// Slowv logs a message at slow level.
Slowv(any)
// 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: write any kind of messages into logs, with likefmt.Sprint(…).Errorf,Infof,Slowf: write messages with given format into logs.Errorv,Infov,Slowv: write any kind of messages into logs, with json marshalling to encode them.Errorw,Infow,Sloww: write the string message with givenkey:valuefields.WithContext: inject the given ctx into the log messages, typically used to logtrace-idandspan-id.WithDuration: write elapsed duration into the log messages, with keyduration.
Write the logs to specific stores
logger defined two interfaces to let you customize logger to write logs into any stores.
logger.NewWriter(w io.Writer)logger.SetWriter(writer logx.Writer)
Filtering sensitive fields
If we need to prevent the password fields from logging, we can do it like below:
type (
Message struct {
Name string
Password string
Message string
}
SensitiveLogger struct {
logger.Writer
}
)
func NewSensitiveLogger(writer logger.Writer) *SensitiveLogger {
return &SensitiveLogger{
Writer: writer,
}
}
func (l *SensitiveLogger) Info(msg any, 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 := logger.Reset()
writer := NewSensitiveLogger(originalWriter)
logger.SetWriter(writer)
logger.Infov(Message{
Name: "foo",
Password: "shouldNotAppear",
Message: "bar",
})
// more code
}