-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathlogger.go
140 lines (112 loc) · 3.03 KB
/
logger.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package dbx
import (
"context"
"fmt"
"regexp"
"strings"
"time"
)
const (
fmtLogQuery = `Query: %s`
fmtLogArgs = `Arguments: %#v`
fmtLogRowsAffected = `Rows affected: %d`
fmtLogLastInsertID = `Last insert ID: %d`
fmtLogError = `Error: %v`
fmtLogTimeTaken = `Time taken: %0.5fs`
fmtLogContext = `Context: %v`
)
var (
reInvisibleChars = regexp.MustCompile(`[\s\r\n\t]+`)
reColumnCompareExclude = regexp.MustCompile(`[^a-zA-Z0-9]`)
)
// QueryStatus represents the status of a query after being executed.
type QueryStatus struct {
Message *string
RowsAffected *int64
LastInsertID *int64
Query string
Args []interface{}
Err error
Start time.Time
End time.Time
Context context.Context
}
// String returns a formatted log message.
func (q *QueryStatus) String() string {
lines := make([]string, 0, 8)
if q.Message != nil {
line := *q.Message
if q.Err != nil {
line += "err: " + q.Err.Error()
}
return line
}
if query := q.Query; query != "" {
query = reInvisibleChars.ReplaceAllString(query, ` `)
query = strings.TrimSpace(query)
lines = append(lines, fmt.Sprintf(fmtLogQuery, query))
}
if len(q.Args) > 0 {
lines = append(lines, fmt.Sprintf(fmtLogArgs, q.Args))
}
if q.RowsAffected != nil {
lines = append(lines, fmt.Sprintf(fmtLogRowsAffected, *q.RowsAffected))
}
if q.LastInsertID != nil {
lines = append(lines, fmt.Sprintf(fmtLogLastInsertID, *q.LastInsertID))
}
if q.Err != nil {
lines = append(lines, fmt.Sprintf(fmtLogError, q.Err))
}
lines = append(lines, fmt.Sprintf(fmtLogTimeTaken, float64(q.End.UnixNano()-q.Start.UnixNano())/float64(1e9)))
if q.Context != nil {
lines = append(lines, fmt.Sprintf(fmtLogContext, q.Context))
}
return strings.Join(lines, "\n")
}
type ILogger interface {
Log(*QueryStatus)
}
// Settings defines methods to get or set configuration values.
type LoggerSettings interface {
// SetLogging enables or disables logging.
SetLogging(bool)
// LoggingEnabled returns true if logging is enabled, false otherwise.
LoggingEnabled() bool
// SetLogger defines which logger to use.
SetLogger(ILogger)
// Returns the currently configured logger.
Logger() ILogger
}
type defaultLogger struct {
loggerSettings
}
func (lg *defaultLogger) Log(m *QueryStatus) {
if m.Err != nil {
s := fmt.Sprintf("\033[31m%s \033[0m \n\t%s\n\n", "ERROR:", strings.Replace(m.String(), "\n", "\n\t", -1))
fmt.Print(s)
} else {
fmt.Printf("\n\t%s\n\n", strings.Replace(m.String(), "\n", "\n\t", -1))
}
}
var _ = ILogger(&defaultLogger{})
var defaultLoggerSettings = &loggerSettings{}
type loggerSettings struct {
loggingEnabled bool
queryLogger ILogger
}
func (c *loggerSettings) Logger() ILogger {
if c.queryLogger == nil {
c.queryLogger = &defaultLogger{}
}
return c.queryLogger
}
func (c *loggerSettings) SetLogger(lg ILogger) {
c.queryLogger = lg
}
func (c *loggerSettings) SetLogging(value bool) {
c.loggingEnabled = value
}
func (c *loggerSettings) LoggingEnabled() bool {
return c.loggingEnabled
}