-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This makes it easier to report verbose program logging to troubleshooting issues with the preflight itself.
- Loading branch information
Showing
5 changed files
with
157 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package log | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"log" | ||
"os" | ||
) | ||
|
||
// We want all logging to go to the standard error stream, since we output data | ||
// on the standard output stream. | ||
var infoLogger = log.New(os.Stderr, "INFO: ", log.LUTC|log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile) | ||
var errorLogger = log.New(os.Stderr, "ERROR: ", log.LUTC|log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile) | ||
var isDebug = false | ||
|
||
/* | ||
RecordedError prints an error message to the error log and returns a new error with the given message. | ||
This method can receive also more arguments (e.g an external error) and they will be appended to the given error message. | ||
For example, we have a local method `someMethod()`. This method handles its own error printing and thus we can consume | ||
the error and not append it to the new error message, as follows: | ||
returnVal, err := someMethod() | ||
if err != nil { | ||
return nil, log.RecordedError("failed to run someMethod") | ||
} | ||
On the other hand, if `someMethod()` is a 3rd party method we want to print also the returned error as it wasn't printed | ||
to the error log. So we'll have the following code: | ||
returnVal, err := 3rdParty.someMethod() | ||
if err != nil { | ||
return nil, log.RecordedError("failed to run someMethod. Reason: %s", err) | ||
} | ||
*/ | ||
func RecordedError(errorMessage string, args ...interface{}) error { | ||
message := fmt.Sprintf(errorMessage, args...) | ||
writeLog(errorLogger, "ERROR", message) | ||
return errors.New(message) | ||
} | ||
|
||
// Error prints a message to the error log with the "ERROR" label. | ||
func Error(message string, args ...interface{}) { | ||
writeLog(errorLogger, "ERROR", message, args...) | ||
} | ||
|
||
// Warn prints a message to the info log with the "WARN" label. | ||
func Warn(message string, args ...interface{}) { | ||
writeLog(infoLogger, "WARN", message, args...) | ||
} | ||
|
||
// Info prints a message to the info log with the "INFO" label. | ||
func Info(message string, args ...interface{}) { | ||
writeLog(infoLogger, "INFO", message, args...) | ||
} | ||
|
||
// Debug prints a message to the info log with the "DEBUG" label. | ||
func Debug(infoMessage string, args ...interface{}) { | ||
if isDebug { | ||
writeLog(infoLogger, "DEBUG", infoMessage, args...) | ||
} | ||
} | ||
|
||
// EnableDebugMode enables writing DEBUG level messages to the log output. | ||
func EnableDebugMode() { | ||
isDebug = true | ||
Debug("Debug mode is enabled") | ||
} | ||
|
||
func writeLog(logger *log.Logger, logLevel string, message string, args ...interface{}) { | ||
// -7 format ensures logs alignment, by padding spaces to log level to ensure 7 characters length. | ||
// 5 for longest log level, 1 for ':', and a space separator. | ||
logger.SetPrefix(fmt.Sprintf("%-7s", logLevel+":")) | ||
if len(args) > 0 { | ||
message = fmt.Sprintf(message, args...) | ||
} | ||
logger.Output(3, message) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package log | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestAuthenticator(t *testing.T) { | ||
t.Run("Logger", func(t *testing.T) { | ||
t.Run("Calling RecordedError logs the message and return error object with that message", func(t *testing.T) { | ||
validateLog(t, func(message string, params ...interface{}) { | ||
err := RecordedError(message, params...) | ||
assert.Contains(t, err.Error(), fmt.Sprintf(message, params...)) | ||
}, "ERROR", "log message with param: <%s>", "param value") | ||
}) | ||
|
||
t.Run("Calling Error logs the message", func(t *testing.T) { | ||
validateLog(t, Error, "ERROR", "log message with param: <%s>", "param value") | ||
}) | ||
|
||
t.Run("Calling Warn logs the message", func(t *testing.T) { | ||
validateLog(t, Warn, "WARN", "log message with param: <%s>", "param value") | ||
}) | ||
|
||
t.Run("Calling Info logs the message", func(t *testing.T) { | ||
validateLog(t, Info, "INFO", "log message with param: <%s>", "param value") | ||
}) | ||
|
||
t.Run("Calling Debug does nothing before Calling EnableDebugMode", func(t *testing.T) { | ||
var logBuffer bytes.Buffer | ||
infoLogger = log.New(&logBuffer, "", 0) | ||
|
||
Debug("message") | ||
|
||
assert.Equal(t, logBuffer.Len(), 0) | ||
}) | ||
|
||
t.Run("Calling Debug logs the message after Calling EnableDebugMode", func(t *testing.T) { | ||
EnableDebugMode() | ||
validateLog(t, Debug, "DEBUG", "log message with param: <%s>", "param value") | ||
}) | ||
}) | ||
} | ||
|
||
func validateLog(t *testing.T, logFunc func(string, ...interface{}), logLevel, messageFormat, param string) { | ||
// Replace logger with buffer to test its value | ||
var logBuffer bytes.Buffer | ||
errorLogger = log.New(&logBuffer, "", 0) | ||
infoLogger = log.New(&logBuffer, "", 0) | ||
|
||
logFunc(messageFormat, param) | ||
|
||
logMessages := logBuffer.String() | ||
assert.Contains(t, logMessages, logLevel) | ||
assert.Contains(t, logMessages, fmt.Sprintf(messageFormat, param)) | ||
} |