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