Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,23 @@ package riak

import (
"fmt"
"log"
"os"
)

// Logger represents a leveled logger, with methods representing
// debug, warn, and error levels
type Logger interface {
Debug(v ...interface{})
Debugf(format string, v ...interface{})
Warn(v ...interface{})
Warnf(format string, v ...interface{})
Error(v ...interface{})
Errorf(format string, v ...interface{})
}

// If true, debug messages will be written to the log
var EnableDebugLogging = false

var errLogger = log.New(os.Stderr, "", log.LstdFlags)
var stdLogger = log.New(os.Stderr, "", log.LstdFlags)
var logger Logger

func init() {
if debugEnvVar := os.Getenv("RIAK_GO_CLIENT_DEBUG"); debugEnvVar != "" {
Expand All @@ -36,50 +44,45 @@ func init() {

// SetLogger sets the standard logger used for
// WARN and DEBUG (if enabled)
func SetLogger(logger *log.Logger) {
stdLogger = logger
}

// SetErrorLogger sets the logger used for errors
func SetErrorLogger(logger *log.Logger) {
errLogger = logger
func SetLogger(l Logger) {
logger = l
}

// logDebug writes formatted string debug messages using Printf only if debug logging is enabled
func logDebug(source, format string, v ...interface{}) {
if EnableDebugLogging {
stdLogger.Printf(fmt.Sprintf("[DEBUG] %s %s", source, format), v...)
logger.Debugf(fmt.Sprintf("%s %s", source, format), v...)
}
}

// logDebugln writes string debug messages using Println
func logDebugln(source string, v ...interface{}) {
if EnableDebugLogging {
stdLogger.Println("[DEBUG]", source, v)
logger.Debug(source, v)
}
}

// logWarn writes formatted string warning messages using Printf
func logWarn(source, format string, v ...interface{}) {
stdLogger.Printf(fmt.Sprintf("[WARNING] %s %s", source, format), v...)
logger.Warnf(fmt.Sprintf("%s %s", source, format), v...)
}

// logWarnln writes string warning messages using Println
func logWarnln(source string, v ...interface{}) {
stdLogger.Println("[WARNING]", source, v)
logger.Warn(source, v)
}

// logError writes formatted string error messages using Printf
func logError(source, format string, v ...interface{}) {
errLogger.Printf(fmt.Sprintf("[ERROR] %s %s", source, format), v...)
logger.Errorf(fmt.Sprintf("%s %s", source, format), v...)
}

// logErr writes err.Error() using Println
func logErr(source string, err error) {
errLogger.Println("[ERROR]", source, err)
logger.Error(source, err)
}

// logErrorln writes an error message using Println
func logErrorln(source string, v ...interface{}) {
errLogger.Println("[ERROR]", source, v)
logger.Error(source, v)
}
149 changes: 147 additions & 2 deletions logging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,75 @@ package riak
import (
"bytes"
"fmt"
"io"
"log"
"strings"
"testing"
)

type fakeFancyLogger struct {
buf io.Writer
lastCalled string
}

// appendNewline adds a newline, if one does not already exist at the
// end of the format string. This mimics log.Print[f|ln]'s behavior.
func appendNewline(s string, w io.Writer) {
// taken from stdlib's log.Printf
if len(s) == 0 || s[len(s)-1] != '\n' {
w.Write([]byte(string('\n')))
}
}

func (logger *fakeFancyLogger) Println(v ...interface{}) {
fmt.Fprintln(logger.buf, v...)
logger.lastCalled = "Println"
}

func (logger *fakeFancyLogger) Printf(format string, v ...interface{}) {
fmt.Fprintf(logger.buf, format, v...)
appendNewline(format, logger.buf)
logger.lastCalled = "Printf"
}

func (logger *fakeFancyLogger) Debug(v ...interface{}) {
fmt.Fprintln(logger.buf, v...)
logger.lastCalled = "Debug"
}

func (logger *fakeFancyLogger) Debugf(format string, v ...interface{}) {
fmt.Fprintf(logger.buf, format, v...)
appendNewline(format, logger.buf)
logger.lastCalled = "Debugf"
}

func (logger *fakeFancyLogger) Warn(v ...interface{}) {
fmt.Fprintln(logger.buf, v...)
logger.lastCalled = "Warn"
}

func (logger *fakeFancyLogger) Warnf(format string, v ...interface{}) {
fmt.Fprintf(logger.buf, format, v...)
appendNewline(format, logger.buf)
logger.lastCalled = "Warnf"
}

func (logger *fakeFancyLogger) Error(v ...interface{}) {
fmt.Fprintln(logger.buf, v...)
logger.lastCalled = "Error"
}

func (logger *fakeFancyLogger) Errorf(format string, v ...interface{}) {
fmt.Fprintf(logger.buf, format, v...)
appendNewline(format, logger.buf)
logger.lastCalled = "Errorf"
}

func TestLog(t *testing.T) {
EnableDebugLogging = true

tests := []struct {
setLoggerFunc func(*log.Logger)
setLoggerFunc func(Logger)
logFunc func(string, string, ...interface{})
prefix string
}{
Expand Down Expand Up @@ -48,11 +107,54 @@ func TestLog(t *testing.T) {
}
}

func TestFancyLog(t *testing.T) {
EnableDebugLogging = true

tests := []struct {
setLoggerFunc func(Logger)
logFunc func(string, string, ...interface{})
shouldCall string
}{
{
SetErrorLogger,
logError,
"Errorf",
},
{
SetLogger,
logWarn,
"Warnf",
},
{
SetLogger,
logDebug,
"Debugf",
},
}

for _, tt := range tests {
buf := &bytes.Buffer{}
fancyLogger := &fakeFancyLogger{buf: buf}
tt.setLoggerFunc(fancyLogger)
tt.logFunc("[test]", "Hello %s!", "World")

actual := buf.String()
suffix := "[test] Hello World!\n"

if !strings.HasSuffix(actual, suffix) {
t.Errorf("Expected %s to end with %s", actual, suffix)
}
if fancyLogger.lastCalled != tt.shouldCall {
t.Errorf("Expected call to %s, got %s", tt.shouldCall, fancyLogger.lastCalled)
}
}
}

func TestLogln(t *testing.T) {
EnableDebugLogging = true

tests := []struct {
setLoggerFunc func(*log.Logger)
setLoggerFunc func(Logger)
logFunc func(string, ...interface{})
prefix string
}{
Expand Down Expand Up @@ -88,6 +190,49 @@ func TestLogln(t *testing.T) {
}
}

func TestFancyLogln(t *testing.T) {
EnableDebugLogging = true

tests := []struct {
setLoggerFunc func(Logger)
logFunc func(string, ...interface{})
shouldCall string
}{
{
SetErrorLogger,
logErrorln,
"Error",
},
{
SetLogger,
logWarnln,
"Warn",
},
{
SetLogger,
logDebugln,
"Debug",
},
}

for _, tt := range tests {
buf := &bytes.Buffer{}
fancyLogger := &fakeFancyLogger{buf: buf}
tt.setLoggerFunc(fancyLogger)
tt.logFunc("[test]", "Hello", "World!")

actual := buf.String()
suffix := "[test] [Hello World!]\n"

if !strings.HasSuffix(actual, suffix) {
t.Errorf("Expected %s to end with %s", actual, suffix)
}
if fancyLogger.lastCalled != tt.shouldCall {
t.Errorf("Expected call to %s, got %s", tt.shouldCall, fancyLogger.lastCalled)
}
}
}

func TestDebugDisabled(t *testing.T) {
EnableDebugLogging = false

Expand Down