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

     1  // Copyright 2023 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  	"context"
    19  	"errors"
    20  	"strconv"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/google/uuid"
    25  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic"
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  func TestAggregator(t *testing.T) {
    31  
    32  	var sessionId [16]byte
    33  	sessionId[0] = 1
    34  	var sessionId2 [16]byte
    35  	sessionId2[0] = 2
    36  	const aggrWindow = 5 * time.Second
    37  
    38  	ctx := context.Background()
    39  	aggregator := NewAggregator(
    40  		ctx,
    41  		aggrWindow,
    42  		StatementInfoNew,
    43  		StatementInfoUpdate,
    44  		StatementInfoFilter,
    45  	)
    46  
    47  	// Insert StatementInfo instances into the aggregator
    48  	_, err := aggregator.AddItem(&StatementInfo{
    49  		StatementType: "Grant",
    50  		Duration:      time.Duration(500 * time.Millisecond), // make it longer than 200ms to pass filter
    51  		SqlSourceType: "internal_sql",
    52  	})
    53  
    54  	if !errors.Is(err, ErrFilteredOut) {
    55  		t.Fatalf("Expected error ErrFilteredOut, got: %v", err)
    56  	}
    57  
    58  	// Insert StatementInfo instances into the aggregator
    59  	_, err = aggregator.AddItem(&StatementInfo{
    60  		StatementType: "Select",
    61  		Duration:      time.Duration(500 * time.Millisecond), // make it longer than 200ms to pass filter
    62  		SqlSourceType: "internal_sql",
    63  	})
    64  
    65  	if !errors.Is(err, ErrFilteredOut) {
    66  		t.Fatalf("Expected error ErrFilteredOut, got: %v", err)
    67  	}
    68  
    69  	_, err = aggregator.AddItem(&StatementInfo{
    70  		StatementType: "Type1",
    71  		Duration:      time.Duration(10 * time.Second),
    72  	})
    73  
    74  	if !errors.Is(err, ErrFilteredOut) {
    75  		t.Fatalf("Expected error ErrFilteredOut, got: %v", err)
    76  	}
    77  
    78  	_, err = aggregator.AddItem(&StatementInfo{
    79  		StatementType: "Insert",
    80  		SqlSourceType: "cloud_user",
    81  		Duration:      time.Duration(10 * time.Second),
    82  	})
    83  
    84  	if !errors.Is(err, ErrFilteredOut) {
    85  		t.Fatalf("Expected error ErrFilteredOut, got: %v", err)
    86  	}
    87  
    88  	// Get results from aggregator
    89  	results := aggregator.GetResults()
    90  
    91  	// Test expected behavior
    92  	if len(results) != 0 {
    93  		t.Errorf("Expected 0 aggregated statements, got %d", len(results))
    94  	}
    95  
    96  	// Aggregate some Select
    97  	fixedTime := time.Date(2023, time.June, 10, 12, 0, 1, 0, time.UTC)
    98  	for i := 0; i < 5; i++ {
    99  		_, err = aggregator.AddItem(&StatementInfo{
   100  			Account:       "MO",
   101  			User:          "moroot",
   102  			Database:      "system",
   103  			StatementType: "Select",
   104  			SqlSourceType: "external_sql",
   105  			SessionID:     sessionId,
   106  			Statement:     "SELECT 11",
   107  			ResponseAt:    fixedTime,
   108  			RequestAt:     fixedTime.Add(-10 * time.Millisecond),
   109  			Duration:      10 * time.Millisecond,
   110  			TransactionID: _1TxnID,
   111  			StatementID:   _1TxnID,
   112  			Status:        StatementStatusSuccess,
   113  			ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   114  			ConnType:      statistic.ConnTypeExternal,
   115  		})
   116  		if err != nil {
   117  			t.Fatalf("Unexpected error when adding item: %v", err)
   118  		}
   119  
   120  		// different session id
   121  		_, err = aggregator.AddItem(&StatementInfo{
   122  			Account:       "MO",
   123  			User:          "moroot",
   124  			Database:      "system",
   125  			StatementType: "Select",
   126  			SqlSourceType: "internal_sql",
   127  			SessionID:     sessionId2,
   128  			Statement:     "SELECT 11",
   129  			ResponseAt:    fixedTime,
   130  			RequestAt:     fixedTime.Add(-10 * time.Millisecond),
   131  			Duration:      10 * time.Millisecond,
   132  			TransactionID: _1TxnID,
   133  			StatementID:   _1TxnID,
   134  			Status:        StatementStatusSuccess,
   135  			ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   136  			ConnType:      statistic.ConnTypeExternal,
   137  		})
   138  		if err != nil {
   139  			t.Fatalf("Unexpected error when adding item: %v", err)
   140  		}
   141  
   142  		// same as the second session id with 5 seconds later
   143  		_, err = aggregator.AddItem(&StatementInfo{
   144  			Account:       "MO",
   145  			User:          "moroot",
   146  			Database:      "system",
   147  			StatementType: "Select",
   148  			SqlSourceType: "internal_sql",
   149  			SessionID:     sessionId2,
   150  			Statement:     "SELECT 11",
   151  			ResponseAt:    fixedTime.Add(6 * time.Second),
   152  			RequestAt:     fixedTime.Add(6 * time.Second).Add(-10 * time.Millisecond),
   153  			Duration:      10 * time.Millisecond,
   154  			TransactionID: _1TxnID,
   155  			StatementID:   _1TxnID,
   156  			Status:        StatementStatusSuccess,
   157  			ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   158  			ConnType:      statistic.ConnTypeExternal,
   159  		})
   160  
   161  		if err != nil {
   162  			t.Fatalf("Unexpected error when adding item: %v", err)
   163  		}
   164  
   165  		// Error status
   166  		_, err = aggregator.AddItem(&StatementInfo{
   167  			Account:       "MO",
   168  			User:          "moroot",
   169  			Database:      "system",
   170  			StatementType: "Select",
   171  			SqlSourceType: "external_sql",
   172  			SessionID:     sessionId2,
   173  			Statement:     "SELECT 11", // make it longer than 200ms to pass filter
   174  			ResponseAt:    fixedTime.Add(6 * time.Second),
   175  			RequestAt:     fixedTime.Add(6 * time.Second).Add(-10 * time.Millisecond),
   176  			Duration:      10 * time.Millisecond,
   177  			TransactionID: _1TxnID,
   178  			StatementID:   _1TxnID,
   179  			Status:        StatementStatusFailed,
   180  			ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   181  			ConnType:      statistic.ConnTypeExternal,
   182  		})
   183  		if err != nil {
   184  			t.Fatalf("Unexpected error when adding item: %v", err)
   185  		}
   186  	}
   187  
   188  	// Get results from aggregator
   189  	results = aggregator.GetResults()
   190  
   191  	// Test expected behavior
   192  	if len(results) != 4 {
   193  		t.Errorf("Expected 4 aggregated statements, got %d", len(results))
   194  	}
   195  	assert.Equal(t, 50*time.Millisecond, results[0].(*StatementInfo).Duration)
   196  	assert.Equal(t, 50*time.Millisecond, results[1].(*StatementInfo).Duration)
   197  	assert.Equal(t, 50*time.Millisecond, results[2].(*StatementInfo).Duration)
   198  	assert.Equal(t, 50*time.Millisecond, results[3].(*StatementInfo).Duration)
   199  	for idx := 0; idx < 4; idx++ {
   200  	}
   201  	targetBytes := []byte(`[4,5,10.000,15,20,25,2,0,220.0803]`)
   202  	for idx := 0; idx < 4; idx++ {
   203  		require.Equal(t, targetBytes, results[idx].(*StatementInfo).GetStatsArrayBytes())
   204  	}
   205  	item, _ := results[0].(*StatementInfo)
   206  	row := item.GetTable().GetRow(ctx)
   207  	targetBytes = []byte(`[4,5,2.000,15,20,25,2,0,220.0803]`) // re-calculate memory usage in FillRow
   208  	for idx := 0; idx < 4; idx++ {
   209  		results[idx].(*StatementInfo).FillRow(ctx, row)
   210  		require.Equal(t, targetBytes, results[idx].(*StatementInfo).GetStatsArrayBytes())
   211  	}
   212  
   213  	aggregator.Close()
   214  
   215  	aggregator = NewAggregator(
   216  		ctx,
   217  		aggrWindow,
   218  		StatementInfoNew,
   219  		StatementInfoUpdate,
   220  		StatementInfoFilter,
   221  	)
   222  
   223  	// Update
   224  	for i := 0; i < 5; i++ {
   225  
   226  		_, err = aggregator.AddItem(&StatementInfo{
   227  			Account:       "MO",
   228  			User:          "moroot",
   229  			Database:      "system",
   230  			StatementType: "Update",
   231  			SqlSourceType: "external_sql",
   232  			SessionID:     sessionId2,
   233  			Statement:     "Update 11",
   234  			ResponseAt:    fixedTime.Add(6 * time.Second),
   235  			RequestAt:     fixedTime.Add(6 * time.Second).Add(-10 * time.Millisecond),
   236  			Duration:      time.Duration(10+i) * time.Millisecond,
   237  			TransactionID: _1TxnID,
   238  			StatementID:   _1TxnID,
   239  			Status:        StatementStatusFailed,
   240  			ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   241  		})
   242  		if err != nil {
   243  			t.Fatalf("Unexpected error when adding item: %v", err)
   244  		}
   245  
   246  		_, err = aggregator.AddItem(&StatementInfo{
   247  			Account:       "MO",
   248  			User:          "moroot",
   249  			Database:      "system",
   250  			StatementType: "Update",
   251  			SqlSourceType: "internal_sql",
   252  			SessionID:     sessionId2,
   253  			Statement:     "Update 11",
   254  			ResponseAt:    fixedTime.Add(6 * time.Second),
   255  			RequestAt:     fixedTime.Add(6 * time.Second).Add(-10 * time.Millisecond),
   256  			Duration:      time.Duration(10+i) * time.Millisecond,
   257  			TransactionID: _1TxnID,
   258  			StatementID:   _1TxnID,
   259  			Status:        StatementStatusFailed,
   260  			ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   261  		})
   262  		if err != nil {
   263  			t.Fatalf("Unexpected error when adding item: %v", err)
   264  		}
   265  	}
   266  	results = aggregator.GetResults()
   267  
   268  	assert.Equal(t, "Update 11", results[0].(*StatementInfo).StmtBuilder.String())
   269  	// should have two results since they have different sqlSourceType
   270  	assert.Equal(t, "Update 11", results[1].(*StatementInfo).StmtBuilder.String())
   271  	assert.Equal(t, 60*time.Millisecond, results[1].(*StatementInfo).Duration)
   272  	// RequestAt should be starting of the window
   273  	assert.Equal(t, fixedTime.Add(4*time.Second), results[0].(*StatementInfo).RequestAt)
   274  	// ResponseAt should be end of the window
   275  	assert.Equal(t, fixedTime.Add(9*time.Second), results[0].(*StatementInfo).ResponseAt)
   276  	require.Equal(t, []byte(`[4,5,10.000,15,20,25,0,0,220.0803]`), results[0].(*StatementInfo).GetStatsArrayBytes())
   277  	results[0].(*StatementInfo).FillRow(ctx, row) // re-calculate memory usage in FillRow
   278  	require.Equal(t, []byte(`[4,5,2.000,15,20,25,0,0,220.0803]`), results[0].(*StatementInfo).GetStatsArrayBytes())
   279  
   280  	_, err = aggregator.AddItem(&StatementInfo{
   281  		Account:       "MO",
   282  		User:          "moroot",
   283  		Database:      "system",
   284  		StatementType: "Update",
   285  		SqlSourceType: "external_sql",
   286  		SessionID:     sessionId2,
   287  		Statement:     "Update 11",
   288  		ResponseAt:    fixedTime.Add(6 * time.Second),
   289  		RequestAt:     fixedTime.Add(6 * time.Second).Add(-10 * time.Millisecond),
   290  		Duration:      203 * time.Millisecond,
   291  		TransactionID: _1TxnID,
   292  		StatementID:   _1TxnID,
   293  		Status:        StatementStatusFailed,
   294  		ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   295  	})
   296  	if err != ErrFilteredOut {
   297  		t.Fatalf("Expecting filter out error due to Duration longer than 200ms: %v", err)
   298  	}
   299  
   300  }
   301  
   302  func TestAggregatorWithStmtMerge(t *testing.T) {
   303  	c := GetTracerProvider()
   304  	c.enableStmtMerge = true
   305  
   306  	var sessionId [16]byte
   307  	sessionId[0] = 1
   308  	var sessionId2 [16]byte
   309  	sessionId2[0] = 2
   310  	const aggrWindow = 5 * time.Second
   311  
   312  	ctx := context.Background()
   313  	aggregator := NewAggregator(
   314  		ctx,
   315  		aggrWindow,
   316  		StatementInfoNew,
   317  		StatementInfoUpdate,
   318  		StatementInfoFilter,
   319  	)
   320  	var err error
   321  
   322  	fixedTime := time.Date(2023, time.June, 10, 12, 0, 1, 0, time.UTC)
   323  	for i := 0; i < 2; i++ {
   324  		_, err = aggregator.AddItem(&StatementInfo{
   325  			Account:       "MO",
   326  			User:          "moroot",
   327  			Database:      "system",
   328  			StatementType: "Select",
   329  			SqlSourceType: "external_sql",
   330  			SessionID:     sessionId,
   331  			Statement:     "SELECT 11",
   332  			ResponseAt:    fixedTime,
   333  			RequestAt:     fixedTime.Add(-10 * time.Millisecond),
   334  			Duration:      10 * time.Millisecond,
   335  			RowsRead:      1,
   336  			TransactionID: _1TxnID,
   337  			StatementID:   _1TxnID,
   338  			Status:        StatementStatusSuccess,
   339  			ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   340  		})
   341  		if err != nil {
   342  			t.Fatalf("Unexpected error when adding item: %v", err)
   343  		}
   344  	}
   345  
   346  	// Get results from aggregator
   347  	results := aggregator.GetResults()
   348  
   349  	// Test expected behavior
   350  	if len(results) != 1 {
   351  		t.Errorf("Expected 0 aggregated statements, got %d", len(results))
   352  	}
   353  
   354  	assert.Equal(t, "SELECT 11;\nSELECT 11", results[0].(*StatementInfo).StmtBuilder.String())
   355  
   356  	res := "/* " + strconv.FormatInt(results[0].(*StatementInfo).AggrCount, 10) + " queries */ \n" + results[0].(*StatementInfo).StmtBuilder.String()
   357  
   358  	assert.Equal(t, "/* 2 queries */ \nSELECT 11;\nSELECT 11", res)
   359  
   360  	assert.Equal(t, int64(2), results[0].(*StatementInfo).RowsRead)
   361  
   362  }
   363  
   364  func TestAggregator_MarkExported(t *testing.T) {
   365  	type fields struct {
   366  		elems int
   367  	}
   368  	tests := []struct {
   369  		name   string
   370  		fields fields
   371  		//want   []Item
   372  	}{
   373  		{
   374  			name:   "normal",
   375  			fields: fields{elems: 5},
   376  		},
   377  		{
   378  			name:   "normal_100",
   379  			fields: fields{elems: 100},
   380  		},
   381  	}
   382  
   383  	const aggrWindow = 5 * time.Second
   384  
   385  	var err error
   386  	var sessionId = [16]byte{1}
   387  	var ctx = context.TODO()
   388  	// Aggregate some Select
   389  	var fixedTime = time.Date(2023, time.June, 10, 12, 0, 1, 0, time.UTC)
   390  
   391  	for _, tt := range tests {
   392  		t.Run(tt.name, func(t *testing.T) {
   393  
   394  			aggregator := NewAggregator(
   395  				ctx,
   396  				aggrWindow,
   397  				StatementInfoNew,
   398  				StatementInfoUpdate,
   399  				StatementInfoFilter,
   400  			)
   401  
   402  			var stmts []*StatementInfo
   403  			for i := 0; i < tt.fields.elems; i++ {
   404  				stmt := &StatementInfo{
   405  					Account:       "MO",
   406  					User:          "moroot",
   407  					Database:      "system",
   408  					StatementType: "Select",
   409  					SqlSourceType: "external_sql",
   410  					SessionID:     sessionId,
   411  					Statement:     "SELECT 11",
   412  					ResponseAt:    fixedTime,
   413  					RequestAt:     fixedTime.Add(-10 * time.Millisecond),
   414  					Duration:      10 * time.Millisecond,
   415  					TransactionID: _1TxnID,
   416  					StatementID:   _1TxnID,
   417  					Status:        StatementStatusSuccess,
   418  					ExecPlan:      NewDummySerializableExecPlan(map[string]string{"key": "val"}, dummySerializeExecPlan, uuid.UUID(_2TraceID)),
   419  				}
   420  				stmts = append(stmts, stmt)
   421  				_, err = aggregator.AddItem(stmt)
   422  				if err != nil {
   423  					t.Fatalf("Unexpected error when adding item: %v", err)
   424  				}
   425  			}
   426  
   427  			// Get results from aggregator
   428  			// Check all records' exported value.
   429  			results := aggregator.GetResults()
   430  			require.Equal(t, 1, len(results))
   431  			require.Equal(t, false, results[0].(*StatementInfo).exported)
   432  			for i := 1; i < tt.fields.elems; i++ {
   433  				require.Equal(t, true, stmts[i].exported)
   434  			}
   435  		})
   436  	}
   437  }