From cd072c31088dd1a8c048f7297a7ea461745e341b Mon Sep 17 00:00:00 2001 From: Jiangnan Jia Date: Thu, 10 Nov 2022 11:04:32 +0800 Subject: [PATCH] docs: comments and README.md for logging Signed-off-by: Jiangnan Jia --- README.md | 7 +++ pkg/common/logging/README.md | 94 ++++++++++++++++++++++++++++ pkg/common/logging/logger.go | 58 +++++++++++++++++ pkg/common/logging/logger_default.go | 9 ++- 4 files changed, 165 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2d8fe09..bd4fae6 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,10 @@ OpenSergo control plane enables unified management for microservice governance rules with OpenSergo CRD (under Kubernetes). ![arch](https://user-images.githubusercontent.com/9434884/182856237-8ce85f41-1a1a-4a2a-8f58-db042bd4db42.png) + + + +# Feature +## logger mechanism +Provider a common Logger interface which is highly extensible and multi implementable. +For detail please refer to [logging/README.md](./pkg/common/logging/README.md) diff --git a/pkg/common/logging/README.md b/pkg/common/logging/README.md index e69de29..a8d6879 100644 --- a/pkg/common/logging/README.md +++ b/pkg/common/logging/README.md @@ -0,0 +1,94 @@ +# logging component + +here provider a common Logger interface which is highly extensible and multi implementable + +## Quick start +In this logging component, you can have only one global ConsoleLogger, and several FileLogger, By invoking function in [logger.go](./logger.go): +``` go + // AppendLoggerSlice add the Logger into loggerSlice + func AppendLoggerSlice(loggerAppend Logger) { + loggerSlice = append(loggerSlice, loggerAppend) + } + + // SetConsoleLogger set the consoleLogger to print int stdout + func SetConsoleLogger(logger Logger) { + consoleLogger = logger + } +``` + +You can use the default implement of Logger directly, By new Logger instance implemented in [logger_default.go](./logger_default.go), +But first, you should new instances from [logger_default.go](./logger_default.go), like following: +``` go + // new instances + logging.NewDefaultConsoleLogger(logging.DebugLevel) + logging.NewDefaultFileLogger(logging.DebugLevel) + // invoke the function in Logger interface + logging.Error(errors.New("errors.New"), "this is error log in printErrorStack()") + logging.Info("this is info log in printErrorStack()") + logging.Debug("this is debug log in printErrorStack()") +``` + +You can format you log, by using [logger_assembler.go](./logger_assembler.go), +the assembler provides AssembleMsgJsonFormat and AssembleMsgSeparateFormat can be chosen. + +``` go + // the unified entrance for AssembleMsg + func AssembleMsg(logFormat LogFormat, callerDepth int, logLevel, msg string, err error, errWithStack bool, keysAndValues ...interface{}) string + + // AssembleMsgJsonFormat Assemble log-msg as json-format + // + // debug/info/warn: + // {"logLevel":"INFO","timestamp":"2006-01-02 15:04:05.000","caller":"opensergo_client.go:74","msg":"openSergoClient is starting..."} + // + // error: + // {"logLevel":"ERROR","timestamp":"2006-01-02 15:04:05.000","caller":"opensergo_client.go:83","msg":"can not connect.","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial tcp 33.1.33.1:10246: connect: connection refused\""} + // [ ERROR CAUSES WITH STACK ][ rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 33.1.33.1:10246: connect: connection refused" + // github.com/opensergo/opensergo-go/pkg/client.handleReceive.func1 + // + // .../opensergo-go-sdk/pkg/client/opensergo_client.go:82 ][ ERROR CAUSES WITH STACK END ] + func AssembleMsgJsonFormat(callerDepth int, logLevel, msg string, err error, errWithStack bool, keysAndValues ...interface{}) string + + // AssembleMsgSeparateFormat Assemble log-msg as separate-format + // + // pattern: + // level | timestamp | callerFile:line | logContentJson | errorInfo + // + // debug/info/warn: + // INFO | 2006-01-02 15:04:05.000 | main.go:30 | {"msg":"connected.", kvs:{}} + // + // error: + // ERROR | 2006-01-02 15:04:05.000 | main.go:30 | {"msg":"connected.", kvs:{}} | rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 33.1.33.1:10246: i/o timeout" + // [ ERROR CAUSES WITH STACK ][ rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 33.1.33.1:10246: connect: connection refused" + // github.com/opensergo/opensergo-go/pkg/client.handleReceive.func1 + // + // .../opensergo-go-sdk/pkg/client/opensergo_client.go:82 ][ ERROR CAUSES WITH STACK END ] + func AssembleMsgSeparateFormat(callerDepth int, logLevel, msg string, err error, errWithStack bool, keysAndValues ...interface{}) +``` + +## Samples + +### sample_simple_print +If you only want to use the Logger provided by default, you can new a ConsoleLogger, like following: +``` go + // default ConsoleLogger + // logging.NewDefaultConsoleLogger(logging.DebugLevel) + // custom ConsoleLogger + logging.NewConsoleLogger(logging.DebugLevel, logging.JsonFormat, true) + logging.Error(errors.New("errors.New"), "this is error log in printErrorStack()") + logging.Info("this is info log in printErrorStack()") + logging.Debug("this is debug log in printErrorStack()") +``` +For detail, please refer to [sample_simple_print](./samples/sample_simple_print) + +### sample_print_impl_logging +If you want to replace the logger implement where has integrated this logging component, +you can implement the [Logger](./logger.go) by your-self, append you Logger after invoke `ClearLoggerSlice()` in Logger, +or invoke `SetConsoleLogger(logger Logger)` to set the global ConsoleLogger. + +For detail, please refer to [sample_print_impl_logging](./samples/sample_print_impl_logging) + +### sample_print_use_logging +If you want to use this logging component to replace the other has already integrated, +you can re-implement the other Logger by invoking the function in Logger which was instanced. + +For detail, please refer to [sample_print_use_logging](./samples/sample_print_use_logging) diff --git a/pkg/common/logging/logger.go b/pkg/common/logging/logger.go index 14c04aa..d0c95d3 100644 --- a/pkg/common/logging/logger.go +++ b/pkg/common/logging/logger.go @@ -19,6 +19,7 @@ import ( "reflect" ) +// Logger the common interface for logging. type Logger interface { // Print logs message no format as what the msg presents. @@ -71,14 +72,29 @@ var ( consoleLogger Logger ) +// Print logs message no format as what the msg presents. func Print(msg string) { doLog("Print", nil, msg) } +// Debug logs a non-error message with the given key/value pairs as context. +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func Debug(msg string, keysAndValues ...interface{}) { doLog("Debug", nil, msg, keysAndValues...) } +// DebugWithCallerDepth logs a non-error message with the given key/value pairs as context. +// +// logCallerDepth: to calculate the caller:line +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func DebugWithCallerDepth(logger Logger, logFormat LogFormat, logCallerDepth int, msg string, keysAndValues ...interface{}) { if !logger.DebugEnabled() { return @@ -86,10 +102,24 @@ func DebugWithCallerDepth(logger Logger, logFormat LogFormat, logCallerDepth int logger.Print(AssembleMsg(logFormat, logCallerDepth, "DEBUG", msg, nil, false, keysAndValues...)) } +// Info logs a non-error message with the given key/value pairs as context. +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func Info(msg string, keysAndValues ...interface{}) { doLog("Info", nil, msg, keysAndValues...) } +// InfoWithCallerDepth logs a non-error message with the given key/value pairs as context. +// +// logCallerDepth: to calculate the caller:line +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func InfoWithCallerDepth(logger Logger, logFormat LogFormat, logCallerDepth int, msg string, keysAndValues ...interface{}) { if !logger.InfoEnabled() { return @@ -97,10 +127,24 @@ func InfoWithCallerDepth(logger Logger, logFormat LogFormat, logCallerDepth int, logger.Print(AssembleMsg(logFormat, logCallerDepth, "INFO", msg, nil, false, keysAndValues...)) } +// Warn logs a non-error message with the given key/value pairs as context. +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func Warn(msg string, keysAndValues ...interface{}) { doLog("Warn", nil, msg, keysAndValues...) } +// WarnWithCallerDepth logs a non-error message with the given key/value pairs as context. +// +// logCallerDepth: to calculate the caller:line +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func WarnWithCallerDepth(logger Logger, logFormat LogFormat, logCallerDepth int, msg string, keysAndValues ...interface{}) { if !logger.WarnEnabled() { return @@ -109,10 +153,24 @@ func WarnWithCallerDepth(logger Logger, logFormat LogFormat, logCallerDepth int, logger.Print(AssembleMsg(logFormat, logCallerDepth, "WARN", msg, nil, false, keysAndValues...)) } +// Error logs an error message with error and the given key/value pairs as context. +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func Error(err error, msg string, keysAndValues ...interface{}) { doLog("Error", err, msg, keysAndValues...) } +// ErrorWithCallerDepth logs an error message with error and the given key/value pairs as context. +// +// logCallerDepth: to calculate the caller:line +// +// The msg argument should be used to add some constant description to +// the log line. The key/value pairs can then be used to add additional +// variable information. The key/value pairs should alternate string +// keys and arbitrary values. func ErrorWithCallerDepth(logger Logger, logFormat LogFormat, logCallerDepth int, err error, errorWithStack bool, msg string, keysAndValues ...interface{}) { if !logger.ErrorEnabled() { return diff --git a/pkg/common/logging/logger_default.go b/pkg/common/logging/logger_default.go index 718476f..f204714 100644 --- a/pkg/common/logging/logger_default.go +++ b/pkg/common/logging/logger_default.go @@ -93,8 +93,6 @@ func (l *DefaultLogger) ErrorEnabled() bool { } // NewDefaultFileLogger -// filePath $HOME/logs/opensergo/opensergo-universal-transport-service.log -// loggerName FileLoggerName // LoggerLevel DefaultLogLevel func NewDefaultFileLogger(logLevel Level) (Logger, error) { // log dir of 'OpenSergo universal transport service' @@ -108,6 +106,7 @@ func NewDefaultFileLogger(logLevel Level) (Logger, error) { return NewFileLogger(filePath, logLevel, JsonFormat, DefaultErrorWithStack) } +// create a file to write log. func mkdirLogFile(filePath string) { dir := filepath.Dir(filePath) @@ -124,7 +123,7 @@ func mkdirLogFile(filePath string) { } -// NewFileLogger +// NewFileLogger new a Logger which write logs into file. And append the LoggerSlice. // filepath is the full path(absolute path). eg: /root/logs/opensergo/opensergo-universal-transport-service.log func NewFileLogger(filepath string, loggerLevel Level, logFormat LogFormat, errorWithStack bool) (Logger, error) { mkdirLogFile(filepath) @@ -142,12 +141,16 @@ func NewFileLogger(filepath string, loggerLevel Level, logFormat LogFormat, erro return defaultLogger, err } +// NewDefaultConsoleLogger new a default ConsoleLogger to print logs in console. +// And there is only one ConsoleLogger instance in the Global. func NewDefaultConsoleLogger(logLevel Level) Logger { defaultLogger := NewConsoleLogger(logLevel, ConsoleLogFormat, DefaultErrorWithStack) SetConsoleLogger(defaultLogger) return defaultLogger } +// NewConsoleLogger new a ConsoleLogger to print logs in console. +// And there is only one ConsoleLogger instance in the Global. func NewConsoleLogger(logLevel Level, logFormat LogFormat, errorWithStack bool) Logger { defaultLogger := &DefaultLogger{ Logger: log.New(os.Stdout, "", 0),