Open NathanZook opened 5 years ago
+1 for custom levels. Maybe custom levels not argent right now, but at least adding Trace level would be soooo goood.
+1 to add trace level
Yes, it’s very good if there are more levels.
Is anything ever going to be done about this? At a minimum, a trace log level is a must, but support for custom levels would be the ideal solution.
It's not clear whether this can be done in a fully backwards compatible way (as existing cores and encoders may break). For example, the sampler panics when a negative level is passed in (#713). While the sampler can be fixed because it's part of the zap repository, there may be other implementations that would not support new levels.
We are open to PRs that implement custom levels in a backwards compatible way (ideally with an analysis of existing implementations of zap cores/encoders to ensure that it is not breaking). Unfortunately we can't accept any backwards incompatible changes to zap 1.0
Stackdriver has a few more levels on the severe end:
// Alert means a person must take an action immediately.
Alert = Severity(logtypepb.LogSeverity_ALERT)
// Emergency means one or more systems are unusable.
Emergency = Severity(logtypepb.LogSeverity_EMERGENCY)
Stackdriver has a few more levels on the severe end:
// Alert means a person must take an action immediately. Alert = Severity(logtypepb.LogSeverity_ALERT) // Emergency means one or more systems are unusable. Emergency = Severity(logtypepb.LogSeverity_EMERGENCY)
these are just the syslog levels (https://tools.ietf.org/html/rfc3164#section-4.1.1 (Table 2.))
@alxn Good point (I didn't recognize them because of the presentation). However, it doesn't matter whether they're Stackdriver opinions or syslog opinions; they're log destination opinions that zap doesn't share, and they can't currently be added either.
Background: I'm writing an app using zap, sending log to stackdriver (similarly, syslog) via stdio, and just realized while writing the adapter that the models don't match exactly. At least it's a field I can't express in my program with zap, and not the other way around where I would have to lose information.
Zap does have a few other levels (DPanic, Fatal, Panic). They do have different behaviours, but perhaps they can help.
Since this is still open, I'd like to chime in. My motivation to look into the possibility to use custom log levels with zap was to log (http, gRPC, ...) requests. E.g. zap.Log("request", "GET /users/<some-id>", zap.Int("status", httpStatus))
. It would make it very easy to filter by these log lines (or exclude them), extract the error rate and of course you don't have to wonder if a 400
response is InfoLevel
, ErrorLevel
or ... .
It's basically like keeping request and error log in separate files (remember the times...?). I understand there are ways to work around that (e.g. log every request as info and use fields). But again, querying your logs would definitely be easier with this custom level. I also respect your previous comments about backward compatibility, yet it might be something for a v2
?
I extend the trace level like this and it works.
const TraceLevel = zapcore.DebugLevel - 1
func NewDevZapLogger(lvl zapcore.LevelEnabler) *zap.Logger {
encCfg := zap.NewDevelopmentEncoderConfig()
encCfg.EncodeLevel = capitalColorLevelEncoder
zapCore := zapcore.NewCore(zapcore.NewConsoleEncoder(encCfg), zapcore.AddSync(os.Stderr), lvl)
return zap.New(zapCore)
}
func capitalColorLevelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
if level == TraceLevel {
enc.AppendString(color.CyanString("TRACE"))
return
}
zapcore.CapitalColorLevelEncoder(level, enc)
}
func Use() {
zap.ReplaceGlobals(NewDevZapLogger(zap.NewAtomicLevelAt(TraceLevel)))
}
@win5do How do you log a message with Trace level? There is no Trace() method, and we can't specify level when log a message.
@win5do How do you log a message with Trace level? There is no Trace() method, and we can't specify level when log a message.
zap.Logger
provide Log
API that you can pass log level,or make a wrapper func.
zap.L().Log(TraceLevel, "trace msg")
@win5do but it only support string, we need something like Tracef, Tracew, e.g https://github.com/uber-go/zap/pull/933 probably a fork of zap would be better.
@win5do but it only support string, we need something like Tracef, Tracew, e.g #933 probably a fork of zap would be better.
It's easy to make a wrapper func:
func (s *logger) Tracef(format string, args ...interface{}) {
s.zapLogger.Log(TraceLevel, fmt.Sprintf(format, args...))
}
Don't forget to handle caller skip.
My company wants to implement a trace level log. Currently, this is problematic because zap.Logger.check is private.
Digging in, it would seem that a full implementation would extract https://github.com/uber-go/zap/blob/master/logger.go#L273-L282 into a method call. Of course, the natural target of the call is probably the levels themselves, which would be a problem. Making it a method on *zap.Logger would do, I think.
Ideally, we would probably want to change the zapcore.Level constants to variables, and implement a zap.Logger#Log method that takes a zapcore.Level as its second argument.
I know of one major user of Go that implements TRACE1, TRACE2, and TRACE3...