diff --git a/v1/client.go b/v1/client.go index 429f2c8..3dd5273 100644 --- a/v1/client.go +++ b/v1/client.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log" "net/http" "strings" "time" @@ -22,6 +23,22 @@ func New(url string, token string) *MgClient { } } +// WithLogger sets the provided logger instance into the Client. +func (c *MgClient) WithLogger(logger BasicLogger) *MgClient { + c.logger = logger + return c +} + +// writeLog writes to the log. +func (c *MgClient) writeLog(format string, v ...interface{}) { + if c.logger != nil { + c.logger.Printf(format, v...) + return + } + + log.Printf(format, v...) +} + // Bots get all available bots // // Example: diff --git a/v1/client_test.go b/v1/client_test.go index 2700460..d5340a2 100644 --- a/v1/client_test.go +++ b/v1/client_test.go @@ -1,6 +1,7 @@ package v1 import ( + "bytes" "encoding/json" "fmt" "log" @@ -830,3 +831,31 @@ func RandStringBytesMaskImprSrc(n int) string { return string(b) } + +func TestMgClient_DebugNoLogger(t *testing.T) { + c := client() + c.Debug = true + + var buf bytes.Buffer + log.SetOutput(&buf) + defer func() { + log.SetOutput(os.Stderr) + }() + + c.writeLog("Test log string") + + assert.Contains(t, buf.String(), "Test log string") +} + +func TestMgClient_DebugWithLogger(t *testing.T) { + var buf bytes.Buffer + logger := log.New(&buf, "Custom log prefix ", 0) + + c := client() + c.Debug = true + c.WithLogger(logger) + + c.writeLog("Test log string") + + assert.Contains(t, buf.String(), "Custom log prefix Test log string") +} diff --git a/v1/log.go b/v1/log.go new file mode 100644 index 0000000..214fb4a --- /dev/null +++ b/v1/log.go @@ -0,0 +1,25 @@ +package v1 + +// BasicLogger provides basic functionality for logging. +type BasicLogger interface { + Printf(string, ...interface{}) +} + +// DebugLogger can be used to easily wrap any logger with Debugf method into the BasicLogger instance. +type DebugLogger interface { + Debugf(string, ...interface{}) +} + +type debugLoggerAdapter struct { + logger DebugLogger +} + +// DebugLoggerAdapter returns BasicLogger that calls underlying DebugLogger.Debugf. +func DebugLoggerAdapter(logger DebugLogger) BasicLogger { + return &debugLoggerAdapter{logger: logger} +} + +// Printf data in the log using DebugLogger.Debugf. +func (l *debugLoggerAdapter) Printf(format string, v ...interface{}) { + l.logger.Debugf(format, v...) +} diff --git a/v1/log_test.go b/v1/log_test.go new file mode 100644 index 0000000..cf8c412 --- /dev/null +++ b/v1/log_test.go @@ -0,0 +1,24 @@ +package v1 + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +type wrappedLogger struct { + lastMessage string +} + +func (w *wrappedLogger) Debugf(msg string, v ...interface{}) { + w.lastMessage = fmt.Sprintf(msg, v...) +} + +func TestDebugLoggerAdapter_Printf(t *testing.T) { + wrapped := &wrappedLogger{} + logger := DebugLoggerAdapter(wrapped) + logger.Printf("Test message #%d", 1) + + assert.Equal(t, "Test message #1", wrapped.lastMessage) +} diff --git a/v1/request.go b/v1/request.go index 26f0da2..b2ad854 100644 --- a/v1/request.go +++ b/v1/request.go @@ -5,7 +5,6 @@ import ( "fmt" "io" "io/ioutil" - "log" "net/http" ) @@ -72,7 +71,7 @@ func makeRequest(reqType, url string, buf io.Reader, c *MgClient) ([]byte, int, req.Header.Set("X-Bot-Token", c.Token) if c.Debug { - log.Printf("MG BOT API Request: %s %s %s %+v", reqType, url, c.Token, buf) + c.writeLog("MG BOT API Request: %s %s %s %+v", reqType, url, c.Token, buf) } resp, err := c.httpClient.Do(req) @@ -91,7 +90,7 @@ func makeRequest(reqType, url string, buf io.Reader, c *MgClient) ([]byte, int, } if c.Debug { - log.Printf("MG BOT API Response: %s", res) + c.writeLog("MG BOT API Response: %s", res) } return res, resp.StatusCode, err diff --git a/v1/types.go b/v1/types.go index 56cee00..0eab27e 100644 --- a/v1/types.go +++ b/v1/types.go @@ -83,6 +83,7 @@ type MgClient struct { Token string `json:"token"` Debug bool `json:"debug"` httpClient *http.Client + logger BasicLogger `json:"-"` } // Request types