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 }