github.com/matrixorigin/matrixone@v1.2.0/pkg/util/trace/impl/motrace/buffer_pipe_test.go (about)

     1  // Copyright 2022 Matrix Origin
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package motrace
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	"io"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/google/gops/agent"
    27  	"github.com/google/uuid"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  	"go.uber.org/zap"
    31  	"go.uber.org/zap/zapcore"
    32  
    33  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    34  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    35  	"github.com/matrixorigin/matrixone/pkg/config"
    36  	"github.com/matrixorigin/matrixone/pkg/util/batchpipe"
    37  	"github.com/matrixorigin/matrixone/pkg/util/errutil"
    38  	"github.com/matrixorigin/matrixone/pkg/util/export/etl"
    39  	"github.com/matrixorigin/matrixone/pkg/util/export/table"
    40  	"github.com/matrixorigin/matrixone/pkg/util/internalExecutor"
    41  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    42  )
    43  
    44  var buf = new(bytes.Buffer)
    45  var err1 = moerr.NewInternalError(context.Background(), "test1")
    46  var err2 = errutil.Wrapf(err1, "test2")
    47  var traceIDSpanIDColumnStr string
    48  var traceIDSpanIDCsvStr string
    49  
    50  func noopReportError(context.Context, error, int) {}
    51  
    52  var dummyBaseTime time.Time
    53  
    54  func init() {
    55  	time.Local = time.FixedZone("CST", 0) // set time-zone +0000
    56  	dummyBaseTime = time.Unix(0, 0)
    57  	SV := config.ObservabilityParameters{}
    58  	SV.SetDefaultValues("v0.test.0")
    59  	SV.TraceExportInterval = 15
    60  	SV.LongQueryTime = 0
    61  	SV.EnableTraceDebug = true
    62  	if err, _ := InitWithConfig(
    63  		context.Background(),
    64  		&SV,
    65  		EnableTracer(true),
    66  		withMOVersion("v0.test.0"),
    67  		WithNode("node_uuid", trace.NodeTypeStandalone),
    68  		WithFSWriterFactory(&dummyFSWriterFactory{}),
    69  		WithSQLExecutor(func() internalExecutor.InternalExecutor {
    70  			return nil
    71  		}),
    72  	); err != nil {
    73  		panic(err)
    74  	}
    75  	errutil.SetErrorReporter(noopReportError)
    76  
    77  	sc := trace.SpanFromContext(DefaultContext()).SpanContext()
    78  	traceIDSpanIDColumnStr = fmt.Sprintf(`"%s", "%s"`, sc.TraceID.String(), sc.SpanID.String())
    79  	traceIDSpanIDCsvStr = fmt.Sprintf(`%s,%s`, sc.TraceID.String(), sc.SpanID.String())
    80  
    81  	if err := agent.Listen(agent.Options{}); err != nil {
    82  		_ = moerr.NewInternalError(DefaultContext(), "listen gops agent failed: %s", err)
    83  		panic(err)
    84  	}
    85  	fmt.Println("Finish tests init.")
    86  }
    87  
    88  type dummyStringWriter struct{}
    89  
    90  func (w *dummyStringWriter) WriteString(s string) (n int, err error) {
    91  	return fmt.Printf("dummyStringWriter: %s\n", s)
    92  }
    93  func (w *dummyStringWriter) WriteRow(row *table.Row) error {
    94  	fmt.Printf("dummyStringWriter: %v\n", row.ToStrings())
    95  	return nil
    96  }
    97  func (w *dummyStringWriter) FlushAndClose() (int, error) {
    98  	return 0, nil
    99  }
   100  func (w *dummyStringWriter) GetContent() string { return "" }
   101  
   102  func (w *dummyStringWriter) Write(p []byte) (n int, err error) {
   103  	return fmt.Printf("dummyStringWriter: %s\n", p)
   104  }
   105  
   106  func (w *dummyStringWriter) Close() error { return nil }
   107  
   108  type dummyFSWriterFactory struct{}
   109  
   110  func (f *dummyFSWriterFactory) GetRowWriter(ctx context.Context, account string, tbl *table.Table, ts time.Time) table.RowWriter {
   111  	return &dummyStringWriter{}
   112  }
   113  func (f *dummyFSWriterFactory) GetWriter(ctx context.Context, fp string) io.WriteCloser {
   114  	return &dummyStringWriter{}
   115  }
   116  
   117  func Test_newBuffer2Sql_base(t *testing.T) {
   118  
   119  	buf := NewItemBuffer()
   120  	byteBuf := new(bytes.Buffer)
   121  	assert.Equal(t, true, buf.IsEmpty())
   122  	buf.Add(&MOSpan{})
   123  	assert.Equal(t, false, buf.IsEmpty())
   124  	assert.Equal(t, false, buf.ShouldFlush())
   125  	assert.Equal(t, "", buf.GetBatch(context.TODO(), byteBuf))
   126  	buf.Reset()
   127  	assert.Equal(t, true, buf.IsEmpty())
   128  }
   129  
   130  func Test_buffer2Sql_IsEmpty(t *testing.T) {
   131  	type fields struct {
   132  		Reminder      batchpipe.Reminder
   133  		buf           []IBuffer2SqlItem
   134  		sizeThreshold int64
   135  		batchFunc     genBatchFunc
   136  	}
   137  	tests := []struct {
   138  		name   string
   139  		fields fields
   140  		want   bool
   141  	}{
   142  		{
   143  			name: "empty",
   144  			fields: fields{
   145  				Reminder:      batchpipe.NewConstantClock(time.Hour),
   146  				buf:           []IBuffer2SqlItem{},
   147  				sizeThreshold: mpool.GB,
   148  				batchFunc:     nil,
   149  			},
   150  			want: true,
   151  		},
   152  		{
   153  			name: "not_empty",
   154  			fields: fields{
   155  				Reminder:      batchpipe.NewConstantClock(time.Hour),
   156  				buf:           []IBuffer2SqlItem{&MOZapLog{}},
   157  				sizeThreshold: mpool.GB,
   158  				batchFunc:     nil,
   159  			},
   160  			want: false,
   161  		},
   162  	}
   163  	for _, tt := range tests {
   164  		t.Run(tt.name, func(t *testing.T) {
   165  			b := &itemBuffer{
   166  				Reminder:      tt.fields.Reminder,
   167  				buf:           tt.fields.buf,
   168  				sizeThreshold: tt.fields.sizeThreshold,
   169  				genBatchFunc:  tt.fields.batchFunc,
   170  			}
   171  			if got := b.IsEmpty(); got != tt.want {
   172  				t.Errorf("IsEmpty() = %v, want %v", got, tt.want)
   173  			}
   174  		})
   175  	}
   176  }
   177  
   178  func Test_buffer2Sql_Reset(t *testing.T) {
   179  	type fields struct {
   180  		Reminder      batchpipe.Reminder
   181  		buf           []IBuffer2SqlItem
   182  		sizeThreshold int64
   183  		batchFunc     genBatchFunc
   184  	}
   185  	tests := []struct {
   186  		name   string
   187  		fields fields
   188  		want   bool
   189  	}{
   190  		{
   191  			name: "empty",
   192  			fields: fields{
   193  				Reminder:      batchpipe.NewConstantClock(time.Hour),
   194  				buf:           []IBuffer2SqlItem{},
   195  				sizeThreshold: mpool.GB,
   196  				batchFunc:     nil,
   197  			},
   198  			want: true,
   199  		},
   200  		{
   201  			name: "not_empty",
   202  			fields: fields{
   203  				Reminder:      batchpipe.NewConstantClock(time.Hour),
   204  				buf:           []IBuffer2SqlItem{&MOZapLog{}},
   205  				sizeThreshold: mpool.GB,
   206  				batchFunc:     nil,
   207  			},
   208  			want: true,
   209  		},
   210  	}
   211  	for _, tt := range tests {
   212  		t.Run(tt.name, func(t *testing.T) {
   213  			b := &itemBuffer{
   214  				Reminder:      tt.fields.Reminder,
   215  				buf:           tt.fields.buf,
   216  				sizeThreshold: tt.fields.sizeThreshold,
   217  				genBatchFunc:  tt.fields.batchFunc,
   218  			}
   219  			b.Reset()
   220  			if got := b.IsEmpty(); got != tt.want {
   221  				t.Errorf("IsEmpty() = %v, want %v", got, tt.want)
   222  			}
   223  		})
   224  	}
   225  }
   226  
   227  func Test_withSizeThreshold(t *testing.T) {
   228  	type args struct {
   229  		size int64
   230  	}
   231  	tests := []struct {
   232  		name string
   233  		args args
   234  		want int64
   235  	}{
   236  		{name: "1  B", args: args{size: 1}, want: 1},
   237  		{name: "1 KB", args: args{size: mpool.KB}, want: 1 << 10},
   238  		{name: "1 MB", args: args{size: mpool.MB}, want: 1 << 20},
   239  		{name: "1 GB", args: args{size: mpool.GB}, want: 1 << 30},
   240  		{name: "1.001 GB", args: args{size: mpool.GB + mpool.MB}, want: 1<<30 + 1<<20},
   241  	}
   242  	buf := &itemBuffer{}
   243  	for _, tt := range tests {
   244  		t.Run(tt.name, func(t *testing.T) {
   245  			BufferWithSizeThreshold(tt.args.size).apply(buf)
   246  			if got := buf.sizeThreshold; got != tt.want {
   247  				t.Errorf("BufferWithSizeThreshold() = %v, want %v", got, tt.want)
   248  			}
   249  		})
   250  	}
   251  }
   252  
   253  /*
   254  var gCtrlSqlCh = make(chan struct{}, 1)
   255  func Test_batchSqlHandler_NewItemBatchHandler(t1 *testing.T) {
   256  	gCtrlSqlCh <- struct{}{}
   257  	type fields struct {
   258  		defaultOpts []BufferOption
   259  		ch          chan string
   260  	}
   261  	type args struct {
   262  		batch string
   263  	}
   264  
   265  	tests := []struct {
   266  		name   string
   267  		fields fields
   268  		args   args
   269  		want   func(batch any)
   270  	}{
   271  		{
   272  			name: "nil",
   273  			fields: fields{
   274  				defaultOpts: []BufferOption{BufferWithSizeThreshold(GB)},
   275  				ch:          make(chan string, 10),
   276  			},
   277  			args: args{
   278  				batch: "batch",
   279  			},
   280  			want: func(batch any) {},
   281  		},
   282  	}
   283  	for _, tt := range tests {
   284  		t1.Run(tt.name, func(t1 *testing.T) {
   285  			WithSQLExecutor(newDummyExecutorFactory(tt.fields.ch)).apply(&GetTracerProvider().tracerProviderConfig)
   286  			t := batchSqlHandler{
   287  				defaultOpts: tt.fields.defaultOpts,
   288  			}
   289  
   290  			got := t.NewItemBatchHandler(context.TODO())
   291  			go got(tt.args.batch)
   292  			batch, ok := <-tt.fields.ch
   293  			if ok {
   294  				require.Equal(t1, tt.args.batch, batch)
   295  			} else {
   296  				t1.Log("exec sql Done.")
   297  			}
   298  			//close(tt.fields.ch)
   299  		})
   300  	}
   301  	WithSQLExecutor(func() internalExecutor.InternalExecutor { return nil }).apply(&GetTracerProvider().tracerProviderConfig)
   302  	<-gCtrlSqlCh
   303  }*/
   304  
   305  var genFactory = func() table.WriterFactory {
   306  	return table.NewWriterFactoryGetter(
   307  		func(ctx context.Context, account string, tbl *table.Table, ts time.Time) table.RowWriter {
   308  			return etl.NewCSVWriter(ctx, &dummyStringWriter{})
   309  		},
   310  		nil,
   311  	)
   312  }
   313  
   314  func Test_genCsvData(t *testing.T) {
   315  	errorFormatter.Store("%v")
   316  	logStackFormatter.Store("%n")
   317  	type args struct {
   318  		in  []IBuffer2SqlItem
   319  		buf *bytes.Buffer
   320  	}
   321  	sc := trace.SpanContextWithIDs(_1TraceID, _1SpanID)
   322  	tests := []struct {
   323  		name string
   324  		args args
   325  		want any
   326  	}{
   327  		{
   328  			name: "single_span",
   329  			args: args{
   330  				in: []IBuffer2SqlItem{
   331  					&MOSpan{
   332  						SpanConfig: trace.SpanConfig{SpanContext: trace.SpanContext{TraceID: _1TraceID, SpanID: _1SpanID}, Parent: trace.NoopSpan{}},
   333  						Name:       "span1",
   334  						StartTime:  dummyBaseTime,
   335  						EndTime:    dummyBaseTime.Add(time.Microsecond),
   336  						Duration:   time.Microsecond,
   337  						tracer:     gTracer.(*MOTracer),
   338  					},
   339  				},
   340  				buf: buf,
   341  			},
   342  			want: `span_info,node_uuid,Standalone,0000000000000001,00000000-0000-0000-0000-000000000001,,1970-01-01 00:00:00.000001,,,,{},0,,,span1,0,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000001,1000,"{""Node"":{""node_uuid"":""node_uuid"",""node_type"":""Standalone""},""version"":""v0.test.0""}",internal,,
   343  `,
   344  		},
   345  		{
   346  			name: "multi_span",
   347  			args: args{
   348  				in: []IBuffer2SqlItem{
   349  					&MOSpan{
   350  						SpanConfig: trace.SpanConfig{SpanContext: trace.SpanContext{TraceID: _1TraceID, SpanID: _1SpanID, Kind: trace.SpanKindStatement}, Parent: trace.NoopSpan{}},
   351  						Name:       "span1",
   352  						StartTime:  dummyBaseTime,
   353  						EndTime:    dummyBaseTime.Add(time.Microsecond),
   354  						Duration:   time.Microsecond,
   355  						tracer:     gTracer.(*MOTracer),
   356  					},
   357  					&MOSpan{
   358  						SpanConfig: trace.SpanConfig{SpanContext: trace.SpanContext{TraceID: _1TraceID, SpanID: _2SpanID, Kind: trace.SpanKindRemote}, Parent: trace.NoopSpan{}},
   359  						Name:       "span2",
   360  						StartTime:  dummyBaseTime.Add(time.Microsecond),
   361  						EndTime:    dummyBaseTime.Add(time.Millisecond),
   362  						Duration:   time.Millisecond - time.Microsecond,
   363  						tracer:     gTracer.(*MOTracer),
   364  					},
   365  					&MOSpan{
   366  						SpanConfig: trace.SpanConfig{SpanContext: trace.SpanContext{TraceID: _1TraceID, SpanID: _2SpanID, Kind: trace.SpanKindRemote}, Parent: trace.NoopSpan{}},
   367  						Name:       "empty_end",
   368  						StartTime:  dummyBaseTime.Add(time.Microsecond),
   369  						Duration:   0,
   370  						tracer:     gTracer.(*MOTracer),
   371  						//EndTime:    table.ZeroTime,
   372  						ExtraFields: []zap.Field{zap.String("str", "field"), zap.Int64("int", 0)},
   373  					},
   374  				},
   375  				buf: buf,
   376  			},
   377  			want: `span_info,node_uuid,Standalone,0000000000000001,00000000-0000-0000-0000-000000000001,,1970-01-01 00:00:00.000001,,,,{},0,,,span1,0,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000001,1000,"{""Node"":{""node_uuid"":""node_uuid"",""node_type"":""Standalone""},""version"":""v0.test.0""}",statement,,
   378  span_info,node_uuid,Standalone,0000000000000002,00000000-0000-0000-0000-000000000001,,1970-01-01 00:00:00.001000,,,,{},0,,,span2,0,1970-01-01 00:00:00.000001,1970-01-01 00:00:00.001000,999000,"{""Node"":{""node_uuid"":""node_uuid"",""node_type"":""Standalone""},""version"":""v0.test.0""}",remote,,
   379  span_info,node_uuid,Standalone,0000000000000002,00000000-0000-0000-0000-000000000001,,0001-01-01 00:00:00.000000,,,,"{""str"":""field"",""int"":0}",0,,,empty_end,0,1970-01-01 00:00:00.000001,0001-01-01 00:00:00.000000,0,"{""Node"":{""node_uuid"":""node_uuid"",""node_type"":""Standalone""},""version"":""v0.test.0""}",remote,,
   380  `,
   381  		},
   382  		{
   383  			name: "single_zap",
   384  			args: args{
   385  				in: []IBuffer2SqlItem{
   386  					&MOZapLog{
   387  						Level:       zapcore.InfoLevel,
   388  						SpanContext: &sc,
   389  						Timestamp:   dummyBaseTime,
   390  						Caller:      "trace/buffer_pipe_sql_test.go:912",
   391  						Message:     "info message",
   392  						Extra:       "{}",
   393  					},
   394  				},
   395  				buf: buf,
   396  			},
   397  			want: `log_info,node_uuid,Standalone,0000000000000001,00000000-0000-0000-0000-000000000001,,1970-01-01 00:00:00.000000,info,trace/buffer_pipe_sql_test.go:912,info message,{},0,,,,0,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,0,{},internal,,
   398  `,
   399  		},
   400  		{
   401  			name: "multi_zap",
   402  			args: args{
   403  				in: []IBuffer2SqlItem{
   404  					&MOZapLog{
   405  						Level:       zapcore.InfoLevel,
   406  						SpanContext: &sc,
   407  						Timestamp:   dummyBaseTime,
   408  						Caller:      "trace/buffer_pipe_sql_test.go:939",
   409  						Message:     "info message",
   410  						Extra:       "{}",
   411  					},
   412  					&MOZapLog{
   413  						Level:       zapcore.DebugLevel,
   414  						SpanContext: &sc,
   415  						Timestamp:   dummyBaseTime.Add(time.Microsecond + time.Millisecond),
   416  						Caller:      "trace/buffer_pipe_sql_test.go:939",
   417  						Message:     "debug message",
   418  						Extra:       "{}",
   419  					},
   420  				},
   421  				buf: buf,
   422  			},
   423  			want: `log_info,node_uuid,Standalone,0000000000000001,00000000-0000-0000-0000-000000000001,,1970-01-01 00:00:00.000000,info,trace/buffer_pipe_sql_test.go:939,info message,{},0,,,,0,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,0,{},internal,,
   424  log_info,node_uuid,Standalone,0000000000000001,00000000-0000-0000-0000-000000000001,,1970-01-01 00:00:00.001001,debug,trace/buffer_pipe_sql_test.go:939,debug message,{},0,,,,0,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,0,{},internal,,
   425  `,
   426  		},
   427  		{
   428  			name: "single_statement",
   429  			args: args{
   430  				in: []IBuffer2SqlItem{
   431  					&StatementInfo{
   432  						StatementID:          _1TraceID,
   433  						TransactionID:        _1TxnID,
   434  						SessionID:            _1SesID,
   435  						Account:              "MO",
   436  						User:                 "moroot",
   437  						Database:             "system",
   438  						Statement:            "show tables",
   439  						StatementFingerprint: "show tables",
   440  						StatementTag:         "",
   441  						ExecPlan:             nil,
   442  						RequestAt:            dummyBaseTime,
   443  						ResponseAt:           dummyBaseTime,
   444  					},
   445  				},
   446  				buf: buf,
   447  			},
   448  			want: `00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0]",,,0,,0,0
   449  `,
   450  		},
   451  		{
   452  			name: "multi_statement",
   453  			args: args{
   454  				in: []IBuffer2SqlItem{
   455  					&StatementInfo{
   456  						StatementID:          _1TraceID,
   457  						TransactionID:        _1TxnID,
   458  						SessionID:            _1SesID,
   459  						Account:              "MO",
   460  						User:                 "moroot",
   461  						Database:             "system",
   462  						Statement:            "show tables",
   463  						StatementFingerprint: "show tables",
   464  						StatementTag:         "",
   465  						ExecPlan:             nil,
   466  						RequestAt:            dummyBaseTime,
   467  						ResponseAt:           dummyBaseTime,
   468  					},
   469  					&StatementInfo{
   470  						StatementID:          _2TraceID,
   471  						TransactionID:        _1TxnID,
   472  						SessionID:            _1SesID,
   473  						Account:              "MO",
   474  						User:                 "moroot",
   475  						Database:             "system",
   476  						Statement:            "show databases",
   477  						StatementFingerprint: "show databases",
   478  						StatementTag:         "dcl",
   479  						RequestAt:            dummyBaseTime.Add(time.Microsecond),
   480  						ResponseAt:           dummyBaseTime.Add(time.Microsecond + time.Second),
   481  						Duration:             time.Microsecond + time.Second,
   482  						Status:               StatementStatusFailed,
   483  						Error:                moerr.NewInternalError(DefaultContext(), "test error"),
   484  						ExecPlan:             nil,
   485  					},
   486  				},
   487  				buf: buf,
   488  			},
   489  			want: `00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0]",,,0,,0,0
   490  00000000-0000-0000-0000-000000000002,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000001000,Failed,20101,internal error: test error,{},0,0,"[0,0,0,0,0,0,0,0,0]",,,0,,0,0
   491  `,
   492  		},
   493  		{
   494  			name: "single_error",
   495  			args: args{
   496  				in: []IBuffer2SqlItem{
   497  					&MOErrorHolder{Error: err1, Timestamp: dummyBaseTime},
   498  				},
   499  				buf: buf,
   500  			},
   501  			want: `error_info,node_uuid,Standalone,0,,,1970-01-01 00:00:00.000000,,,,{},20101,internal error: test1,internal error: test1,,0,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,0,{},,,
   502  `,
   503  		},
   504  		{
   505  			name: "multi_error",
   506  			args: args{
   507  				in: []IBuffer2SqlItem{
   508  					&MOErrorHolder{Error: err1, Timestamp: dummyBaseTime},
   509  					&MOErrorHolder{Error: err2, Timestamp: dummyBaseTime.Add(time.Millisecond + time.Microsecond)},
   510  				},
   511  				buf: buf,
   512  			},
   513  			want: `error_info,node_uuid,Standalone,0,,,1970-01-01 00:00:00.000000,,,,{},20101,internal error: test1,internal error: test1,,0,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,0,{},,,
   514  error_info,node_uuid,Standalone,0,,,1970-01-01 00:00:00.001001,,,,{},20101,test2: internal error: test1,test2: internal error: test1,,0,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,0,{},,,
   515  `,
   516  		},
   517  	}
   518  
   519  	for _, tt := range tests {
   520  		t.Run(tt.name, func(t *testing.T) {
   521  			got := genETLData(context.TODO(), tt.args.in, tt.args.buf, genFactory())
   522  			require.NotEqual(t, nil, got)
   523  			req, ok := got.(table.ExportRequests)
   524  			require.Equal(t, true, ok)
   525  			require.Equal(t, 1, len(req))
   526  			batch := req[0].(*table.RowRequest)
   527  			content := batch.GetContent()
   528  			assert.Equalf(t, tt.want, content, "genETLData(%v, %v)", content, tt.args.buf)
   529  			t.Logf("%s", tt.want)
   530  		})
   531  	}
   532  }
   533  
   534  func Test_genCsvData_diffAccount(t *testing.T) {
   535  	type args struct {
   536  		in  []IBuffer2SqlItem
   537  		buf *bytes.Buffer
   538  	}
   539  	tests := []struct {
   540  		name       string
   541  		args       args
   542  		wantReqCnt int
   543  		want       []string
   544  	}{
   545  		{
   546  			name: "single_statement",
   547  			args: args{
   548  				in: []IBuffer2SqlItem{
   549  					&StatementInfo{
   550  						StatementID:          _1TraceID,
   551  						TransactionID:        _1TxnID,
   552  						SessionID:            _1SesID,
   553  						Account:              "MO",
   554  						User:                 "moroot",
   555  						Database:             "system",
   556  						Statement:            "show tables",
   557  						StatementFingerprint: "show tables",
   558  						StatementTag:         "",
   559  						ExecPlan:             nil,
   560  						RequestAt:            dummyBaseTime,
   561  						ResponseAt:           dummyBaseTime,
   562  					},
   563  				},
   564  				buf: buf,
   565  			},
   566  			wantReqCnt: 1,
   567  			want: []string{`00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0]",,,0,,0,0
   568  `},
   569  		},
   570  		{
   571  			name: "multi_statement",
   572  			args: args{
   573  				in: []IBuffer2SqlItem{
   574  					&StatementInfo{
   575  						StatementID:          _1TraceID,
   576  						TransactionID:        _1TxnID,
   577  						SessionID:            _1SesID,
   578  						Account:              "MO",
   579  						User:                 "moroot",
   580  						Database:             "system",
   581  						Statement:            "show tables",
   582  						StatementFingerprint: "show tables",
   583  						StatementTag:         "",
   584  						ExecPlan:             nil,
   585  						RequestAt:            dummyBaseTime,
   586  						ResponseAt:           dummyBaseTime,
   587  					},
   588  					&StatementInfo{
   589  						StatementID:          _2TraceID,
   590  						TransactionID:        _1TxnID,
   591  						SessionID:            _1SesID,
   592  						Account:              "sys",
   593  						User:                 "moroot",
   594  						Database:             "system",
   595  						Statement:            "show databases",
   596  						StatementFingerprint: "show databases",
   597  						StatementTag:         "dcl",
   598  						RequestAt:            dummyBaseTime.Add(time.Microsecond),
   599  						ResponseAt:           dummyBaseTime.Add(time.Microsecond + time.Second),
   600  						Duration:             time.Microsecond + time.Second,
   601  						Status:               StatementStatusFailed,
   602  						Error:                moerr.NewInternalError(DefaultContext(), "test error"),
   603  						ExecPlan:             nil,
   604  					},
   605  				},
   606  				buf: buf,
   607  			},
   608  			wantReqCnt: 1,
   609  			want: []string{`00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,0,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0]",,,0,,0,0
   610  `, `00000000-0000-0000-0000-000000000002,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,sys,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000001000,Failed,20101,internal error: test error,{},0,0,"[0,0,0,0,0,0,0,0,0]",,,0,,0,0
   611  `},
   612  		},
   613  	}
   614  	for _, tt := range tests {
   615  		t.Run(tt.name, func(t *testing.T) {
   616  			got := genETLData(DefaultContext(), tt.args.in, tt.args.buf, genFactory())
   617  			require.NotEqual(t, nil, got)
   618  			reqs, ok := got.(table.ExportRequests)
   619  			require.Equal(t, true, ok)
   620  			require.Equal(t, tt.wantReqCnt, len(reqs))
   621  			require.Equal(t, len(tt.args.in), len(tt.want))
   622  			for _, req := range reqs {
   623  				found := false
   624  				batch := req.(*table.RowRequest)
   625  				for idx, w := range tt.want {
   626  					if strings.Contains(batch.GetContent(), w) {
   627  						found = true
   628  						t.Logf("idx %d: %s", idx, w)
   629  					}
   630  				}
   631  				assert.Equalf(t, true, found, "genETLData: %v", batch.GetContent())
   632  			}
   633  		})
   634  	}
   635  }
   636  
   637  func Test_genCsvData_LongQueryTime(t *testing.T) {
   638  	errorFormatter.Store("%v")
   639  	logStackFormatter.Store("%n")
   640  	type args struct {
   641  		preapre func([]IBuffer2SqlItem)
   642  
   643  		in     []IBuffer2SqlItem
   644  		buf    *bytes.Buffer
   645  		queryT int64
   646  	}
   647  	tests := []struct {
   648  		name string
   649  		args args
   650  		want any
   651  	}{
   652  		{
   653  			name: "multi_statement",
   654  			args: args{
   655  				preapre: func(in []IBuffer2SqlItem) {
   656  					for _, item := range in {
   657  						item.(*StatementInfo).ExecPlan2Stats(context.TODO())
   658  					}
   659  				},
   660  				in: []IBuffer2SqlItem{
   661  					&StatementInfo{
   662  						StatementID:          _1TraceID,
   663  						TransactionID:        _1TxnID,
   664  						SessionID:            _1SesID,
   665  						Account:              "MO",
   666  						User:                 "moroot",
   667  						Database:             "system",
   668  						Statement:            "show tables",
   669  						StatementFingerprint: "show tables",
   670  						StatementTag:         "",
   671  						ExecPlan:             nil,
   672  						Duration:             time.Second - time.Nanosecond,
   673  						ResultCount:          1,
   674  					},
   675  					&StatementInfo{
   676  						StatementID:          _1TraceID,
   677  						TransactionID:        _1TxnID,
   678  						SessionID:            _1SesID,
   679  						Account:              "MO",
   680  						User:                 "moroot",
   681  						Database:             "system",
   682  						Statement:            "show tables",
   683  						StatementFingerprint: "show tables",
   684  						StatementTag:         "",
   685  						ExecPlan:             NewDummySerializableExecPlan(nil, dummySerializeExecPlan, uuid.UUID(_1TraceID)),
   686  						Duration:             time.Second - time.Nanosecond,
   687  						ResultCount:          2,
   688  						RequestAt:            dummyBaseTime,
   689  						ResponseAt:           dummyBaseTime,
   690  					},
   691  					&StatementInfo{
   692  						StatementID:          _2TraceID,
   693  						TransactionID:        _1TxnID,
   694  						SessionID:            _1SesID,
   695  						Account:              "MO",
   696  						User:                 "moroot",
   697  						Database:             "system",
   698  						Statement:            "show databases",
   699  						StatementFingerprint: "show databases",
   700  						StatementTag:         "dcl",
   701  						RequestAt:            dummyBaseTime.Add(time.Microsecond),
   702  						ResponseAt:           dummyBaseTime.Add(time.Microsecond + time.Second),
   703  						Duration:             time.Second,
   704  						Status:               StatementStatusFailed,
   705  						Error:                moerr.NewInternalError(DefaultContext(), "test error"),
   706  						ExecPlan:             NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   707  						SqlSourceType:        "internal",
   708  						ResultCount:          3,
   709  					},
   710  				},
   711  				buf:    buf,
   712  				queryT: int64(time.Second),
   713  			},
   714  			want: `00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,0001-01-01 00:00:00.000000,0001-01-01 00:00:00.000000,999999999,Running,0,,{},0,0,"[0,0,0,0,0,0,0,0,0]",,,0,,0,1
   715  00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show tables,,show tables,node_uuid,Standalone,1970-01-01 00:00:00.000000,1970-01-01 00:00:00.000000,999999999,Running,0,,"{""code"":200,""message"":""no exec plan""}",0,0,"[4,0,0,0,0,0,0,0,0]",,,0,,0,2
   716  00000000-0000-0000-0000-000000000002,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,MO,moroot,,system,show databases,dcl,show databases,node_uuid,Standalone,1970-01-01 00:00:00.000001,1970-01-01 00:00:01.000001,1000000000,Failed,20101,internal error: test error,"{""key"":""val""}",1,1,"[4,1,2.000,3,4,5,0,0,44.0161]",,,0,internal,0,3
   717  `,
   718  		},
   719  	}
   720  	for _, tt := range tests {
   721  		t.Run(tt.name, func(t *testing.T) {
   722  			GetTracerProvider().longQueryTime = tt.args.queryT
   723  			if tt.args.preapre != nil {
   724  				tt.args.preapre(tt.args.in)
   725  			}
   726  			got := genETLData(DefaultContext(), tt.args.in, tt.args.buf, genFactory())
   727  			require.NotEqual(t, nil, got)
   728  			req, ok := got.(table.ExportRequests)
   729  			require.Equal(t, true, ok)
   730  			require.Equal(t, 1, len(req))
   731  			batch := req[0].(*table.RowRequest)
   732  			content := batch.GetContent()
   733  			assert.Equalf(t, tt.want, content, "genETLData(%v, %v)", content, tt.args.buf)
   734  			t.Logf("%s", tt.want)
   735  			GetTracerProvider().longQueryTime = 0
   736  		})
   737  	}
   738  }