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  }