diff --git a/CHANGELOG.md b/CHANGELOG.md index 186a5d535..af0c10d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Version 1.2 (pending) + +New Features: + + - Logging of critical errors is configurable with `SetLogger` + ## Version 1.1 (2013-11-02) Changes: diff --git a/errors.go b/errors.go index 811fe98fe..9ee98088a 100644 --- a/errors.go +++ b/errors.go @@ -13,6 +13,8 @@ import ( "errors" "fmt" "io" + "log" + "os" ) var ( @@ -24,8 +26,26 @@ var ( errPktSync = errors.New("Commands out of sync. You can't run this command now") errPktSyncMul = errors.New("Commands out of sync. Did you run multiple statements at once?") errPktTooLarge = errors.New("Packet for query is too large. You can change this value on the server by adjusting the 'max_allowed_packet' variable.") + errBusyBuffer = errors.New("Busy buffer") + + errLog Logger = log.New(os.Stderr, "[MySQL] ", log.Ldate|log.Ltime|log.Lshortfile) ) +// Logger is used to log critical error messages. +type Logger interface { + Print(v ...interface{}) +} + +// SetLogger is used to set the logger for critical errors. +// The initial logger is stderr. +func SetLogger(logger Logger) error { + if logger == nil { + return errors.New("logger is nil") + } + errLog = logger + return nil +} + // MySQLError is an error type which represents a single MySQL error type MySQLError struct { Number uint16 diff --git a/errors_test.go b/errors_test.go new file mode 100644 index 000000000..b83d38211 --- /dev/null +++ b/errors_test.go @@ -0,0 +1,30 @@ +// Go MySQL Driver - A MySQL-Driver for Go's database/sql package +// +// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package mysql + +import ( + "bytes" + "log" + "testing" +) + +func TestSetLogger(t *testing.T) { + previous := errLog + defer func() { + errLog = previous + }() + const expected = "prefix: test\n" + buffer := bytes.NewBuffer(make([]byte, 0, 64)) + logger := log.New(buffer, "prefix: ", 0) + SetLogger(logger) + errLog.Print("test") + if actual := buffer.String(); actual != expected { + t.Errorf("expected %q, got %q", expected, actual) + } +} diff --git a/packets.go b/packets.go index b570a3e1c..5ef8036fe 100644 --- a/packets.go +++ b/packets.go @@ -29,7 +29,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) { // Read packet header data, err := mc.buf.readNext(4) if err != nil { - errLog.Print(err.Error()) + errLog.Print(err) mc.Close() return nil, driver.ErrBadConn } @@ -38,7 +38,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) { pktLen := int(uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16) if pktLen < 1 { - errLog.Print(errMalformPkt.Error()) + errLog.Print(errMalformPkt) mc.Close() return nil, driver.ErrBadConn } @@ -56,7 +56,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) { // Read packet body [pktLen bytes] data, err = mc.buf.readNext(pktLen) if err != nil { - errLog.Print(err.Error()) + errLog.Print(err) mc.Close() return nil, driver.ErrBadConn } @@ -113,9 +113,9 @@ func (mc *mysqlConn) writePacket(data []byte) error { // Handle error if err == nil { // n != len(data) - errLog.Print(errMalformPkt.Error()) + errLog.Print(errMalformPkt) } else { - errLog.Print(err.Error()) + errLog.Print(err) } return driver.ErrBadConn } @@ -228,7 +228,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { data := mc.buf.takeSmallBuffer(pktLen + 4) if data == nil { // can not take the buffer. Something must be wrong with the connection - errLog.Print("Busy buffer") + errLog.Print(errBusyBuffer) return driver.ErrBadConn } @@ -299,7 +299,7 @@ func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error { data := mc.buf.takeSmallBuffer(pktLen + 4) if data == nil { // can not take the buffer. Something must be wrong with the connection - errLog.Print("Busy buffer") + errLog.Print(errBusyBuffer) return driver.ErrBadConn } @@ -320,7 +320,7 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error { data := mc.buf.takeSmallBuffer(4 + 1) if data == nil { // can not take the buffer. Something must be wrong with the connection - errLog.Print("Busy buffer") + errLog.Print(errBusyBuffer) return driver.ErrBadConn } @@ -339,7 +339,7 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error { data := mc.buf.takeBuffer(pktLen + 4) if data == nil { // can not take the buffer. Something must be wrong with the connection - errLog.Print("Busy buffer") + errLog.Print(errBusyBuffer) return driver.ErrBadConn } @@ -360,7 +360,7 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error { data := mc.buf.takeSmallBuffer(4 + 1 + 4) if data == nil { // can not take the buffer. Something must be wrong with the connection - errLog.Print("Busy buffer") + errLog.Print(errBusyBuffer) return driver.ErrBadConn } @@ -751,7 +751,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error { } if data == nil { // can not take the buffer. Something must be wrong with the connection - errLog.Print("Busy buffer") + errLog.Print(errBusyBuffer) return driver.ErrBadConn } diff --git a/utils.go b/utils.go index efe4d3f8e..c1afb54ac 100644 --- a/utils.go +++ b/utils.go @@ -16,15 +16,12 @@ import ( "errors" "fmt" "io" - "log" "net/url" - "os" "strings" "time" ) var ( - errLog *log.Logger // Error Logger tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs errInvalidDSNUnescaped = errors.New("Invalid DSN: Did you forget to escape a param value?") @@ -32,7 +29,6 @@ var ( ) func init() { - errLog = log.New(os.Stderr, "[MySQL] ", log.Ldate|log.Ltime|log.Lshortfile) tlsConfigRegister = make(map[string]*tls.Config) } @@ -678,5 +674,5 @@ func appendLengthEncodedInteger(b []byte, n uint64) []byte { return append(b, 0xfd, byte(n), byte(n>>8), byte(n>>16)) } return append(b, 0xfe, byte(n), byte(n>>8), byte(n>>16), byte(n>>24), - byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56)) + byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56)) }