github.com/lulzWill/go-agent@v2.1.2+incompatible/internal_slow_queries_test.go (about) 1 package newrelic 2 3 import ( 4 "strings" 5 "testing" 6 "time" 7 8 "github.com/lulzWill/go-agent/internal" 9 "github.com/lulzWill/go-agent/internal/crossagent" 10 ) 11 12 func TestSlowQueryBasic(t *testing.T) { 13 cfgfn := func(cfg *Config) { 14 cfg.DatastoreTracer.SlowQuery.Threshold = 0 15 } 16 app := testApp(nil, cfgfn, t) 17 txn := app.StartTransaction("hello", nil, helloRequest) 18 s1 := DatastoreSegment{ 19 StartTime: StartSegmentNow(txn), 20 Product: DatastoreMySQL, 21 Collection: "users", 22 Operation: "INSERT", 23 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 24 } 25 s1.End() 26 txn.End() 27 28 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 29 Count: 1, 30 MetricName: "Datastore/statement/MySQL/users/INSERT", 31 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 32 TxnName: "WebTransaction/Go/hello", 33 TxnURL: "/hello", 34 DatabaseName: "", 35 Host: "", 36 PortPathOrID: "", 37 }}) 38 } 39 40 func TestSlowQueryLocallyDisabled(t *testing.T) { 41 cfgfn := func(cfg *Config) { 42 cfg.DatastoreTracer.SlowQuery.Threshold = 0 43 cfg.DatastoreTracer.SlowQuery.Enabled = false 44 } 45 app := testApp(nil, cfgfn, t) 46 txn := app.StartTransaction("hello", nil, helloRequest) 47 s1 := DatastoreSegment{ 48 StartTime: StartSegmentNow(txn), 49 Product: DatastoreMySQL, 50 Collection: "users", 51 Operation: "INSERT", 52 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 53 } 54 s1.End() 55 txn.End() 56 57 app.ExpectSlowQueries(t, []internal.WantSlowQuery{}) 58 } 59 60 func TestSlowQueryRemotelyDisabled(t *testing.T) { 61 cfgfn := func(cfg *Config) { 62 cfg.DatastoreTracer.SlowQuery.Threshold = 0 63 } 64 replyfn := func(reply *internal.ConnectReply) { 65 reply.CollectTraces = false 66 } 67 app := testApp(replyfn, cfgfn, t) 68 txn := app.StartTransaction("hello", nil, helloRequest) 69 s1 := DatastoreSegment{ 70 StartTime: StartSegmentNow(txn), 71 Product: DatastoreMySQL, 72 Collection: "users", 73 Operation: "INSERT", 74 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 75 } 76 s1.End() 77 txn.End() 78 79 app.ExpectSlowQueries(t, []internal.WantSlowQuery{}) 80 } 81 82 func TestSlowQueryBelowThreshold(t *testing.T) { 83 cfgfn := func(cfg *Config) { 84 cfg.DatastoreTracer.SlowQuery.Threshold = 1 * time.Hour 85 } 86 app := testApp(nil, cfgfn, t) 87 txn := app.StartTransaction("hello", nil, helloRequest) 88 s1 := DatastoreSegment{ 89 StartTime: StartSegmentNow(txn), 90 Product: DatastoreMySQL, 91 Collection: "users", 92 Operation: "INSERT", 93 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 94 } 95 s1.End() 96 txn.End() 97 98 app.ExpectSlowQueries(t, []internal.WantSlowQuery{}) 99 } 100 101 func TestSlowQueryDatabaseProvided(t *testing.T) { 102 cfgfn := func(cfg *Config) { 103 cfg.DatastoreTracer.SlowQuery.Threshold = 0 104 } 105 app := testApp(nil, cfgfn, t) 106 txn := app.StartTransaction("hello", nil, helloRequest) 107 s1 := DatastoreSegment{ 108 StartTime: StartSegmentNow(txn), 109 Product: DatastoreMySQL, 110 Collection: "users", 111 Operation: "INSERT", 112 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 113 DatabaseName: "my_database", 114 } 115 s1.End() 116 txn.End() 117 118 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 119 Count: 1, 120 MetricName: "Datastore/statement/MySQL/users/INSERT", 121 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 122 TxnName: "WebTransaction/Go/hello", 123 TxnURL: "/hello", 124 DatabaseName: "my_database", 125 Host: "", 126 PortPathOrID: "", 127 }}) 128 } 129 130 func TestSlowQueryHostProvided(t *testing.T) { 131 cfgfn := func(cfg *Config) { 132 cfg.DatastoreTracer.SlowQuery.Threshold = 0 133 } 134 app := testApp(nil, cfgfn, t) 135 txn := app.StartTransaction("hello", nil, helloRequest) 136 s1 := DatastoreSegment{ 137 StartTime: StartSegmentNow(txn), 138 Product: DatastoreMySQL, 139 Collection: "users", 140 Operation: "INSERT", 141 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 142 Host: "db-server-1", 143 } 144 s1.End() 145 txn.End() 146 147 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 148 Count: 1, 149 MetricName: "Datastore/statement/MySQL/users/INSERT", 150 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 151 TxnName: "WebTransaction/Go/hello", 152 TxnURL: "/hello", 153 DatabaseName: "", 154 Host: "db-server-1", 155 PortPathOrID: "unknown", 156 }}) 157 scope := "WebTransaction/Go/hello" 158 app.ExpectMetrics(t, append([]internal.WantMetric{ 159 {Name: "Datastore/all", Scope: "", Forced: true, Data: nil}, 160 {Name: "Datastore/allWeb", Scope: "", Forced: true, Data: nil}, 161 {Name: "Datastore/MySQL/all", Scope: "", Forced: true, Data: nil}, 162 {Name: "Datastore/MySQL/allWeb", Scope: "", Forced: true, Data: nil}, 163 {Name: "Datastore/operation/MySQL/INSERT", Scope: "", Forced: false, Data: nil}, 164 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: "", Forced: false, Data: nil}, 165 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: scope, Forced: false, Data: nil}, 166 {Name: "Datastore/instance/MySQL/db-server-1/unknown", Scope: "", Forced: false, Data: nil}, 167 }, webMetrics...)) 168 } 169 170 func TestSlowQueryPortProvided(t *testing.T) { 171 cfgfn := func(cfg *Config) { 172 cfg.DatastoreTracer.SlowQuery.Threshold = 0 173 } 174 app := testApp(nil, cfgfn, t) 175 txn := app.StartTransaction("hello", nil, helloRequest) 176 s1 := DatastoreSegment{ 177 StartTime: StartSegmentNow(txn), 178 Product: DatastoreMySQL, 179 Collection: "users", 180 Operation: "INSERT", 181 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 182 PortPathOrID: "98021", 183 } 184 s1.End() 185 txn.End() 186 187 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 188 Count: 1, 189 MetricName: "Datastore/statement/MySQL/users/INSERT", 190 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 191 TxnName: "WebTransaction/Go/hello", 192 TxnURL: "/hello", 193 DatabaseName: "", 194 Host: "unknown", 195 PortPathOrID: "98021", 196 }}) 197 scope := "WebTransaction/Go/hello" 198 app.ExpectMetrics(t, append([]internal.WantMetric{ 199 {Name: "Datastore/all", Scope: "", Forced: true, Data: nil}, 200 {Name: "Datastore/allWeb", Scope: "", Forced: true, Data: nil}, 201 {Name: "Datastore/MySQL/all", Scope: "", Forced: true, Data: nil}, 202 {Name: "Datastore/MySQL/allWeb", Scope: "", Forced: true, Data: nil}, 203 {Name: "Datastore/operation/MySQL/INSERT", Scope: "", Forced: false, Data: nil}, 204 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: "", Forced: false, Data: nil}, 205 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: scope, Forced: false, Data: nil}, 206 {Name: "Datastore/instance/MySQL/unknown/98021", Scope: "", Forced: false, Data: nil}, 207 }, webMetrics...)) 208 } 209 210 func TestSlowQueryHostPortProvided(t *testing.T) { 211 cfgfn := func(cfg *Config) { 212 cfg.DatastoreTracer.SlowQuery.Threshold = 0 213 } 214 app := testApp(nil, cfgfn, t) 215 txn := app.StartTransaction("hello", nil, helloRequest) 216 s1 := DatastoreSegment{ 217 StartTime: StartSegmentNow(txn), 218 Product: DatastoreMySQL, 219 Collection: "users", 220 Operation: "INSERT", 221 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 222 Host: "db-server-1", 223 PortPathOrID: "98021", 224 } 225 s1.End() 226 txn.End() 227 228 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 229 Count: 1, 230 MetricName: "Datastore/statement/MySQL/users/INSERT", 231 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 232 TxnName: "WebTransaction/Go/hello", 233 TxnURL: "/hello", 234 DatabaseName: "", 235 Host: "db-server-1", 236 PortPathOrID: "98021", 237 }}) 238 scope := "WebTransaction/Go/hello" 239 app.ExpectMetrics(t, append([]internal.WantMetric{ 240 {Name: "Datastore/all", Scope: "", Forced: true, Data: nil}, 241 {Name: "Datastore/allWeb", Scope: "", Forced: true, Data: nil}, 242 {Name: "Datastore/MySQL/all", Scope: "", Forced: true, Data: nil}, 243 {Name: "Datastore/MySQL/allWeb", Scope: "", Forced: true, Data: nil}, 244 {Name: "Datastore/operation/MySQL/INSERT", Scope: "", Forced: false, Data: nil}, 245 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: "", Forced: false, Data: nil}, 246 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: scope, Forced: false, Data: nil}, 247 {Name: "Datastore/instance/MySQL/db-server-1/98021", Scope: "", Forced: false, Data: nil}, 248 }, webMetrics...)) 249 } 250 251 func TestSlowQueryAggregation(t *testing.T) { 252 cfgfn := func(cfg *Config) { 253 cfg.DatastoreTracer.SlowQuery.Threshold = 0 254 } 255 app := testApp(nil, cfgfn, t) 256 txn := app.StartTransaction("hello", nil, helloRequest) 257 ds := DatastoreSegment{ 258 StartTime: StartSegmentNow(txn), 259 Product: DatastoreMySQL, 260 Collection: "users", 261 Operation: "INSERT", 262 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 263 } 264 ds.End() 265 ds = DatastoreSegment{ 266 StartTime: StartSegmentNow(txn), 267 Product: DatastoreMySQL, 268 Collection: "users", 269 Operation: "INSERT", 270 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 271 } 272 ds.End() 273 ds = DatastoreSegment{ 274 StartTime: StartSegmentNow(txn), 275 Product: DatastorePostgres, 276 Collection: "products", 277 Operation: "INSERT", 278 ParameterizedQuery: "INSERT INTO products (name, price) VALUES ($1, $2)", 279 } 280 ds.End() 281 txn.End() 282 283 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 284 Count: 2, 285 MetricName: "Datastore/statement/MySQL/users/INSERT", 286 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 287 TxnName: "WebTransaction/Go/hello", 288 TxnURL: "/hello", 289 DatabaseName: "", 290 Host: "", 291 PortPathOrID: "", 292 }, { 293 Count: 1, 294 MetricName: "Datastore/statement/Postgres/products/INSERT", 295 Query: "INSERT INTO products (name, price) VALUES ($1, $2)", 296 TxnName: "WebTransaction/Go/hello", 297 TxnURL: "/hello", 298 DatabaseName: "", 299 Host: "", 300 PortPathOrID: "", 301 }, 302 }) 303 } 304 305 func TestSlowQueryMissingQuery(t *testing.T) { 306 cfgfn := func(cfg *Config) { 307 cfg.DatastoreTracer.SlowQuery.Threshold = 0 308 } 309 app := testApp(nil, cfgfn, t) 310 txn := app.StartTransaction("hello", nil, helloRequest) 311 s1 := DatastoreSegment{ 312 StartTime: StartSegmentNow(txn), 313 Product: DatastoreMySQL, 314 Collection: "users", 315 Operation: "INSERT", 316 } 317 s1.End() 318 txn.End() 319 320 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 321 Count: 1, 322 MetricName: "Datastore/statement/MySQL/users/INSERT", 323 Query: "'INSERT' on 'users' using 'MySQL'", 324 TxnName: "WebTransaction/Go/hello", 325 TxnURL: "/hello", 326 DatabaseName: "", 327 Host: "", 328 PortPathOrID: "", 329 }}) 330 } 331 332 func TestSlowQueryMissingEverything(t *testing.T) { 333 cfgfn := func(cfg *Config) { 334 cfg.DatastoreTracer.SlowQuery.Threshold = 0 335 } 336 app := testApp(nil, cfgfn, t) 337 txn := app.StartTransaction("hello", nil, helloRequest) 338 s1 := DatastoreSegment{ 339 StartTime: StartSegmentNow(txn), 340 } 341 s1.End() 342 txn.End() 343 344 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 345 Count: 1, 346 MetricName: "Datastore/operation/Unknown/other", 347 Query: "'other' on 'unknown' using 'Unknown'", 348 TxnName: "WebTransaction/Go/hello", 349 TxnURL: "/hello", 350 DatabaseName: "", 351 Host: "", 352 PortPathOrID: "", 353 }}) 354 scope := "WebTransaction/Go/hello" 355 app.ExpectMetrics(t, append([]internal.WantMetric{ 356 {Name: "Datastore/all", Scope: "", Forced: true, Data: nil}, 357 {Name: "Datastore/allWeb", Scope: "", Forced: true, Data: nil}, 358 {Name: "Datastore/Unknown/all", Scope: "", Forced: true, Data: nil}, 359 {Name: "Datastore/Unknown/allWeb", Scope: "", Forced: true, Data: nil}, 360 {Name: "Datastore/operation/Unknown/other", Scope: "", Forced: false, Data: nil}, 361 {Name: "Datastore/operation/Unknown/other", Scope: scope, Forced: false, Data: nil}, 362 }, webMetrics...)) 363 } 364 365 func TestSlowQueryWithQueryParameters(t *testing.T) { 366 cfgfn := func(cfg *Config) { 367 cfg.DatastoreTracer.SlowQuery.Threshold = 0 368 } 369 app := testApp(nil, cfgfn, t) 370 txn := app.StartTransaction("hello", nil, helloRequest) 371 params := map[string]interface{}{ 372 "str": "zap", 373 "int": 123, 374 } 375 s1 := DatastoreSegment{ 376 StartTime: StartSegmentNow(txn), 377 Product: DatastoreMySQL, 378 Collection: "users", 379 Operation: "INSERT", 380 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 381 QueryParameters: params, 382 } 383 s1.End() 384 txn.End() 385 386 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 387 Count: 1, 388 MetricName: "Datastore/statement/MySQL/users/INSERT", 389 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 390 TxnName: "WebTransaction/Go/hello", 391 TxnURL: "/hello", 392 DatabaseName: "", 393 Host: "", 394 PortPathOrID: "", 395 Params: params, 396 }}) 397 } 398 399 func TestSlowQueryHighSecurity(t *testing.T) { 400 cfgfn := func(cfg *Config) { 401 cfg.DatastoreTracer.SlowQuery.Threshold = 0 402 cfg.HighSecurity = true 403 } 404 app := testApp(nil, cfgfn, t) 405 txn := app.StartTransaction("hello", nil, helloRequest) 406 params := map[string]interface{}{ 407 "str": "zap", 408 "int": 123, 409 } 410 s1 := DatastoreSegment{ 411 StartTime: StartSegmentNow(txn), 412 Product: DatastoreMySQL, 413 Collection: "users", 414 Operation: "INSERT", 415 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 416 QueryParameters: params, 417 } 418 s1.End() 419 txn.End() 420 421 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 422 Count: 1, 423 MetricName: "Datastore/statement/MySQL/users/INSERT", 424 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 425 TxnName: "WebTransaction/Go/hello", 426 TxnURL: "/hello", 427 DatabaseName: "", 428 Host: "", 429 PortPathOrID: "", 430 Params: nil, 431 }}) 432 } 433 434 func TestSlowQuerySecurityPolicyFalse(t *testing.T) { 435 // When the record_sql security policy is set to false, sql parameters 436 // and the sql format string should be replaced. 437 cfgfn := func(cfg *Config) { 438 cfg.DatastoreTracer.SlowQuery.Threshold = 0 439 } 440 replyfn := func(reply *internal.ConnectReply) { 441 reply.SecurityPolicies.RecordSQL.SetEnabled(false) 442 } 443 app := testApp(replyfn, cfgfn, t) 444 txn := app.StartTransaction("hello", nil, helloRequest) 445 params := map[string]interface{}{ 446 "str": "zap", 447 "int": 123, 448 } 449 s1 := DatastoreSegment{ 450 StartTime: StartSegmentNow(txn), 451 Product: DatastoreMySQL, 452 Collection: "users", 453 Operation: "INSERT", 454 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 455 QueryParameters: params, 456 } 457 s1.End() 458 txn.End() 459 460 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 461 Count: 1, 462 MetricName: "Datastore/statement/MySQL/users/INSERT", 463 Query: "'INSERT' on 'users' using 'MySQL'", 464 TxnName: "WebTransaction/Go/hello", 465 TxnURL: "/hello", 466 DatabaseName: "", 467 Host: "", 468 PortPathOrID: "", 469 Params: nil, 470 }}) 471 } 472 473 func TestSlowQuerySecurityPolicyTrue(t *testing.T) { 474 // When the record_sql security policy is set to true, sql parameters 475 // should be omitted. 476 cfgfn := func(cfg *Config) { 477 cfg.DatastoreTracer.SlowQuery.Threshold = 0 478 } 479 replyfn := func(reply *internal.ConnectReply) { 480 reply.SecurityPolicies.RecordSQL.SetEnabled(true) 481 } 482 app := testApp(replyfn, cfgfn, t) 483 txn := app.StartTransaction("hello", nil, helloRequest) 484 params := map[string]interface{}{ 485 "str": "zap", 486 "int": 123, 487 } 488 s1 := DatastoreSegment{ 489 StartTime: StartSegmentNow(txn), 490 Product: DatastoreMySQL, 491 Collection: "users", 492 Operation: "INSERT", 493 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 494 QueryParameters: params, 495 } 496 s1.End() 497 txn.End() 498 499 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 500 Count: 1, 501 MetricName: "Datastore/statement/MySQL/users/INSERT", 502 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 503 TxnName: "WebTransaction/Go/hello", 504 TxnURL: "/hello", 505 DatabaseName: "", 506 Host: "", 507 PortPathOrID: "", 508 Params: nil, 509 }}) 510 } 511 512 func TestSlowQueryInvalidParameters(t *testing.T) { 513 cfgfn := func(cfg *Config) { 514 cfg.DatastoreTracer.SlowQuery.Threshold = 0 515 } 516 app := testApp(nil, cfgfn, t) 517 txn := app.StartTransaction("hello", nil, helloRequest) 518 params := map[string]interface{}{ 519 "str": "zap", 520 "int": 123, 521 "invalid_value": struct{}{}, 522 strings.Repeat("key-too-long", 100): 1, 523 "long-key": strings.Repeat("A", 300), 524 } 525 s1 := DatastoreSegment{ 526 StartTime: StartSegmentNow(txn), 527 Product: DatastoreMySQL, 528 Collection: "users", 529 Operation: "INSERT", 530 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 531 QueryParameters: params, 532 } 533 s1.End() 534 txn.End() 535 536 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 537 Count: 1, 538 MetricName: "Datastore/statement/MySQL/users/INSERT", 539 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 540 TxnName: "WebTransaction/Go/hello", 541 TxnURL: "/hello", 542 DatabaseName: "", 543 Host: "", 544 PortPathOrID: "", 545 Params: map[string]interface{}{ 546 "str": "zap", 547 "int": 123, 548 "long-key": strings.Repeat("A", 255), 549 }, 550 }}) 551 } 552 553 func TestSlowQueryParametersDisabled(t *testing.T) { 554 cfgfn := func(cfg *Config) { 555 cfg.DatastoreTracer.SlowQuery.Threshold = 0 556 cfg.DatastoreTracer.QueryParameters.Enabled = false 557 } 558 app := testApp(nil, cfgfn, t) 559 txn := app.StartTransaction("hello", nil, helloRequest) 560 params := map[string]interface{}{ 561 "str": "zap", 562 "int": 123, 563 } 564 s1 := DatastoreSegment{ 565 StartTime: StartSegmentNow(txn), 566 Product: DatastoreMySQL, 567 Collection: "users", 568 Operation: "INSERT", 569 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 570 QueryParameters: params, 571 } 572 s1.End() 573 txn.End() 574 575 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 576 Count: 1, 577 MetricName: "Datastore/statement/MySQL/users/INSERT", 578 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 579 TxnName: "WebTransaction/Go/hello", 580 TxnURL: "/hello", 581 DatabaseName: "", 582 Host: "", 583 PortPathOrID: "", 584 Params: nil, 585 }}) 586 } 587 588 func TestSlowQueryInstanceDisabled(t *testing.T) { 589 cfgfn := func(cfg *Config) { 590 cfg.DatastoreTracer.SlowQuery.Threshold = 0 591 cfg.DatastoreTracer.InstanceReporting.Enabled = false 592 } 593 app := testApp(nil, cfgfn, t) 594 txn := app.StartTransaction("hello", nil, helloRequest) 595 s1 := DatastoreSegment{ 596 StartTime: StartSegmentNow(txn), 597 Product: DatastoreMySQL, 598 Collection: "users", 599 Operation: "INSERT", 600 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 601 Host: "db-server-1", 602 } 603 s1.End() 604 txn.End() 605 606 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 607 Count: 1, 608 MetricName: "Datastore/statement/MySQL/users/INSERT", 609 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 610 TxnName: "WebTransaction/Go/hello", 611 TxnURL: "/hello", 612 DatabaseName: "", 613 Host: "", 614 PortPathOrID: "", 615 }}) 616 scope := "WebTransaction/Go/hello" 617 app.ExpectMetrics(t, append([]internal.WantMetric{ 618 {Name: "Datastore/all", Scope: "", Forced: true, Data: nil}, 619 {Name: "Datastore/allWeb", Scope: "", Forced: true, Data: nil}, 620 {Name: "Datastore/MySQL/all", Scope: "", Forced: true, Data: nil}, 621 {Name: "Datastore/MySQL/allWeb", Scope: "", Forced: true, Data: nil}, 622 {Name: "Datastore/operation/MySQL/INSERT", Scope: "", Forced: false, Data: nil}, 623 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: "", Forced: false, Data: nil}, 624 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: scope, Forced: false, Data: nil}, 625 }, webMetrics...)) 626 } 627 628 func TestSlowQueryInstanceDisabledLocalhost(t *testing.T) { 629 cfgfn := func(cfg *Config) { 630 cfg.DatastoreTracer.SlowQuery.Threshold = 0 631 cfg.DatastoreTracer.InstanceReporting.Enabled = false 632 } 633 app := testApp(nil, cfgfn, t) 634 txn := app.StartTransaction("hello", nil, helloRequest) 635 s1 := DatastoreSegment{ 636 StartTime: StartSegmentNow(txn), 637 Product: DatastoreMySQL, 638 Collection: "users", 639 Operation: "INSERT", 640 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 641 Host: "localhost", 642 PortPathOrID: "3306", 643 } 644 s1.End() 645 txn.End() 646 647 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 648 Count: 1, 649 MetricName: "Datastore/statement/MySQL/users/INSERT", 650 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 651 TxnName: "WebTransaction/Go/hello", 652 TxnURL: "/hello", 653 DatabaseName: "", 654 Host: "", 655 PortPathOrID: "", 656 }}) 657 scope := "WebTransaction/Go/hello" 658 app.ExpectMetrics(t, append([]internal.WantMetric{ 659 {Name: "Datastore/all", Scope: "", Forced: true, Data: nil}, 660 {Name: "Datastore/allWeb", Scope: "", Forced: true, Data: nil}, 661 {Name: "Datastore/MySQL/all", Scope: "", Forced: true, Data: nil}, 662 {Name: "Datastore/MySQL/allWeb", Scope: "", Forced: true, Data: nil}, 663 {Name: "Datastore/operation/MySQL/INSERT", Scope: "", Forced: false, Data: nil}, 664 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: "", Forced: false, Data: nil}, 665 {Name: "Datastore/statement/MySQL/users/INSERT", Scope: scope, Forced: false, Data: nil}, 666 }, webMetrics...)) 667 } 668 669 func TestSlowQueryDatabaseNameDisabled(t *testing.T) { 670 cfgfn := func(cfg *Config) { 671 cfg.DatastoreTracer.SlowQuery.Threshold = 0 672 cfg.DatastoreTracer.DatabaseNameReporting.Enabled = false 673 } 674 app := testApp(nil, cfgfn, t) 675 txn := app.StartTransaction("hello", nil, helloRequest) 676 s1 := DatastoreSegment{ 677 StartTime: StartSegmentNow(txn), 678 Product: DatastoreMySQL, 679 Collection: "users", 680 Operation: "INSERT", 681 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 682 DatabaseName: "db-server-1", 683 } 684 s1.End() 685 txn.End() 686 687 app.ExpectSlowQueries(t, []internal.WantSlowQuery{{ 688 Count: 1, 689 MetricName: "Datastore/statement/MySQL/users/INSERT", 690 Query: "INSERT INTO users (name, age) VALUES ($1, $2)", 691 TxnName: "WebTransaction/Go/hello", 692 TxnURL: "/hello", 693 DatabaseName: "", 694 Host: "", 695 PortPathOrID: "", 696 }}) 697 } 698 699 func TestDatastoreAPICrossAgent(t *testing.T) { 700 var testcases []struct { 701 TestName string `json:"test_name"` 702 Input struct { 703 Parameters struct { 704 Product string `json:"product"` 705 Collection string `json:"collection"` 706 Operation string `json:"operation"` 707 Host string `json:"host"` 708 PortPathOrID string `json:"port_path_or_id"` 709 DatabaseName string `json:"database_name"` 710 } `json:"parameters"` 711 IsWeb bool `json:"is_web"` 712 SystemHostname string `json:"system_hostname"` 713 Configuration struct { 714 InstanceEnabled bool `json:"datastore_tracer.instance_reporting.enabled"` 715 DatabaseEnabled bool `json:"datastore_tracer.database_name_reporting.enabled"` 716 } 717 } 718 Expectation struct { 719 MetricsScoped []string `json:"metrics_scoped"` 720 MetricsUnscoped []string `json:"metrics_unscoped"` 721 Trace struct { 722 MetricName string `json:"metric_name"` 723 Host string `json:"host"` 724 PortPathOrID string `json:"port_path_or_id"` 725 DatabaseName string `json:"database_name"` 726 } `json:"transaction_segment_and_slow_query_trace"` 727 } 728 } 729 730 err := crossagent.ReadJSON("datastores/datastore_api.json", &testcases) 731 if err != nil { 732 t.Fatal(err) 733 } 734 735 for _, tc := range testcases { 736 query := "my query" 737 cfgfn := func(cfg *Config) { 738 cfg.DatastoreTracer.SlowQuery.Threshold = 0 739 cfg.DatastoreTracer.InstanceReporting.Enabled = 740 tc.Input.Configuration.InstanceEnabled 741 cfg.DatastoreTracer.DatabaseNameReporting.Enabled = 742 tc.Input.Configuration.DatabaseEnabled 743 } 744 app := testApp(nil, cfgfn, t) 745 var txn Transaction 746 var txnURL string 747 if tc.Input.IsWeb { 748 txnURL = helloPath 749 txn = app.StartTransaction("hello", nil, helloRequest) 750 } else { 751 txn = app.StartTransaction("hello", nil, nil) 752 } 753 ds := DatastoreSegment{ 754 StartTime: StartSegmentNow(txn), 755 Product: DatastoreProduct(tc.Input.Parameters.Product), 756 Operation: tc.Input.Parameters.Operation, 757 Collection: tc.Input.Parameters.Collection, 758 PortPathOrID: tc.Input.Parameters.PortPathOrID, 759 Host: tc.Input.Parameters.Host, 760 DatabaseName: tc.Input.Parameters.DatabaseName, 761 ParameterizedQuery: query, 762 } 763 ds.End() 764 txn.End() 765 766 var metrics []internal.WantMetric 767 var scope string 768 if tc.Input.IsWeb { 769 scope = "WebTransaction/Go/hello" 770 metrics = append([]internal.WantMetric{}, webMetrics...) 771 } else { 772 scope = "OtherTransaction/Go/hello" 773 metrics = append([]internal.WantMetric{}, backgroundMetrics...) 774 } 775 776 for _, m := range tc.Expectation.MetricsScoped { 777 metrics = append(metrics, internal.WantMetric{ 778 Name: m, Scope: scope, Forced: nil, Data: nil, 779 }) 780 } 781 for _, m := range tc.Expectation.MetricsUnscoped { 782 metrics = append(metrics, internal.WantMetric{ 783 Name: m, Scope: "", Forced: nil, Data: nil, 784 }) 785 } 786 787 expectTraceHost := tc.Expectation.Trace.Host 788 if tc.Input.SystemHostname != "" { 789 for i := range metrics { 790 metrics[i].Name = strings.Replace(metrics[i].Name, 791 tc.Input.SystemHostname, 792 internal.ThisHost, -1) 793 } 794 expectTraceHost = strings.Replace(expectTraceHost, 795 tc.Input.SystemHostname, 796 internal.ThisHost, -1) 797 } 798 799 tt := internal.ExtendValidator(t, tc.TestName) 800 app.ExpectMetrics(tt, metrics) 801 app.ExpectSlowQueries(tt, []internal.WantSlowQuery{{ 802 Count: 1, 803 MetricName: tc.Expectation.Trace.MetricName, 804 TxnName: scope, 805 DatabaseName: tc.Expectation.Trace.DatabaseName, 806 Host: expectTraceHost, 807 PortPathOrID: tc.Expectation.Trace.PortPathOrID, 808 TxnURL: txnURL, 809 Query: query, 810 }}) 811 } 812 }