-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NSM logging system is complicated and buggy #1272
Comments
/cc @edwarnicke , @glazychev-art |
And remove any hard-coded reference to logrus in the interface. It should be possible to implement a custom logger from the Logger interface that isn't logrus. Now that is possible (it seems) except that you must set the Logrus is in maintenace mode for the reason below. I want to use Zap as logger.
|
Nope. NSM doesn't care about the logger set in the context with
|
I guess the problem above is addressed by the first items in the proposed solutio;
|
IMO a good test (necessary actually) to verify that an abstract log interface really is usable for may implementations is to try at least two, e.g. logrus and Zap. I include my Zap based logger below. We use go-logr/logr with Zap as backend. An NSM Logger with Zapimport (
"github.com/go-logr/zapr"
"go.uber.org/zap"
nsmlog "github.com/networkservicemesh/sdk/pkg/tools/log"
)
// NSMLogger return a logger to use for NSM logging.
func NSMLogger(baseLogger logr.Logger) nsmlog.Logger {
// Get the zap logger
if underlier, ok := baseLogger.GetSink().(zapr.Underlier); ok {
return &nsmLogger{ z: underlier.GetUnderlying() }
} else {
panic("NSMLogger: Can't get the Zap logger")
}
}
type nsmLogger struct {
z *zap.Logger
}
func (l *nsmLogger) Info(v ...interface{}) {
l.z.Sugar().Info(v...)
}
func (l *nsmLogger) Infof(format string, v ...interface{}) {
l.z.Sugar().Infof(format, v...)
}
func (l *nsmLogger) Warn(v ...interface{}) {
l.z.Sugar().Info(v...)
}
func (l *nsmLogger) Warnf(format string, v ...interface{}) {
l.z.Sugar().Infof(format, v...)
}
func (l *nsmLogger) Error(v ...interface{}) {
l.z.Sugar().Error(v...)
}
func (l *nsmLogger) Errorf(format string, v ...interface{}) {
l.z.Sugar().Errorf(format, v...)
}
func (l *nsmLogger) Fatal(v ...interface{}) {
l.z.Sugar().Fatal(v...)
}
func (l *nsmLogger) Fatalf(format string, v ...interface{}) {
l.z.Sugar().Fatalf(format, v...)
}
func (l *nsmLogger) Debug(v ...interface{}) {
l.z.Sugar().Debug(v...)
}
func (l *nsmLogger) Debugf(format string, v ...interface{}) {
l.z.Sugar().Debugf(format, v...)
}
func (l *nsmLogger) Trace(v ...interface{}) {
if l.z.Core().Enabled(-2) {
l.z.Sugar().Debug(v...)
}
}
func (l *nsmLogger) Tracef(format string, v ...interface{}) {
if l.z.Core().Enabled(-2) {
l.z.Sugar().Debugf(format, v...)
}
}
func (l *nsmLogger) Object(k, v interface{}) {
l.z.Sugar().Info(k, v)
}
func (l *nsmLogger) WithField(key, value interface{}) nsmlog.Logger {
return &nsmLogger{
z: l.z.With(zap.Any(fmt.Sprintf("%v", key), value)),
}
} |
Above used as; if config.LogLevel == "TRACE" {
nsmlog.EnableTracing(true)
// Work-around for hard-coded logrus dependency in NSM
logrus.SetLevel(logrus.TraceLevel)
}
logger.Info("NSM trace", "enabled", nsmlog.IsTracingEnabled())
ctx = nsmlog.WithLog(ctx, log.NSMLogger(logger)) // allow NSM logs |
Keep |
Hello @uablrek! Good to know that you started look into that. We're super welcome for refactorings/ideas on improvements. I also really like idea to support zap logging for NSM. Let us know if you want to work with this issue. @edwarnicke Thoughts? |
Some things that should be done but breaks the API; Move IsTracingEnabled() to the Logger interfaceThis is a per-logger thing and moving it removes the need for weird work-arounds with This would also make Use a single logger as parameter to WithLog()Current definition; func WithLog(ctx context.Context, log ...Logger) context.Context This enforces an extra A user can easily use ctx = log.WithLog(ctx, log.Combine(A, B)) The Consider ditching the Join() functionThis seem to be a rarely used "nice-to-have" function. APIs should be kept a simple as possible to make test and maintenance easier. |
The logging system is going to be more complicated. I'd suggest drawing a diagram of classes and a diagram of use cases to check the current state of it. |
Sounds good. When will it be ready? |
Hello, I'm thinking about something like this: Current log message: Future log message: |
The PR #1348 adds a settable NSM-logger. You can configure it with a structured logging format of your preference. Initiate your code with something like; if config.LogLevel == "TRACE" {
nsmlog.EnableTracing(true)
// Work-around for hard-coded logrus dependency in NSM
logrus.SetLevel(logrus.TraceLevel)
}
logger.Info("NSM trace", "enabled", nsmlog.IsTracingEnabled())
nsmlogger := log.NSMLogger(logger)
nsmlog.SetGlobalLogger(nsmlogger)
ctx = nsmlog.WithLog(ctx, nsmlogger) The logger should be set as the global logger and added to the context passed to NSM. We use the zap logger, but you can probably adapt another structured logger easily. Below is our code for an NSMLogger (narrowed) as an example. The NSM programs themselves can't be configured to use a structured logger yet. We needed to set it in our NSE/NSC code for starters. NSM-logger exampleimport "go.uber.org/zap"
// NSM logger;
type nsmLogger struct {
z *zap.Logger
s *zap.SugaredLogger
}
func (l *nsmLogger) Info(v ...interface{}) {
l.s.Info(v...)
}
func (l *nsmLogger) Infof(format string, v ...interface{}) {
l.s.Infof(format, v...)
}
func (l *nsmLogger) Warn(v ...interface{}) {
l.s.Info(v...)
}
func (l *nsmLogger) Warnf(format string, v ...interface{}) {
l.s.Infof(format, v...)
}
func (l *nsmLogger) Error(v ...interface{}) {
l.s.Error(v...)
}
func (l *nsmLogger) Errorf(format string, v ...interface{}) {
l.s.Errorf(format, v...)
}
func (l *nsmLogger) Fatal(v ...interface{}) {
l.s.Fatal(v...)
}
func (l *nsmLogger) Fatalf(format string, v ...interface{}) {
l.s.Fatalf(format, v...)
}
func (l *nsmLogger) Debug(v ...interface{}) {
l.s.Debug(v...)
}
func (l *nsmLogger) Debugf(format string, v ...interface{}) {
l.s.Debugf(format, v...)
}
func (l *nsmLogger) Trace(v ...interface{}) {
if l.z.Core().Enabled(-2) {
l.s.Debug(v...)
}
}
func (l *nsmLogger) Tracef(format string, v ...interface{}) {
if l.z.Core().Enabled(-2) {
l.s.Debugf(format, v...)
}
}
func (l *nsmLogger) Object(k, v interface{}) {
l.z.Info("Object", zap.Any(fmt.Sprintf("%v", k), v))
}
func (l *nsmLogger) WithField(key, value interface{}) nsmlog.Logger {
z := l.z.With(zap.Any(fmt.Sprintf("%v", key), value))
return &nsmLogger{
z: z,
s: z.Sugar(),
}
} |
Description
During fixing issue reported by @richardstone23 I found a few issues in our current NSM logging system
Solution
Rework and simplify the logging system.
The text was updated successfully, but these errors were encountered: