gorm/logger.go

126 lines
3.4 KiB
Go
Raw Normal View History

2013-11-11 05:05:14 +04:00
package gorm
2013-11-11 07:11:49 +04:00
import (
2015-02-23 04:26:26 +03:00
"database/sql/driver"
2013-11-11 07:11:49 +04:00
"fmt"
"log"
"os"
2015-02-20 17:41:03 +03:00
"reflect"
2013-11-11 07:53:56 +04:00
"regexp"
"strconv"
2013-11-11 11:48:31 +04:00
"time"
2016-03-04 04:12:01 +03:00
"unicode"
2013-11-11 07:11:49 +04:00
)
2013-11-11 05:05:14 +04:00
2016-03-07 09:54:20 +03:00
var (
defaultLogger = Logger{log.New(os.Stdout, "\r\n", 0)}
sqlRegexp = regexp.MustCompile(`\?`)
numericPlaceHolderRegexp = regexp.MustCompile(`\$\d+`)
2016-03-07 09:54:20 +03:00
)
2017-01-15 11:58:55 +03:00
func isPrintable(s string) bool {
for _, r := range s {
if !unicode.IsPrint(r) {
return false
}
}
return true
2013-11-11 13:16:15 +04:00
}
2017-01-15 11:58:55 +03:00
var LogFormatter = func(values ...interface{}) (messages []interface{}) {
2015-02-17 17:55:14 +03:00
if len(values) > 1 {
2017-01-15 11:58:55 +03:00
var (
sql string
formattedValues []string
level = values[0]
currentTime = "\n\033[33m[" + NowFunc().Format("2006-01-02 15:04:05") + "]\033[0m"
source = fmt.Sprintf("\033[35m(%v)\033[0m", values[1])
)
messages = []interface{}{source, currentTime}
2013-11-11 13:16:15 +04:00
if level == "sql" {
2014-01-04 13:36:58 +04:00
// duration
2015-02-17 17:55:14 +03:00
messages = append(messages, fmt.Sprintf(" \033[36;1m[%.2fms]\033[0m ", float64(values[2].(time.Duration).Nanoseconds()/1e4)/100.0))
2014-01-04 13:36:58 +04:00
// sql
2016-03-04 03:59:33 +03:00
2015-02-20 17:41:03 +03:00
for _, value := range values[4].([]interface{}) {
indirectValue := reflect.Indirect(reflect.ValueOf(value))
if indirectValue.IsValid() {
value = indirectValue.Interface()
if t, ok := value.(time.Time); ok {
2017-01-15 11:58:55 +03:00
formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format("2006-01-02 15:04:05")))
2015-02-23 04:26:26 +03:00
} else if b, ok := value.([]byte); ok {
2016-03-04 04:12:01 +03:00
if str := string(b); isPrintable(str) {
formattedValues = append(formattedValues, fmt.Sprintf("'%v'", str))
} else {
formattedValues = append(formattedValues, "'<binary>'")
}
2015-02-23 04:26:26 +03:00
} else if r, ok := value.(driver.Valuer); ok {
if value, err := r.Value(); err == nil && value != nil {
2016-03-04 03:59:33 +03:00
formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
2015-02-23 04:26:26 +03:00
} else {
2016-03-04 03:59:33 +03:00
formattedValues = append(formattedValues, "NULL")
2015-02-23 04:26:26 +03:00
}
2015-02-20 17:41:03 +03:00
} else {
switch value.(type) {
case int8, int, int16, int32, int64, float32, float64, bool:
formattedValues = append(formattedValues, fmt.Sprintf("%v", value))
break
default:
formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
}
2015-02-20 17:41:03 +03:00
}
} else {
2017-01-15 11:58:55 +03:00
formattedValues = append(formattedValues, "NULL")
2015-02-20 17:41:03 +03:00
}
}
2016-03-04 03:59:33 +03:00
// differentiate between $n placeholders or else treat like ?
if numericPlaceHolderRegexp.MatchString(values[3].(string)) {
sql = values[3].(string)
for index, value := range formattedValues {
2017-02-10 11:50:55 +03:00
placeholder := fmt.Sprintf(`\$%d([^\d]|$)`, index+1)
2017-02-10 11:49:28 +03:00
sql = regexp.MustCompile(placeholder).ReplaceAllString(sql, value+"$1")
}
} else {
2017-01-15 11:58:55 +03:00
formattedValuesLength := len(formattedValues)
for index, value := range sqlRegexp.Split(values[3].(string), -1) {
sql += value
if index < formattedValuesLength {
sql += formattedValues[index]
}
2016-03-04 03:59:33 +03:00
}
}
messages = append(messages, sql)
messages = append(messages, fmt.Sprintf(" \n\033[36;31m[%v]\033[0m ", strconv.FormatInt(values[5].(int64), 10)+" rows affected or returned "))
2013-11-11 13:16:15 +04:00
} else {
2014-01-04 13:36:58 +04:00
messages = append(messages, "\033[31;1m")
2015-02-17 17:55:14 +03:00
messages = append(messages, values[2:]...)
2013-11-11 13:16:15 +04:00
messages = append(messages, "\033[0m")
}
}
2017-01-15 11:58:55 +03:00
return
2013-11-11 13:16:15 +04:00
}
2016-03-04 04:12:01 +03:00
2017-01-15 11:58:55 +03:00
type logger interface {
Print(v ...interface{})
}
// LogWriter log writer interface
type LogWriter interface {
Println(v ...interface{})
}
// Logger default logger
type Logger struct {
LogWriter
}
// Print format & print log
func (logger Logger) Print(values ...interface{}) {
logger.Println(LogFormatter(values...)...)
2016-03-04 04:12:01 +03:00
}