trpc.group/trpc-go/trpc-go@v1.0.3/config_test.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 package trpc 15 16 import ( 17 "os" 18 "strconv" 19 "strings" 20 "testing" 21 "time" 22 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 yaml "gopkg.in/yaml.v3" 26 27 "trpc.group/trpc-go/trpc-go/errs" 28 "trpc.group/trpc-go/trpc-go/rpcz" 29 ) 30 31 // TestLoadGlobalConfigNICError tests LoadGlobalConfig error. 32 func TestLoadGlobalConfigNICError(t *testing.T) { 33 err := LoadGlobalConfig("testdata/trpc_go_error.yaml") 34 assert.NotNil(t, err) 35 } 36 37 // TestRepairServiceIPWithNicAdminError tests repairServiceIPWithNic for admin error. 38 func TestRepairServiceIPWithNicAdminError(t *testing.T) { 39 conf := &Config{} 40 conf.Server.Admin.IP = "" 41 conf.Server.Admin.Nic = "ethNoneExist" 42 err := repairServiceIPWithNic(conf) 43 assert.Contains(t, err.Error(), "can't find admin IP by the NIC") 44 45 } 46 47 func TestParseEnv(t *testing.T) { 48 filePath := "./trpc_go.yaml" 49 content := ` 50 global: 51 namespace: development 52 env_name: ${test} 53 container_name: ${container_name} 54 local_ip: $local_ip 55 server: 56 app: ${} 57 server: ${server 58 client: 59 timeout: ${client_timeout} 60 ` 61 err := os.WriteFile(filePath, []byte(content), 0644) 62 if err != nil { 63 t.Errorf("write file err: %v", err) 64 return 65 } 66 defer func() { 67 _ = os.Remove(filePath) 68 }() 69 70 containerName := `这是容器名称,this is container name.` 71 _ = os.Setenv("container_name", containerName) 72 localIP := `127.1.2.3` 73 _ = os.Setenv("local_ip", localIP) 74 timeout := 456 75 _ = os.Setenv("client_timeout", strconv.FormatInt(int64(timeout), 10)) 76 77 c, err := parseConfigFromFile(filePath) 78 if err != nil { 79 t.Errorf("parse err: %v", err) 80 return 81 } 82 assert.Equal(t, c.Global.Namespace, "development") 83 assert.Equal(t, c.Global.EnvName, "") // env name not set, should be replaced with empty value 84 assert.Equal(t, c.Global.ContainerName, containerName) 85 assert.Equal(t, c.Global.LocalIP, "$local_ip") // only ${var} instead of $var is valid 86 assert.Equal(t, c.Server.App, "") // empty ${} should be deleted 87 assert.Equal(t, c.Server.Server, "${server") // only ${var} is valid 88 assert.Equal(t, c.Client.Timeout, timeout) 89 } 90 91 func TestParseEnvSpecialChar(t *testing.T) { 92 filePath := "./trpc_go.yaml" 93 content := ` 94 global: 95 namespace: development 96 env_name: test 97 container_name: ${container_name} 98 local_ip: ${local_ip} 99 ` 100 err := os.WriteFile(filePath, []byte(content), 0644) 101 if err != nil { 102 t.Errorf("write file err: %v", err) 103 return 104 } 105 defer func() { 106 _ = os.Remove(filePath) 107 }() 108 109 containerName := `'这是"容器名称": this is container name. !@#$%^&*()_+-='` 110 _ = os.Setenv("container_name", containerName) 111 actualContainerName := strings.Trim(containerName, `'`) // single quotes 112 localIP := `"'127.1.2.3'"` 113 _ = os.Setenv("local_ip", localIP) 114 actualLocalIP := strings.Trim(localIP, `"`) // double quotes 115 116 c, err := parseConfigFromFile(filePath) 117 if err != nil { 118 t.Errorf("parse err: %v", err) 119 return 120 } 121 assert.Equal(t, c.Global.Namespace, "development") 122 assert.Equal(t, c.Global.EnvName, "test") 123 assert.Equal(t, c.Global.ContainerName, actualContainerName) 124 assert.Equal(t, c.Global.LocalIP, actualLocalIP) 125 } 126 127 func Test_serverConfigPath(t *testing.T) { 128 oldServerConfigPath := ServerConfigPath 129 ServerConfigPath = "./testdata/trpc_go.yaml" 130 path := serverConfigPath() 131 assert.Equal(t, "./testdata/trpc_go.yaml", path) 132 133 ServerConfigPath = "./trpc_go.yaml" 134 path = serverConfigPath() 135 assert.Equal(t, defaultConfigPath, path) 136 137 ServerConfigPath = oldServerConfigPath 138 } 139 140 func Test_setDefault(t *testing.T) { 141 var ( 142 dstEmpty string 143 dstNotEmpty = "not-empty" 144 def = "default" 145 ) 146 setDefault(&dstEmpty, def) 147 setDefault(&dstNotEmpty, def) 148 assert.Equal(t, dstEmpty, def) 149 assert.NotEqual(t, dstNotEmpty, def) 150 } 151 152 func TestConfigTransport(t *testing.T) { 153 t.Run("Server Config", func(t *testing.T) { 154 var cfg Config 155 require.Nil(t, yaml.Unmarshal([]byte(` 156 server: 157 transport: test-transport 158 `), &cfg)) 159 require.Equal(t, "test-transport", cfg.Server.Transport) 160 }) 161 t.Run("Service Config", func(t *testing.T) { 162 var cfg ServiceConfig 163 require.Nil(t, yaml.Unmarshal([]byte(` 164 transport: test-transport 165 `), &cfg)) 166 require.Equal(t, "test-transport", cfg.Transport) 167 }) 168 t.Run("Client Config", func(t *testing.T) { 169 var cfg ClientConfig 170 require.Nil(t, yaml.Unmarshal([]byte(` 171 transport: test-transport 172 `), &cfg)) 173 require.Equal(t, "test-transport", cfg.Transport) 174 }) 175 } 176 func TestConfigStreamFilter(t *testing.T) { 177 filterName := "sf1" 178 t.Run("server config", func(t *testing.T) { 179 var cfg Config 180 require.Nil(t, yaml.Unmarshal([]byte(` 181 server: 182 stream_filter: 183 - sf1 184 `), &cfg)) 185 require.Equal(t, filterName, cfg.Server.StreamFilter[0]) 186 }) 187 t.Run("service config", func(t *testing.T) { 188 var cfg ServiceConfig 189 require.Nil(t, yaml.Unmarshal([]byte(` 190 stream_filter: 191 - sf1 192 `), &cfg)) 193 require.Equal(t, filterName, cfg.StreamFilter[0]) 194 }) 195 t.Run("client config", func(t *testing.T) { 196 var cfg ClientConfig 197 require.Nil(t, yaml.Unmarshal([]byte(` 198 stream_filter: 199 - sf1 200 `), &cfg)) 201 require.Equal(t, filterName, cfg.StreamFilter[0]) 202 }) 203 204 } 205 206 func TestRecordWhen(t *testing.T) { 207 t.Run("empty record-when", func(t *testing.T) { 208 config := &RPCZConfig{} 209 require.Nil(t, yaml.Unmarshal( 210 []byte(` 211 fraction: 1.0 212 capacity: 10`), 213 config, 214 )) 215 r := rpcz.NewRPCZ(config.generate()) 216 var ids []rpcz.SpanID 217 for i := 0; i < 10; i++ { 218 s, ender := r.NewChild("") 219 ids = append(ids, s.ID()) 220 ender.End() 221 } 222 for _, id := range ids { 223 _, ok := r.Query(id) 224 require.True(t, ok) 225 } 226 }) 227 t.Run("unknown node", func(t *testing.T) { 228 config := &RecordWhenConfig{} 229 err := yaml.Unmarshal( 230 []byte(` 231 - XOR: 232 - __min_request_size: 30 233 - __min_response_size: 40 234 `), 235 config, 236 ) 237 require.Contains(t, errs.Msg(err), "unknown node: XOR") 238 }) 239 t.Run("AND node is map type", func(t *testing.T) { 240 config := &RecordWhenConfig{} 241 err := yaml.Unmarshal( 242 []byte(` 243 - AND: {__rpc_name: "/trpc.app.server.service/method"} 244 `), 245 config, 246 ) 247 require.Contains(t, errs.Msg(err), "cannot unmarshal !!map into []map[trpc.nodeKind]yaml.Node") 248 }) 249 t.Run("OR node is map type", func(t *testing.T) { 250 config := &RecordWhenConfig{} 251 err := yaml.Unmarshal( 252 []byte(` 253 - OR: {__rpc_name: "/trpc.app.server.service/method"} 254 `), 255 config, 256 ) 257 require.Contains(t, errs.Msg(err), "cannot unmarshal !!map into []map[trpc.nodeKind]yaml.Node") 258 }) 259 260 } 261 func TestRecordWhen_NotNode(t *testing.T) { 262 t.Run("NOT node is empty", func(t *testing.T) { 263 config := &RPCZConfig{} 264 err := yaml.Unmarshal([]byte(` 265 record_when: 266 - NOT: 267 `), 268 config, 269 ) 270 require.ErrorContains(t, err, "value is empty") 271 }) 272 t.Run("NOT node has two children", func(t *testing.T) { 273 config := &RecordWhenConfig{} 274 err := yaml.Unmarshal( 275 []byte(` 276 - NOT: {__rpc_name: "/trpc.app.server.service/method", __min_duration: 1000ms} 277 `), 278 config, 279 ) 280 require.Contains(t, errs.Msg(err), "the valid number of child node can only be 1") 281 }) 282 t.Run("NOT has a leaf child", func(t *testing.T) { 283 config := &RecordWhenConfig{} 284 require.Nil(t, yaml.Unmarshal( 285 []byte(` 286 - NOT: 287 __rpc_name: "/trpc.app.server.service/method" 288 `), 289 config, 290 )) 291 }) 292 t.Run("NOT has a internal child", func(t *testing.T) { 293 config := &RecordWhenConfig{} 294 require.Nil(t, yaml.Unmarshal( 295 []byte(` 296 - NOT: 297 OR: 298 - __min_duration: 1000ms 299 - __rpc_name: "/trpc.app.server.service/method" 300 `), 301 config, 302 )) 303 }) 304 t.Run("NOT node is slice type", func(t *testing.T) { 305 config := &RecordWhenConfig{} 306 err := yaml.Unmarshal( 307 []byte(` 308 - NOT: 309 - __rpc_name: "/trpc.app.server.service/method" 310 `), 311 config, 312 ) 313 require.Contains(t, errs.Msg(err), "cannot unmarshal !!seq into map[trpc.nodeKind]yaml.Node") 314 }) 315 } 316 func TestRecordWhen_ANDNode(t *testing.T) { 317 t.Run("AND node is empty", func(t *testing.T) { 318 config := &RPCZConfig{} 319 err := yaml.Unmarshal([]byte(` 320 record_when: 321 - AND: 322 `), 323 config, 324 ) 325 require.ErrorContains(t, err, "value is empty") 326 }) 327 t.Run("AND node has two children", func(t *testing.T) { 328 config := &RecordWhenConfig{} 329 require.Nil(t, yaml.Unmarshal( 330 []byte(` 331 - AND: 332 - __rpc_name: "/trpc.app.server.service/method" 333 - __min_duration: 1000ms 334 `), 335 config, 336 )) 337 }) 338 t.Run("AND has a leaf child", func(t *testing.T) { 339 config := &RecordWhenConfig{} 340 require.Nil(t, yaml.Unmarshal( 341 []byte(` 342 - AND: 343 - __rpc_name: "/trpc.app.server.service/method" 344 `), 345 config, 346 )) 347 }) 348 t.Run("AND has a internal child", func(t *testing.T) { 349 config := &RecordWhenConfig{} 350 require.Nil(t, yaml.Unmarshal( 351 []byte(` 352 - AND: 353 - OR: 354 - __min_duration: 1000ms 355 - __rpc_name: "/trpc.app.server.service/method" 356 `), 357 config, 358 )) 359 }) 360 t.Run("AND node is map type", func(t *testing.T) { 361 config := &RecordWhenConfig{} 362 err := yaml.Unmarshal( 363 []byte(` 364 - AND: 365 __rpc_name: "/trpc.app.server.service/method" 366 `), 367 config, 368 ) 369 require.Contains(t, errs.Msg(err), "cannot unmarshal !!map into []map[trpc.nodeKind]yaml.Node") 370 }) 371 } 372 func TestRPCZ_RecordWhen_ErrorCode(t *testing.T) { 373 config := &RPCZConfig{} 374 mustYamlUnmarshal(t, []byte(` 375 fraction: 1.0 376 capacity: 10 377 record_when: 378 - __sampling_fraction: 1 379 - OR: 380 - __error_code: 1 # RetServerDecodeFail = 1 381 - __error_code: 2 # RetServerEncodeFail = 2 382 - __error_message: "service codec" 383 - __error_message: "client codec" 384 - NOT: 385 OR: 386 - __error_code: 1 387 - __error_message: "service codec" 388 `), config) 389 390 r := rpcz.NewRPCZ(config.generate()) 391 var ( 392 expectedIDs []rpcz.SpanID 393 unexpectedIDs []rpcz.SpanID 394 ) 395 { 396 s, ender := r.NewChild("") 397 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetServerDecodeFail, "service codec")) 398 unexpectedIDs = append(unexpectedIDs, s.ID()) 399 ender.End() 400 } 401 { 402 s, ender := r.NewChild("") 403 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetServerEncodeFail, "service codec")) 404 unexpectedIDs = append(unexpectedIDs, s.ID()) 405 ender.End() 406 } 407 { 408 s, ender := r.NewChild("") 409 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetServerDecodeFail, "client codec")) 410 unexpectedIDs = append(unexpectedIDs, s.ID()) 411 ender.End() 412 } 413 { 414 s, ender := r.NewChild("") 415 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetServerEncodeFail, "client codec")) 416 expectedIDs = append(expectedIDs, s.ID()) 417 ender.End() 418 } 419 for i, id := range expectedIDs { 420 _, ok := r.Query(id) 421 require.True(t, ok, i) 422 } 423 for i, id := range unexpectedIDs { 424 _, ok := r.Query(id) 425 require.False(t, ok, i) 426 } 427 } 428 func TestRPC_RecordWhen_CustomAttribute(t *testing.T) { 429 config := &RPCZConfig{} 430 mustYamlUnmarshal(t, []byte(` 431 fraction: 1.0 432 capacity: 10 433 record_when: 434 - __sampling_fraction: 1 435 - OR: 436 - __has_attribute: (race, elf) 437 - __has_attribute: (class, wizard) 438 - NOT: 439 OR: 440 - __has_attribute: (race, dwarf) 441 - __has_attribute: (class, warlock) 442 `), config) 443 444 r := rpcz.NewRPCZ(config.generate()) 445 var ( 446 expectedIDs []rpcz.SpanID 447 unexpectedIDs []rpcz.SpanID 448 ) 449 { 450 s, ender := r.NewChild("") 451 s.SetAttribute("race", "elf") 452 s.SetAttribute("class", "wizard") 453 expectedIDs = append(expectedIDs, s.ID()) 454 ender.End() 455 } 456 { 457 s, ender := r.NewChild("") 458 s.SetAttribute("race", "elf") 459 s.SetAttribute("class", "wizard, warlock") 460 unexpectedIDs = append(unexpectedIDs, s.ID()) 461 ender.End() 462 } 463 { 464 s, ender := r.NewChild("") 465 s.SetAttribute("race", "elf, dwarf") 466 s.SetAttribute("class", "wizard") 467 unexpectedIDs = append(unexpectedIDs, s.ID()) 468 ender.End() 469 } 470 { 471 s, ender := r.NewChild("") 472 s.SetAttribute("race", "elf, dwarf") 473 s.SetAttribute("class", "wizard, warlock") 474 unexpectedIDs = append(unexpectedIDs, s.ID()) 475 ender.End() 476 } 477 for i, id := range expectedIDs { 478 _, ok := r.Query(id) 479 require.True(t, ok, i) 480 } 481 for i, id := range unexpectedIDs { 482 _, ok := r.Query(id) 483 require.False(t, ok, i) 484 } 485 } 486 func TestRPC_RecordWhen_InvalidCustomAttribute(t *testing.T) { 487 t.Run("miss left parenthesis", func(t *testing.T) { 488 config := &RPCZConfig{} 489 require.ErrorContains(t, yaml.Unmarshal([]byte(` 490 record_when: 491 - __has_attribute: race, elf) 492 `), config), "invalid attribute form") 493 }) 494 t.Run("miss right parenthesis", func(t *testing.T) { 495 config := &RPCZConfig{} 496 require.ErrorContains(t, yaml.Unmarshal([]byte(` 497 record_when: 498 - __has_attribute: (race, elf 499 `), config), "invalid attribute form") 500 }) 501 t.Run("middle delimiter space", func(t *testing.T) { 502 config := &RPCZConfig{} 503 require.ErrorContains(t, yaml.Unmarshal([]byte(` 504 record_when: 505 - __has_attribute: (race,elf) 506 `), config), "invalid attribute form") 507 }) 508 t.Run("middle delimiter comma", func(t *testing.T) { 509 config := &RPCZConfig{} 510 require.ErrorContains(t, yaml.Unmarshal([]byte(` 511 record_when: 512 - __has_attribute: (race elf) 513 `), config), "invalid attribute form") 514 }) 515 } 516 func TestRPCZ_RecordWhen_MinDuration(t *testing.T) { 517 t.Run("not empty", func(t *testing.T) { 518 config := &RPCZConfig{} 519 mustYamlUnmarshal(t, []byte(` 520 fraction: 1.0 521 capacity: 10 522 record_when: 523 - __error_code: 999 # RetUnknown = 0 524 - __min_duration: 100ms 525 - __sampling_fraction: 1 526 `), config) 527 528 r := rpcz.NewRPCZ(config.generate()) 529 var ( 530 expectedIDs []rpcz.SpanID 531 unexpectedIDs []rpcz.SpanID 532 ) 533 { 534 s, ender := r.NewChild("") 535 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetUnknown, "")) 536 // mimic some time-consuming operation. 537 time.Sleep(1 * time.Second) 538 expectedIDs = append(expectedIDs, s.ID()) 539 ender.End() 540 } 541 { 542 s, ender := r.NewChild("") 543 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetUnknown, "")) 544 // mimic some time-consuming operation. 545 time.Sleep(2 * time.Second) 546 expectedIDs = append(expectedIDs, s.ID()) 547 ender.End() 548 } 549 { 550 // don't call ender.End() 551 s, _ := r.NewChild("") 552 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetOK, "")) 553 unexpectedIDs = append(unexpectedIDs, s.ID()) 554 } 555 { 556 s, ender := r.NewChild("") 557 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetUnknown, "")) 558 // mimic some time-consuming operation. 559 time.Sleep(1 * time.Millisecond) 560 unexpectedIDs = append(unexpectedIDs, s.ID()) 561 ender.End() 562 } 563 { 564 s, ender := r.NewChild("") 565 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetUnknown, "")) 566 // mimic some time-consuming operation. 567 time.Sleep(2 * time.Millisecond) 568 unexpectedIDs = append(unexpectedIDs, s.ID()) 569 ender.End() 570 } 571 for _, id := range expectedIDs { 572 _, ok := r.Query(id) 573 require.True(t, ok) 574 } 575 for _, id := range unexpectedIDs { 576 _, ok := r.Query(id) 577 require.False(t, ok) 578 } 579 }) 580 t.Run("empty", func(t *testing.T) { 581 config := &RPCZConfig{} 582 mustYamlUnmarshal(t, []byte(` 583 fraction: 1.0 584 capacity: 10 585 record_when: 586 - __error_code: 0 # RetOK = 0 587 - __sampling_fraction: 1 588 `), config) 589 590 r := rpcz.NewRPCZ(config.generate()) 591 var ( 592 unexpectedID rpcz.SpanID 593 expectedID rpcz.SpanID 594 ) 595 { 596 s, ender := r.NewChild("") 597 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetUnknown, "")) 598 // mimic some time-consuming operation. 599 time.Sleep(1 * time.Millisecond) 600 unexpectedID = s.ID() 601 ender.End() 602 } 603 { 604 s, ender := r.NewChild("") 605 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetOK, "")) 606 // mimic some time-consuming operation. 607 time.Sleep(1 * time.Millisecond) 608 expectedID = s.ID() 609 ender.End() 610 } 611 _, ok := r.Query(unexpectedID) 612 require.False(t, ok) 613 614 _, ok = r.Query(expectedID) 615 require.True(t, ok) 616 }) 617 } 618 func TestRPCZ_RecordWhen_MinRequestSize(t *testing.T) { 619 config := &RPCZConfig{} 620 mustYamlUnmarshal(t, []byte(` 621 fraction: 1.0 622 capacity: 10 623 record_when: 624 - __sampling_fraction: 1 625 - __min_request_size: 30 626 `), config) 627 628 r := rpcz.NewRPCZ(config.generate()) 629 t.Run("unset request size", func(t *testing.T) { 630 s, ender := r.NewChild("") 631 unexpectedID := s.ID() 632 ender.End() 633 _, ok := r.Query(unexpectedID) 634 require.False(t, ok) 635 }) 636 t.Run("request size less than min_request_size", func(t *testing.T) { 637 s, ender := r.NewChild("") 638 s.SetAttribute(rpcz.TRPCAttributeRequestSize, 29) 639 unexpectedID := s.ID() 640 ender.End() 641 _, ok := r.Query(unexpectedID) 642 require.False(t, ok) 643 }) 644 t.Run("request size equals to min_request_size", func(t *testing.T) { 645 s, ender := r.NewChild("") 646 s.SetAttribute(rpcz.TRPCAttributeRequestSize, 30) 647 expectedID := s.ID() 648 ender.End() 649 _, ok := r.Query(expectedID) 650 require.True(t, ok) 651 }) 652 t.Run("request size greater than min_request_size", func(t *testing.T) { 653 s, ender := r.NewChild("") 654 s.SetAttribute(rpcz.TRPCAttributeRequestSize, 31) 655 expectedID := s.ID() 656 ender.End() 657 _, ok := r.Query(expectedID) 658 require.True(t, ok) 659 }) 660 } 661 func TestRPCZ_RecordWhen_MinResponseSize(t *testing.T) { 662 config := &RPCZConfig{} 663 mustYamlUnmarshal(t, []byte(` 664 fraction: 1.0 665 capacity: 10 666 record_when: 667 - __sampling_fraction: 1 668 - __min_response_size: 40 669 `), config) 670 671 r := rpcz.NewRPCZ(config.generate()) 672 t.Run("unset response size", func(t *testing.T) { 673 s, ender := r.NewChild("") 674 unexpectedID := s.ID() 675 ender.End() 676 _, ok := r.Query(unexpectedID) 677 require.False(t, ok) 678 }) 679 t.Run("request size less than min_response_size", func(t *testing.T) { 680 s, ender := r.NewChild("") 681 s.SetAttribute(rpcz.TRPCAttributeResponseSize, 39) 682 unexpectedID := s.ID() 683 ender.End() 684 _, ok := r.Query(unexpectedID) 685 require.False(t, ok) 686 }) 687 t.Run("request size equals to min_response_size", func(t *testing.T) { 688 s, ender := r.NewChild("") 689 s.SetAttribute(rpcz.TRPCAttributeResponseSize, 40) 690 expectedID := s.ID() 691 ender.End() 692 _, ok := r.Query(expectedID) 693 require.True(t, ok) 694 }) 695 t.Run("request size greater than min_response_size", func(t *testing.T) { 696 s, ender := r.NewChild("") 697 s.SetAttribute(rpcz.TRPCAttributeResponseSize, 41) 698 expectedID := s.ID() 699 ender.End() 700 _, ok := r.Query(expectedID) 701 require.True(t, ok) 702 }) 703 } 704 func TestRPCZ_RecordWhen_RPCName(t *testing.T) { 705 config := &RPCZConfig{} 706 mustYamlUnmarshal(t, []byte(` 707 fraction: 1.0 708 capacity: 10 709 record_when: 710 - __sampling_fraction: 1 711 - __rpc_name: trpc.app.server.service 712 `), config) 713 714 r := rpcz.NewRPCZ(config.generate()) 715 t.Run("unset RPCName", func(t *testing.T) { 716 s, ender := r.NewChild("") 717 unexpectedID := s.ID() 718 ender.End() 719 _, ok := r.Query(unexpectedID) 720 require.False(t, ok) 721 }) 722 t.Run("RPCName does not contain rpc_name", func(t *testing.T) { 723 s, ender := r.NewChild("") 724 s.SetAttribute(rpcz.TRPCAttributeRPCName, "/xxx.app.server.service/method") 725 unexpectedID := s.ID() 726 ender.End() 727 _, ok := r.Query(unexpectedID) 728 require.False(t, ok) 729 }) 730 t.Run("RPCName contains rpc_name", func(t *testing.T) { 731 s, ender := r.NewChild("") 732 s.SetAttribute(rpcz.TRPCAttributeRPCName, "/trpc.app.server.service/method") 733 expectedID := s.ID() 734 ender.End() 735 _, ok := r.Query(expectedID) 736 require.True(t, ok) 737 }) 738 } 739 func TestRPCZ_RecordWhen_ErrorCodeAndMinDuration(t *testing.T) { 740 config := &RPCZConfig{} 741 mustYamlUnmarshal(t, []byte(` 742 fraction: 1.0 743 capacity: 10 744 record_when: 745 - AND: 746 - __error_code: 0 # RetOK = 0 747 - __min_duration: 100ms 748 - __sampling_fraction: 1 749 `), config) 750 751 r := rpcz.NewRPCZ(config.generate()) 752 var ( 753 expectedIDs []rpcz.SpanID 754 unexpectedIDs []rpcz.SpanID 755 ) 756 { 757 s, ender := r.NewChild("") 758 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetOK, "")) 759 // mimic some time-consuming operation. 760 time.Sleep(1 * time.Second) 761 expectedIDs = append(expectedIDs, s.ID()) 762 ender.End() 763 } 764 765 { 766 s, ender := r.NewChild("") 767 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetUnknown, "")) 768 // mimic some time-consuming operation. 769 time.Sleep(2 * time.Second) 770 unexpectedIDs = append(unexpectedIDs, s.ID()) 771 ender.End() 772 } 773 { 774 s, ender := r.NewChild("") 775 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetOK, "")) 776 // mimic some time-consuming operation. 777 time.Sleep(1 * time.Millisecond) 778 unexpectedIDs = append(unexpectedIDs, s.ID()) 779 ender.End() 780 } 781 { 782 s, ender := r.NewChild("") 783 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetUnknown, "")) 784 // mimic some time-consuming operation. 785 time.Sleep(2 * time.Millisecond) 786 unexpectedIDs = append(unexpectedIDs, s.ID()) 787 ender.End() 788 } 789 { 790 // don't call ender.End() 791 s, _ := r.NewChild("") 792 s.SetAttribute(rpcz.TRPCAttributeError, errs.NewFrameError(errs.RetOK, "")) 793 unexpectedIDs = append(unexpectedIDs, s.ID()) 794 } 795 for i, id := range expectedIDs { 796 _, ok := r.Query(id) 797 require.True(t, ok, i) 798 } 799 for i, id := range unexpectedIDs { 800 _, ok := r.Query(id) 801 require.False(t, ok, i) 802 } 803 } 804 805 func mustYamlUnmarshal(t *testing.T, in []byte, out interface{}) { 806 t.Helper() 807 if err := yaml.Unmarshal(in, out); err != nil { 808 t.Fatal(err) 809 } 810 } 811 func TestRepairServiceIdleTime(t *testing.T) { 812 t.Run("set by service timeout", func(t *testing.T) { 813 var cfg Config 814 require.Nil(t, yaml.Unmarshal([]byte(` 815 server: 816 service: 817 - name: trpc.test.helloworld.Greeter 818 ip: 127.0.0.1 819 port: 8000 820 network: tcp 821 protocol: trpc 822 timeout: 120000 823 `), &cfg)) 824 require.Nil(t, RepairConfig(&cfg)) 825 require.Equal(t, 120000, cfg.Server.Service[0].Idletime) 826 }) 827 t.Run("set by default", func(t *testing.T) { 828 var cfg Config 829 require.Nil(t, yaml.Unmarshal([]byte(` 830 server: 831 service: 832 - name: trpc.test.helloworld.Greeter 833 ip: 127.0.0.1 834 port: 8000 835 network: tcp 836 protocol: trpc 837 timeout: 500 838 `), &cfg)) 839 require.Nil(t, RepairConfig(&cfg)) 840 require.Equal(t, defaultIdleTimeout, cfg.Server.Service[0].Idletime) 841 }) 842 t.Run("set by config", func(t *testing.T) { 843 var cfg Config 844 require.Nil(t, yaml.Unmarshal([]byte(` 845 server: 846 service: 847 - name: trpc.test.helloworld.Greeter 848 ip: 127.0.0.1 849 port: 8000 850 network: tcp 851 protocol: trpc 852 timeout: 500 853 idletime: 1500 854 `), &cfg)) 855 require.Nil(t, RepairConfig(&cfg)) 856 require.Equal(t, 1500, cfg.Server.Service[0].Idletime) 857 }) 858 }