github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/slow_query_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package interlock 15 16 import ( 17 "bufio" 18 "bytes" 19 "context" 20 "io" 21 "os" 22 "strings" 23 "time" 24 25 "github.com/whtcorpsinc/BerolinaSQL/terror" 26 . "github.com/whtcorpsinc/check" 27 "github.com/whtcorpsinc/failpoint" 28 causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded" 29 "github.com/whtcorpsinc/milevadb/soliton/logutil" 30 "github.com/whtcorpsinc/milevadb/soliton/mock" 31 "github.com/whtcorpsinc/milevadb/stochastikctx" 32 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 33 "github.com/whtcorpsinc/milevadb/types" 34 ) 35 36 func parseLog(retriever *slowQueryRetriever, sctx stochastikctx.Context, reader *bufio.Reader) ([][]types.Causet, error) { 37 retriever.parsedSlowLogCh = make(chan parsedSlowLog, 100) 38 ctx := context.Background() 39 retriever.parseSlowLog(ctx, sctx, reader, 64) 40 slowLog := <-retriever.parsedSlowLogCh 41 rows, err := slowLog.rows, slowLog.err 42 if err == io.EOF { 43 err = nil 44 } 45 return rows, err 46 } 47 48 func parseSlowLog(sctx stochastikctx.Context, reader *bufio.Reader) ([][]types.Causet, error) { 49 retriever := &slowQueryRetriever{} 50 // Ignore the error is ok for test. 51 terror.Log(retriever.initialize(sctx)) 52 rows, err := parseLog(retriever, sctx, reader) 53 return rows, err 54 } 55 56 func (s *testInterDircSerialSuite) TestParseSlowLogPanic(c *C) { 57 slowLogStr := 58 `# Time: 2020-04-28T15:24:04.309074+08:00 59 # Txn_start_ts: 405888132465033227 60 # User@Host: root[root] @ localhost [127.0.0.1] 61 # Query_time: 0.216905 62 # Cop_time: 0.38 Process_time: 0.021 Request_count: 1 Total_keys: 637 Processed_keys: 436 63 # Is_internal: true 64 # Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 65 # Stats: t1:1,t2:2 66 # Cop_proc_avg: 0.1 Cop_proc_p90: 0.2 Cop_proc_max: 0.03 Cop_proc_addr: 127.0.0.1:20160 67 # Cop_wait_avg: 0.05 Cop_wait_p90: 0.6 Cop_wait_max: 0.8 Cop_wait_addr: 0.0.0.0:20160 68 # Mem_max: 70724 69 # Disk_max: 65536 70 # Causet_from_cache: true 71 # Succ: false 72 # Causet_digest: 60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4 73 # Prev_stmt: uFIDelate t set i = 1; 74 use test; 75 select * from t;` 76 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/interlock/errorMockParseSlowLogPanic", `return(true)`), IsNil) 77 defer func() { 78 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/interlock/errorMockParseSlowLogPanic"), IsNil) 79 }() 80 reader := bufio.NewReader(bytes.NewBufferString(slowLogStr)) 81 loc, err := time.LoadLocation("Asia/Shanghai") 82 c.Assert(err, IsNil) 83 sctx := mock.NewContext() 84 sctx.GetStochastikVars().TimeZone = loc 85 _, err = parseSlowLog(sctx, reader) 86 c.Assert(err, NotNil) 87 c.Assert(err.Error(), Equals, "panic test") 88 } 89 90 func (s *testInterDircSuite) TestParseSlowLogFile(c *C) { 91 slowLogStr := 92 `# Time: 2020-04-28T15:24:04.309074+08:00 93 # Txn_start_ts: 405888132465033227 94 # User@Host: root[root] @ localhost [127.0.0.1] 95 # InterDirc_retry_time: 0.12 InterDirc_retry_count: 57 96 # Query_time: 0.216905 97 # Cop_time: 0.38 Process_time: 0.021 Request_count: 1 Total_keys: 637 Processed_keys: 436 98 # Is_internal: true 99 # Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 100 # Stats: t1:1,t2:2 101 # Cop_proc_avg: 0.1 Cop_proc_p90: 0.2 Cop_proc_max: 0.03 Cop_proc_addr: 127.0.0.1:20160 102 # Cop_wait_avg: 0.05 Cop_wait_p90: 0.6 Cop_wait_max: 0.8 Cop_wait_addr: 0.0.0.0:20160 103 # Mem_max: 70724 104 # Disk_max: 65536 105 # Causet_from_cache: true 106 # Succ: false 107 # Causet_digest: 60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4 108 # Prev_stmt: uFIDelate t set i = 1; 109 use test; 110 select * from t;` 111 reader := bufio.NewReader(bytes.NewBufferString(slowLogStr)) 112 loc, err := time.LoadLocation("Asia/Shanghai") 113 c.Assert(err, IsNil) 114 ctx := mock.NewContext() 115 ctx.GetStochastikVars().TimeZone = loc 116 rows, err := parseSlowLog(ctx, reader) 117 c.Assert(err, IsNil) 118 c.Assert(len(rows), Equals, 1) 119 recordString := "" 120 for i, value := range rows[0] { 121 str, err := value.ToString() 122 c.Assert(err, IsNil) 123 if i > 0 { 124 recordString += "," 125 } 126 recordString += str 127 } 128 expectRecordString := "2020-04-28 15:24:04.309074,405888132465033227,root,localhost,0,57,0.12,0.216905,0,0,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,0,0,0.38,0.021,0,0,0,1,637,0,,,1,42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772,t1:1,t2:2,0.1,0.2,0.03,127.0.0.1:20160,0.05,0.6,0.8,0.0.0.0:20160,70724,65536,0,1,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,uFIDelate t set i = 1;,select * from t;" 129 c.Assert(expectRecordString, Equals, recordString) 130 131 // fix allegrosql contain '# ' bug 132 slowLog := bytes.NewBufferString( 133 `# Time: 2020-04-28T15:24:04.309074+08:00 134 select a# from t; 135 # Time: 2020-01-24T22:32:29.313255+08:00 136 # Txn_start_ts: 405888132465033227 137 # Query_time: 0.216905 138 # Process_time: 0.021 Request_count: 1 Total_keys: 637 Processed_keys: 436 139 # Is_internal: true 140 # Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 141 # Stats: t1:1,t2:2 142 # Succ: false 143 select * from t; 144 `) 145 reader = bufio.NewReader(slowLog) 146 _, err = parseSlowLog(ctx, reader) 147 c.Assert(err, IsNil) 148 149 // test for time format compatibility. 150 slowLog = bytes.NewBufferString( 151 `# Time: 2020-04-28T15:24:04.309074+08:00 152 select * from t; 153 # Time: 2020-04-24-19:41:21.716221 +0800 154 select * from t; 155 `) 156 reader = bufio.NewReader(slowLog) 157 rows, err = parseSlowLog(ctx, reader) 158 c.Assert(err, IsNil) 159 c.Assert(len(rows) == 2, IsTrue) 160 t0Str, err := rows[0][0].ToString() 161 c.Assert(err, IsNil) 162 c.Assert(t0Str, Equals, "2020-04-28 15:24:04.309074") 163 t1Str, err := rows[1][0].ToString() 164 c.Assert(err, IsNil) 165 c.Assert(t1Str, Equals, "2020-04-24 19:41:21.716221") 166 167 // Add parse error check. 168 slowLog = bytes.NewBufferString( 169 `# Time: 2020-04-28T15:24:04.309074+08:00 170 # Succ: abc 171 select * from t; 172 `) 173 reader = bufio.NewReader(slowLog) 174 _, err = parseSlowLog(ctx, reader) 175 c.Assert(err, IsNil) 176 warnings := ctx.GetStochastikVars().StmtCtx.GetWarnings() 177 c.Assert(warnings, HasLen, 1) 178 c.Assert(warnings[0].Err.Error(), Equals, "Parse slow log at line 2 failed. Field: `Succ`, error: strconv.ParseBool: parsing \"abc\": invalid syntax") 179 } 180 181 // It changes variable.MaxOfMaxAllowedPacket, so must be stayed in SerialSuite. 182 func (s *testInterDircSerialSuite) TestParseSlowLogFileSerial(c *C) { 183 loc, err := time.LoadLocation("Asia/Shanghai") 184 c.Assert(err, IsNil) 185 ctx := mock.NewContext() 186 ctx.GetStochastikVars().TimeZone = loc 187 // test for bufio.Scanner: token too long. 188 slowLog := bytes.NewBufferString( 189 `# Time: 2020-04-28T15:24:04.309074+08:00 190 select * from t; 191 # Time: 2020-04-24-19:41:21.716221 +0800 192 `) 193 originValue := variable.MaxOfMaxAllowedPacket 194 variable.MaxOfMaxAllowedPacket = 65536 195 allegrosql := strings.Repeat("x", int(variable.MaxOfMaxAllowedPacket+1)) 196 slowLog.WriteString(allegrosql) 197 reader := bufio.NewReader(slowLog) 198 _, err = parseSlowLog(ctx, reader) 199 c.Assert(err, NotNil) 200 c.Assert(err.Error(), Equals, "single line length exceeds limit: 65536") 201 202 variable.MaxOfMaxAllowedPacket = originValue 203 reader = bufio.NewReader(slowLog) 204 _, err = parseSlowLog(ctx, reader) 205 c.Assert(err, IsNil) 206 } 207 208 func (s *testInterDircSuite) TestSlowLogParseTime(c *C) { 209 t1Str := "2020-01-24T22:32:29.313255+08:00" 210 t2Str := "2020-01-24T22:32:29.313255" 211 t1, err := ParseTime(t1Str) 212 c.Assert(err, IsNil) 213 loc, err := time.LoadLocation("Asia/Shanghai") 214 c.Assert(err, IsNil) 215 t2, err := time.ParseInLocation("2006-01-02T15:04:05.999999999", t2Str, loc) 216 c.Assert(err, IsNil) 217 c.Assert(t1.Unix(), Equals, t2.Unix()) 218 t1Format := t1.In(loc).Format(logutil.SlowLogTimeFormat) 219 c.Assert(t1Format, Equals, t1Str) 220 } 221 222 // TestFixParseSlowLogFile bugfix 223 // allegrosql select * from INFORMATION_SCHEMA.SLOW_QUERY limit 1; 224 // ERROR 1105 (HY000): string "2020-05-12-11:23:29.61474688" doesn't has a prefix that matches format "2006-01-02-15:04:05.999999999 -0700", err: parsing time "2020-05-12-11:23:29.61474688" as "2006-01-02-15:04:05.999999999 -0700": cannot parse "" as "-0700" 225 func (s *testInterDircSuite) TestFixParseSlowLogFile(c *C) { 226 slowLog := bytes.NewBufferString( 227 `# Time: 2020-05-12-11:23:29.614327491 +0800 228 # Txn_start_ts: 405888132465033227 229 # Query_time: 0.216905 230 # Process_time: 0.021 Request_count: 1 Total_keys: 637 Processed_keys: 436 231 # Is_internal: true 232 # Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 233 # Stats: t1:1,t2:2 234 # Cop_proc_avg: 0.1 Cop_proc_p90: 0.2 Cop_proc_max: 0.03 235 # Cop_wait_avg: 0.05 Cop_wait_p90: 0.6 Cop_wait_max: 0.8 236 # Mem_max: 70724 237 select * from t 238 # Time: 2020-05-12-11:23:29.614327491 +0800 239 # Txn_start_ts: 405888132465033227 240 # Query_time: 0.216905 241 # Process_time: 0.021 Request_count: 1 Total_keys: 637 Processed_keys: 436 242 # Is_internal: true 243 # Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 244 # Stats: t1:1,t2:2 245 # Cop_proc_avg: 0.1 Cop_proc_p90: 0.2 Cop_proc_max: 0.03 246 # Cop_wait_avg: 0.05 Cop_wait_p90: 0.6 Cop_wait_max: 0.8 247 # Mem_max: 70724 248 # Causet_digest: 60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4 249 select * from t;`) 250 scanner := bufio.NewReader(slowLog) 251 loc, err := time.LoadLocation("Asia/Shanghai") 252 c.Assert(err, IsNil) 253 ctx := mock.NewContext() 254 ctx.GetStochastikVars().TimeZone = loc 255 _, err = parseSlowLog(ctx, scanner) 256 c.Assert(err, IsNil) 257 258 // Test BerolinaSQL error. 259 slowLog = bytes.NewBufferString( 260 `# Time: 2020-05-12-11:23:29.614327491 +0800 261 # Txn_start_ts: 405888132465033227# 262 `) 263 264 scanner = bufio.NewReader(slowLog) 265 _, err = parseSlowLog(ctx, scanner) 266 c.Assert(err, IsNil) 267 warnings := ctx.GetStochastikVars().StmtCtx.GetWarnings() 268 c.Assert(warnings, HasLen, 1) 269 c.Assert(warnings[0].Err.Error(), Equals, "Parse slow log at line 2 failed. Field: `Txn_start_ts`, error: strconv.ParseUint: parsing \"405888132465033227#\": invalid syntax") 270 271 } 272 273 func (s *testInterDircSuite) TestSlowQueryRetriever(c *C) { 274 writeFile := func(file string, data string) { 275 f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) 276 c.Assert(err, IsNil) 277 _, err = f.Write([]byte(data)) 278 c.Assert(f.Close(), IsNil) 279 c.Assert(err, IsNil) 280 } 281 282 logData0 := "" 283 logData1 := ` 284 # Time: 2020-02-15T18:00:01.000000+08:00 285 select 1; 286 # Time: 2020-02-15T19:00:05.000000+08:00 287 select 2;` 288 logData2 := ` 289 # Time: 2020-02-16T18:00:01.000000+08:00 290 select 3; 291 # Time: 2020-02-16T18:00:05.000000+08:00 292 select 4;` 293 logData3 := ` 294 # Time: 2020-02-16T19:00:00.000000+08:00 295 select 5; 296 # Time: 2020-02-17T18:00:05.000000+08:00 297 select 6; 298 # Time: 2020-04-15T18:00:05.299063744+08:00 299 select 7;` 300 301 fileName0 := "milevadb-slow-2020-02-14T19-04-05.01.log" 302 fileName1 := "milevadb-slow-2020-02-15T19-04-05.01.log" 303 fileName2 := "milevadb-slow-2020-02-16T19-04-05.01.log" 304 fileName3 := "milevadb-slow.log" 305 writeFile(fileName0, logData0) 306 writeFile(fileName1, logData1) 307 writeFile(fileName2, logData2) 308 writeFile(fileName3, logData3) 309 defer func() { 310 os.Remove(fileName0) 311 os.Remove(fileName1) 312 os.Remove(fileName2) 313 os.Remove(fileName3) 314 }() 315 316 cases := []struct { 317 startTime string 318 endTime string 319 files []string 320 querys []string 321 }{ 322 { 323 startTime: "2020-02-15T18:00:00.000000+08:00", 324 endTime: "2020-02-17T20:00:00.000000+08:00", 325 files: []string{fileName1, fileName2, fileName3}, 326 querys: []string{ 327 "select 1;", 328 "select 2;", 329 "select 3;", 330 "select 4;", 331 "select 5;", 332 "select 6;", 333 }, 334 }, 335 { 336 startTime: "2020-02-15T18:00:02.000000+08:00", 337 endTime: "2020-02-16T20:00:00.000000+08:00", 338 files: []string{fileName1, fileName2, fileName3}, 339 querys: []string{ 340 "select 2;", 341 "select 3;", 342 "select 4;", 343 "select 5;", 344 }, 345 }, 346 { 347 startTime: "2020-02-16T18:00:03.000000+08:00", 348 endTime: "2020-02-16T18:59:00.000000+08:00", 349 files: []string{fileName2}, 350 querys: []string{ 351 "select 4;", 352 }, 353 }, 354 { 355 startTime: "2020-02-16T18:00:03.000000+08:00", 356 endTime: "2020-02-16T20:00:00.000000+08:00", 357 files: []string{fileName2, fileName3}, 358 querys: []string{ 359 "select 4;", 360 "select 5;", 361 }, 362 }, 363 { 364 startTime: "2020-02-16T19:00:00.000000+08:00", 365 endTime: "2020-02-17T17:00:00.000000+08:00", 366 files: []string{fileName3}, 367 querys: []string{ 368 "select 5;", 369 }, 370 }, 371 { 372 startTime: "2010-01-01T00:00:00.000000+08:00", 373 endTime: "2010-01-01T01:00:00.000000+08:00", 374 files: []string{}, 375 }, 376 { 377 startTime: "2020-03-01T00:00:00.000000+08:00", 378 endTime: "2010-03-01T01:00:00.000000+08:00", 379 files: []string{}, 380 }, 381 { 382 startTime: "", 383 endTime: "", 384 files: []string{fileName3}, 385 querys: []string{ 386 "select 5;", 387 "select 6;", 388 "select 7;", 389 }, 390 }, 391 { 392 startTime: "2020-04-15T18:00:05.299063744+08:00", 393 endTime: "2020-04-15T18:00:05.299063744+08:00", 394 files: []string{fileName3}, 395 querys: []string{ 396 "select 7;", 397 }, 398 }, 399 } 400 401 loc, err := time.LoadLocation("Asia/Shanghai") 402 c.Assert(err, IsNil) 403 sctx := mock.NewContext() 404 sctx.GetStochastikVars().TimeZone = loc 405 sctx.GetStochastikVars().SlowQueryFile = fileName3 406 for i, cas := range cases { 407 extractor := &causetembedded.SlowQueryExtractor{Enable: (len(cas.startTime) > 0 && len(cas.endTime) > 0)} 408 if extractor.Enable { 409 startTime, err := ParseTime(cas.startTime) 410 c.Assert(err, IsNil) 411 endTime, err := ParseTime(cas.endTime) 412 c.Assert(err, IsNil) 413 extractor.StartTime = startTime 414 extractor.EndTime = endTime 415 416 } 417 retriever := &slowQueryRetriever{extractor: extractor} 418 err := retriever.initialize(sctx) 419 c.Assert(err, IsNil) 420 comment := Commentf("case id: %v", i) 421 c.Assert(retriever.files, HasLen, len(cas.files), comment) 422 if len(retriever.files) > 0 { 423 reader := bufio.NewReader(retriever.files[0].file) 424 rows, err := parseLog(retriever, sctx, reader) 425 c.Assert(err, IsNil) 426 c.Assert(len(rows), Equals, len(cas.querys), comment) 427 for i, event := range rows { 428 c.Assert(event[len(event)-1].GetString(), Equals, cas.querys[i], comment) 429 } 430 } 431 432 for i, file := range retriever.files { 433 c.Assert(file.file.Name(), Equals, cas.files[i]) 434 c.Assert(file.file.Close(), IsNil) 435 } 436 c.Assert(retriever.close(), IsNil) 437 } 438 }