@@ -27,20 +27,24 @@ import (
27
27
"regexp"
28
28
"strconv"
29
29
"strings"
30
+ "time"
30
31
31
32
"github.com/percona/go-mysql/log"
32
33
)
33
34
34
35
// Regular expressions to match important lines in slow log.
35
- var timeRe = regexp .MustCompile (`Time: (\S+\s{1,2}\S+)` )
36
- var userRe = regexp .MustCompile (`User@Host: ([^\[]+|\[[^[]+\]).*?@ (\S*) \[(.*)\]` )
37
- var idRe = regexp .MustCompile (`(Id|Thread_id): +([0-9]*)` )
38
- var schema = regexp .MustCompile (`Schema: +(.*?) +Last_errno:` )
39
- var headerRe = regexp .MustCompile (`^#\s+[A-Z]` )
40
- var metricsRe = regexp .MustCompile (`(\w+): (\S+|\z)` )
41
- var adminRe = regexp .MustCompile (`command: (.+)` )
42
- var setRe = regexp .MustCompile (`^SET (?:last_insert_id|insert_id|timestamp)` )
43
- var useRe = regexp .MustCompile (`^(?i)use ` )
36
+ var (
37
+ timeRe = regexp .MustCompile (`Time: (\S+\s{1,2}\S+)` )
38
+ timeNewRe = regexp .MustCompile (`Time:\s+(\d{4}-\d{2}-\d{2}\S+)` )
39
+ userRe = regexp .MustCompile (`User@Host: ([^\[]+|\[[^[]+\]).*?@ (\S*) \[(.*)\]` )
40
+ idRe = regexp .MustCompile (`(Id|Thread_id): +([0-9]*)` )
41
+ schema = regexp .MustCompile (`Schema: +(.*?) +Last_errno:` )
42
+ headerRe = regexp .MustCompile (`^#\s+[A-Z]` )
43
+ metricsRe = regexp .MustCompile (`(\w+): (\S+|\z)` )
44
+ adminRe = regexp .MustCompile (`command: (.+)` )
45
+ setRe = regexp .MustCompile (`^SET (?:last_insert_id|insert_id|timestamp)` )
46
+ useRe = regexp .MustCompile (`^(?i)use ` )
47
+ )
44
48
45
49
// A SlowLogParser parses a MySQL slow log. It implements the LogParser interface.
46
50
type SlowLogParser struct {
@@ -55,12 +59,17 @@ type SlowLogParser struct {
55
59
queryLines uint64
56
60
bytesRead uint64
57
61
lineOffset uint64
62
+ endOffset uint64
58
63
stopped bool
59
64
event * log.Event
60
65
}
61
66
62
67
// NewSlowLogParser returns a new SlowLogParser that reads from the open file.
63
68
func NewSlowLogParser (file * os.File , opt log.Options ) * SlowLogParser {
69
+ if opt .DefaultLocation == nil {
70
+ // Old MySQL format assumes time is taken from SYSTEM.
71
+ opt .DefaultLocation = time .Local
72
+ }
64
73
p := & SlowLogParser {
65
74
file : file ,
66
75
opt : opt ,
@@ -136,12 +145,6 @@ SCANNER_LOOP:
136
145
lineLen := uint64 (len (line ))
137
146
p .bytesRead += lineLen
138
147
p .lineOffset = p .bytesRead - lineLen
139
- if p .lineOffset != 0 {
140
- // @todo Need to get clear on why this is needed;
141
- // it does make the value correct; an off-by-one issue
142
- p .lineOffset += 1
143
- }
144
-
145
148
if p .opt .Debug {
146
149
fmt .Println ()
147
150
l .Printf ("+%d line: %s" , p .lineOffset , line )
@@ -181,6 +184,7 @@ SCANNER_LOOP:
181
184
}
182
185
183
186
if ! p .stopped && p .queryLines > 0 {
187
+ p .endOffset = p .bytesRead
184
188
p .sendEvent (false , false )
185
189
}
186
190
@@ -214,10 +218,16 @@ func (p *SlowLogParser) parseHeader(line string) {
214
218
l .Println ("time" )
215
219
}
216
220
m := timeRe .FindStringSubmatch (line )
217
- if len (m ) < 2 {
218
- return
221
+ if len (m ) == 2 {
222
+ p .event .Ts , _ = time .ParseInLocation ("060102 15:04:05" , m [1 ], p .opt .DefaultLocation )
223
+ } else {
224
+ m = timeNewRe .FindStringSubmatch (line )
225
+ if len (m ) == 2 {
226
+ p .event .Ts , _ = time .ParseInLocation (time .RFC3339Nano , m [1 ], p .opt .DefaultLocation )
227
+ } else {
228
+ return
229
+ }
219
230
}
220
- p .event .Ts = m [1 ]
221
231
if userRe .MatchString (line ) {
222
232
if p .opt .Debug {
223
233
l .Println ("user (bad format)" )
@@ -300,6 +310,7 @@ func (p *SlowLogParser) parseQuery(line string) {
300
310
}
301
311
p .inHeader = true
302
312
p .inQuery = false
313
+ p .endOffset = p .lineOffset
303
314
p .sendEvent (true , false )
304
315
p .parseHeader (line )
305
316
return
@@ -352,6 +363,7 @@ func (p *SlowLogParser) parseAdmin(line string) {
352
363
if p .opt .Debug {
353
364
l .Println ("not filtered" )
354
365
}
366
+ p .endOffset = p .bytesRead
355
367
p .sendEvent (false , false )
356
368
} else {
357
369
p .inHeader = false
@@ -364,6 +376,8 @@ func (p *SlowLogParser) sendEvent(inHeader bool, inQuery bool) {
364
376
l .Println ("send event" )
365
377
}
366
378
379
+ p .event .OffsetEnd = p .endOffset
380
+
367
381
// Make a new event and reset our metadata.
368
382
defer func () {
369
383
p .event = log .NewEvent ()
0 commit comments