From 3fc7c4186bb6cc85dcb935e3e13edbcdf6993b6d Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Wed, 16 Jun 2021 23:43:18 -0700 Subject: [PATCH 1/3] draft: logging implementation design --- internal/logger/logger.go | 71 +++++++++++++++++++++++++++++++++++++++ otellog/otel_log.go | 70 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 internal/logger/logger.go create mode 100644 otellog/otel_log.go diff --git a/internal/logger/logger.go b/internal/logger/logger.go new file mode 100644 index 00000000000..1e0f82e6448 --- /dev/null +++ b/internal/logger/logger.go @@ -0,0 +1,71 @@ +package logger + +import ( + "fmt" + "os" + + "go.opentelemetry.io/otel/otellog" +) + +// This internal package hides the actual logging functions from the user. + +// Logger instance used by xray to log. Set via xray.SetLogger(). +var Logger otellog.Logger = otellog.NewDefaultLogger(os.Stdout, otellog.LogLevelInfo) + +func Debugf(format string, args ...interface{}) { + Logger.Log(otellog.LogLevelDebug, printfArgs{format, args}) +} + +func Debug(args ...interface{}) { + Logger.Log(otellog.LogLevelDebug, printArgs(args)) +} + +func DebugDeferred(fn func() string) { + Logger.Log(otellog.LogLevelDebug, stringerFunc(fn)) +} + +func Infof(format string, args ...interface{}) { + Logger.Log(otellog.LogLevelInfo, printfArgs{format, args}) +} + +func Info(args ...interface{}) { + Logger.Log(otellog.LogLevelInfo, printArgs(args)) +} + +func Warnf(format string, args ...interface{}) { + Logger.Log(otellog.LogLevelWarn, printfArgs{format, args}) +} + +func Warn(args ...interface{}) { + Logger.Log(otellog.LogLevelWarn, printArgs(args)) +} + +func Errorf(format string, args ...interface{}) { + Logger.Log(otellog.LogLevelError, printfArgs{format, args}) +} + +func Error(args ...interface{}) { + Logger.Log(otellog.LogLevelError, printArgs(args)) +} + +type printfArgs struct { + format string + args []interface{} +} + +func (p printfArgs) String() string { + return fmt.Sprintf(p.format, p.args...) +} + +type printArgs []interface{} + +func (p printArgs) String() string { + return fmt.Sprint([]interface{}(p)...) +} + +type stringerFunc func() string + +func (sf stringerFunc) String() string { + return sf() +} + diff --git a/otellog/otel_log.go b/otellog/otel_log.go new file mode 100644 index 00000000000..2a1f8d87042 --- /dev/null +++ b/otellog/otel_log.go @@ -0,0 +1,70 @@ +package otellog + +import ( + "fmt" + "io" + "sync" + "time" +) + +type Logger interface { + Log(level LogLevel, msg fmt.Stringer) +} + +type LogLevel int + +const ( + // LogLevelDebug is usually only enabled when debugging. + LogLevelDebug LogLevel = iota + 1 + + // LogLevelInfo is general operational entries about what's going on inside the application. + LogLevelInfo + + // LogLevelWarn is non-critical entries that deserve eyes. + LogLevelWarn + + // LogLevelError is used for errors that should definitely be noted. + LogLevelError +) + +func (ll LogLevel) String() string { + switch ll { + case LogLevelDebug: + return "DEBUG" + case LogLevelInfo: + return "INFO" + case LogLevelWarn: + return "WARN" + case LogLevelError: + return "ERROR" + default: + return fmt.Sprintf("UNKNOWNLOGLEVEL<%d>", ll) + } +} + +func NewDefaultLogger(w io.Writer, minLogLevel LogLevel) Logger { + return &defaultLogger{w: w, minLevel: minLogLevel} +} + +type defaultLogger struct { + mu sync.Mutex + w io.Writer + minLevel LogLevel +} + +func (l *defaultLogger) Log(ll LogLevel, msg fmt.Stringer) { + if ll < l.minLevel { + return + } + + l.mu.Lock() + defer l.mu.Unlock() + _, _ = fmt.Fprintf(l.w, "%s [%s] %s\n", time.Now().Format(time.RFC3339), ll, msg) +} + +var NullLogger = nullLogger{} + +type nullLogger struct{} + +func (nl nullLogger) Log(ll LogLevel, msg fmt.Stringer) { +} From 42dbf3f104011a33e00cf049a0234a65ebb8bec7 Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Mon, 21 Jun 2021 01:40:05 -0700 Subject: [PATCH 2/3] minor changes --- internal/logger/logger.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 1e0f82e6448..94c1988bb57 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -7,9 +7,6 @@ import ( "go.opentelemetry.io/otel/otellog" ) -// This internal package hides the actual logging functions from the user. - -// Logger instance used by xray to log. Set via xray.SetLogger(). var Logger otellog.Logger = otellog.NewDefaultLogger(os.Stdout, otellog.LogLevelInfo) func Debugf(format string, args ...interface{}) { From 34fdce8ff37c6b64c4f88d0237fbba4275480466 Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Fri, 25 Jun 2021 00:34:07 -0700 Subject: [PATCH 3/3] added otel spec log levels --- internal/logger/logger.go | 16 ++++++++++++++++ otellog/otel_log.go | 16 +++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 94c1988bb57..43877e878e9 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -9,6 +9,14 @@ import ( var Logger otellog.Logger = otellog.NewDefaultLogger(os.Stdout, otellog.LogLevelInfo) +func Tracef(format string, args ...interface{}) { + Logger.Log(otellog.LogLevelTrace, printfArgs{format, args}) +} + +func Trace(args ...interface{}) { + Logger.Log(otellog.LogLevelTrace, printArgs(args)) +} + func Debugf(format string, args ...interface{}) { Logger.Log(otellog.LogLevelDebug, printfArgs{format, args}) } @@ -45,6 +53,14 @@ func Error(args ...interface{}) { Logger.Log(otellog.LogLevelError, printArgs(args)) } +func Fatalf(format string, args ...interface{}) { + Logger.Log(otellog.LogLevelFatal, printfArgs{format, args}) +} + +func Fatal(args ...interface{}) { + Logger.Log(otellog.LogLevelFatal, printArgs(args)) +} + type printfArgs struct { format string args []interface{} diff --git a/otellog/otel_log.go b/otellog/otel_log.go index 2a1f8d87042..710a0d62f41 100644 --- a/otellog/otel_log.go +++ b/otellog/otel_log.go @@ -14,10 +14,13 @@ type Logger interface { type LogLevel int const ( + // LogLevelTrace is used to for fine-grained debugging event and disabled in default configurations. + LogLevelTrace LogLevel = iota + 1 + // LogLevelDebug is usually only enabled when debugging. - LogLevelDebug LogLevel = iota + 1 + LogLevelDebug - // LogLevelInfo is general operational entries about what's going on inside the application. + // LogLevelInfo is used only for informal event indicates that event has happened. LogLevelInfo // LogLevelWarn is non-critical entries that deserve eyes. @@ -25,10 +28,15 @@ const ( // LogLevelError is used for errors that should definitely be noted. LogLevelError + + // LogLevelError is used for fatal errors such as application or system crash. + LogLevelFatal ) func (ll LogLevel) String() string { switch ll { + case LogLevelTrace: + return "TRACE" case LogLevelDebug: return "DEBUG" case LogLevelInfo: @@ -37,6 +45,8 @@ func (ll LogLevel) String() string { return "WARN" case LogLevelError: return "ERROR" + case LogLevelFatal: + return "FATAL" default: return fmt.Sprintf("UNKNOWNLOGLEVEL<%d>", ll) } @@ -59,7 +69,7 @@ func (l *defaultLogger) Log(ll LogLevel, msg fmt.Stringer) { l.mu.Lock() defer l.mu.Unlock() - _, _ = fmt.Fprintf(l.w, "%s [%s] %s\n", time.Now().Format(time.RFC3339), ll, msg) + _, _ = fmt.Fprintf(l.w, "%s\t[%s]\t%s\n", time.Now().Format(time.RFC3339), ll, msg) } var NullLogger = nullLogger{}