github.com/lulzWill/go-agent@v2.1.2+incompatible/internal_attributes_test.go (about) 1 package newrelic 2 3 import ( 4 "errors" 5 "net/http" 6 "testing" 7 8 "github.com/lulzWill/go-agent/internal" 9 ) 10 11 func TestAddAttributeHighSecurity(t *testing.T) { 12 cfgfn := func(cfg *Config) { 13 cfg.HighSecurity = true 14 } 15 app := testApp(nil, cfgfn, t) 16 txn := app.StartTransaction("hello", nil, nil) 17 18 if err := txn.AddAttribute(`key`, 1); err != errHighSecurityEnabled { 19 t.Error(err) 20 } 21 txn.End() 22 23 app.ExpectTxnEvents(t, []internal.WantEvent{{ 24 Intrinsics: map[string]interface{}{ 25 "name": "OtherTransaction/Go/hello", 26 }, 27 AgentAttributes: nil, 28 UserAttributes: map[string]interface{}{}, 29 }}) 30 } 31 32 func TestAddAttributeSecurityPolicyDisablesParameters(t *testing.T) { 33 replyfn := func(reply *internal.ConnectReply) { 34 reply.SecurityPolicies.CustomParameters.SetEnabled(false) 35 } 36 app := testApp(replyfn, nil, t) 37 txn := app.StartTransaction("hello", nil, nil) 38 39 if err := txn.AddAttribute(`key`, 1); err != errSecurityPolicy { 40 t.Error(err) 41 } 42 txn.End() 43 44 app.ExpectTxnEvents(t, []internal.WantEvent{{ 45 Intrinsics: map[string]interface{}{ 46 "name": "OtherTransaction/Go/hello", 47 }, 48 AgentAttributes: nil, 49 UserAttributes: map[string]interface{}{}, 50 }}) 51 } 52 53 func TestAddAttributeSecurityPolicyDisablesInclude(t *testing.T) { 54 replyfn := func(reply *internal.ConnectReply) { 55 reply.SecurityPolicies.AttributesInclude.SetEnabled(false) 56 } 57 cfgfn := func(cfg *Config) { 58 cfg.TransactionEvents.Attributes.Include = append(cfg.TransactionEvents.Attributes.Include, 59 AttributeRequestUserAgent) 60 } 61 val := "dont-include-me-in-txn-events" 62 app := testApp(replyfn, cfgfn, t) 63 req := &http.Request{} 64 req.Header = make(http.Header) 65 req.Header.Add("User-Agent", val) 66 txn := app.StartTransaction("hello", nil, req) 67 txn.NoticeError(errors.New("hello")) 68 txn.End() 69 app.ExpectTxnEvents(t, []internal.WantEvent{{ 70 Intrinsics: map[string]interface{}{ 71 "name": "WebTransaction/Go/hello", 72 "nr.apdexPerfZone": "F", 73 }, 74 AgentAttributes: map[string]interface{}{}, 75 UserAttributes: map[string]interface{}{}, 76 }}) 77 app.ExpectErrors(t, []internal.WantError{{ 78 TxnName: "WebTransaction/Go/hello", 79 Msg: "hello", 80 Klass: "*errors.errorString", 81 Caller: "go-agent.TestAddAttributeSecurityPolicyDisablesInclude", 82 URL: "", 83 AgentAttributes: map[string]interface{}{AttributeRequestUserAgent: val}, 84 UserAttributes: map[string]interface{}{}, 85 }}) 86 } 87 88 func TestUserAttributeBasics(t *testing.T) { 89 cfgfn := func(cfg *Config) { 90 cfg.TransactionTracer.Threshold.IsApdexFailing = false 91 cfg.TransactionTracer.Threshold.Duration = 0 92 } 93 app := testApp(nil, cfgfn, t) 94 txn := app.StartTransaction("hello", nil, nil) 95 96 txn.NoticeError(errors.New("zap")) 97 98 if err := txn.AddAttribute(`int\key`, 1); nil != err { 99 t.Error(err) 100 } 101 if err := txn.AddAttribute(`str\key`, `zip\zap`); nil != err { 102 t.Error(err) 103 } 104 err := txn.AddAttribute("invalid_value", struct{}{}) 105 if _, ok := err.(internal.ErrInvalidAttributeType); !ok { 106 t.Error(err) 107 } 108 txn.End() 109 if err := txn.AddAttribute("already_ended", "zap"); err != errAlreadyEnded { 110 t.Error(err) 111 } 112 113 agentAttributes := map[string]interface{}{} 114 userAttributes := map[string]interface{}{`int\key`: 1, `str\key`: `zip\zap`} 115 116 app.ExpectTxnEvents(t, []internal.WantEvent{{ 117 Intrinsics: map[string]interface{}{ 118 "name": "OtherTransaction/Go/hello", 119 }, 120 AgentAttributes: agentAttributes, 121 UserAttributes: userAttributes, 122 }}) 123 app.ExpectErrors(t, []internal.WantError{{ 124 TxnName: "OtherTransaction/Go/hello", 125 Msg: "zap", 126 Klass: "*errors.errorString", 127 Caller: "go-agent.TestUserAttributeBasics", 128 URL: "", 129 AgentAttributes: agentAttributes, 130 UserAttributes: userAttributes, 131 }}) 132 app.ExpectErrorEvents(t, []internal.WantEvent{{ 133 Intrinsics: map[string]interface{}{ 134 "error.class": "*errors.errorString", 135 "error.message": "zap", 136 "transactionName": "OtherTransaction/Go/hello", 137 }, 138 AgentAttributes: agentAttributes, 139 UserAttributes: userAttributes, 140 }}) 141 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 142 MetricName: "OtherTransaction/Go/hello", 143 CleanURL: "", 144 NumSegments: 0, 145 AgentAttributes: agentAttributes, 146 UserAttributes: userAttributes, 147 }}) 148 } 149 150 func TestUserAttributeConfiguration(t *testing.T) { 151 cfgfn := func(cfg *Config) { 152 cfg.TransactionEvents.Attributes.Exclude = []string{"only_errors", "only_txn_traces"} 153 cfg.ErrorCollector.Attributes.Exclude = []string{"only_txn_events", "only_txn_traces"} 154 cfg.TransactionTracer.Attributes.Exclude = []string{"only_txn_events", "only_errors"} 155 cfg.Attributes.Exclude = []string{"completed_excluded"} 156 cfg.TransactionTracer.Threshold.IsApdexFailing = false 157 cfg.TransactionTracer.Threshold.Duration = 0 158 } 159 app := testApp(nil, cfgfn, t) 160 txn := app.StartTransaction("hello", nil, nil) 161 162 txn.NoticeError(errors.New("zap")) 163 164 if err := txn.AddAttribute("only_errors", 1); nil != err { 165 t.Error(err) 166 } 167 if err := txn.AddAttribute("only_txn_events", 2); nil != err { 168 t.Error(err) 169 } 170 if err := txn.AddAttribute("only_txn_traces", 3); nil != err { 171 t.Error(err) 172 } 173 if err := txn.AddAttribute("completed_excluded", 4); nil != err { 174 t.Error(err) 175 } 176 txn.End() 177 178 app.ExpectTxnEvents(t, []internal.WantEvent{{ 179 Intrinsics: map[string]interface{}{ 180 "name": "OtherTransaction/Go/hello", 181 }, 182 AgentAttributes: map[string]interface{}{}, 183 UserAttributes: map[string]interface{}{"only_txn_events": 2}, 184 }}) 185 app.ExpectErrors(t, []internal.WantError{{ 186 TxnName: "OtherTransaction/Go/hello", 187 Msg: "zap", 188 Klass: "*errors.errorString", 189 Caller: "go-agent.TestUserAttributeConfiguration", 190 URL: "", 191 AgentAttributes: map[string]interface{}{}, 192 UserAttributes: map[string]interface{}{"only_errors": 1}, 193 }}) 194 app.ExpectErrorEvents(t, []internal.WantEvent{{ 195 Intrinsics: map[string]interface{}{ 196 "error.class": "*errors.errorString", 197 "error.message": "zap", 198 "transactionName": "OtherTransaction/Go/hello", 199 }, 200 AgentAttributes: map[string]interface{}{}, 201 UserAttributes: map[string]interface{}{"only_errors": 1}, 202 }}) 203 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 204 MetricName: "OtherTransaction/Go/hello", 205 CleanURL: "", 206 NumSegments: 0, 207 AgentAttributes: map[string]interface{}{}, 208 UserAttributes: map[string]interface{}{"only_txn_traces": 3}, 209 }}) 210 } 211 212 // Second attributes have priority. 213 func mergeAttributes(a1, a2 map[string]interface{}) map[string]interface{} { 214 a := make(map[string]interface{}) 215 for k, v := range a1 { 216 a[k] = v 217 } 218 for k, v := range a2 { 219 a[k] = v 220 } 221 return a 222 } 223 224 var ( 225 // Agent attributes expected in txn events from usualAttributeTestTransaction. 226 agent1 = map[string]interface{}{ 227 AttributeHostDisplayName: `my\host\display\name`, 228 AttributeResponseCode: `404`, 229 AttributeResponseContentType: `text/plain; charset=us-ascii`, 230 AttributeResponseContentLength: 345, 231 AttributeRequestMethod: "GET", 232 AttributeRequestAccept: "text/plain", 233 AttributeRequestContentType: "text/html; charset=utf-8", 234 AttributeRequestContentLength: 753, 235 AttributeRequestHost: "my_domain.com", 236 } 237 // Agent attributes expected in errors and traces from usualAttributeTestTransaction. 238 agent2 = mergeAttributes(agent1, map[string]interface{}{ 239 AttributeRequestUserAgent: "Mozilla/5.0", 240 AttributeRequestReferer: "http://en.wikipedia.org/zip", 241 }) 242 // User attributes expected from usualAttributeTestTransaction. 243 user1 = map[string]interface{}{ 244 "myStr": "hello", 245 } 246 ) 247 248 func agentAttributeTestcase(t testing.TB, cfgfn func(cfg *Config), e AttributeExpect) { 249 app := testApp(nil, func(cfg *Config) { 250 cfg.HostDisplayName = `my\host\display\name` 251 cfg.TransactionTracer.Threshold.IsApdexFailing = false 252 cfg.TransactionTracer.Threshold.Duration = 0 253 if nil != cfgfn { 254 cfgfn(cfg) 255 } 256 }, t) 257 w := newCompatibleResponseRecorder() 258 txn := app.StartTransaction("hello", w, helloRequest) 259 txn.NoticeError(errors.New("zap")) 260 261 hdr := txn.Header() 262 hdr.Set("Content-Type", `text/plain; charset=us-ascii`) 263 hdr.Set("Content-Length", `345`) 264 265 txn.WriteHeader(404) 266 txn.AddAttribute("myStr", "hello") 267 268 txn.End() 269 270 app.ExpectTxnEvents(t, []internal.WantEvent{{ 271 Intrinsics: map[string]interface{}{ 272 "name": "WebTransaction/Go/hello", 273 "nr.apdexPerfZone": "F", 274 }, 275 AgentAttributes: e.TxnEvent.Agent, 276 UserAttributes: e.TxnEvent.User, 277 }}) 278 app.ExpectErrors(t, []internal.WantError{{ 279 TxnName: "WebTransaction/Go/hello", 280 Msg: "zap", 281 Klass: "*errors.errorString", 282 Caller: "go-agent.agentAttributeTestcase", 283 URL: "/hello", 284 AgentAttributes: e.Error.Agent, 285 UserAttributes: e.Error.User, 286 }}) 287 app.ExpectErrorEvents(t, []internal.WantEvent{{ 288 Intrinsics: map[string]interface{}{ 289 "error.class": "*errors.errorString", 290 "error.message": "zap", 291 "transactionName": "WebTransaction/Go/hello", 292 }, 293 AgentAttributes: e.Error.Agent, 294 UserAttributes: e.Error.User, 295 }}) 296 app.ExpectTxnTraces(t, []internal.WantTxnTrace{{ 297 MetricName: "WebTransaction/Go/hello", 298 CleanURL: "/hello", 299 NumSegments: 0, 300 AgentAttributes: e.TxnTrace.Agent, 301 UserAttributes: e.TxnTrace.User, 302 }}) 303 } 304 305 type UserAgent struct { 306 User map[string]interface{} 307 Agent map[string]interface{} 308 } 309 310 type AttributeExpect struct { 311 TxnEvent UserAgent 312 Error UserAgent 313 TxnTrace UserAgent 314 } 315 316 func TestAgentAttributes(t *testing.T) { 317 agentAttributeTestcase(t, nil, AttributeExpect{ 318 TxnEvent: UserAgent{ 319 Agent: agent1, 320 User: user1}, 321 Error: UserAgent{ 322 Agent: agent2, 323 User: user1}, 324 }) 325 } 326 327 func TestAttributesDisabled(t *testing.T) { 328 agentAttributeTestcase(t, func(cfg *Config) { 329 cfg.Attributes.Enabled = false 330 }, AttributeExpect{ 331 TxnEvent: UserAgent{ 332 Agent: map[string]interface{}{}, 333 User: map[string]interface{}{}}, 334 Error: UserAgent{ 335 Agent: map[string]interface{}{}, 336 User: map[string]interface{}{}}, 337 TxnTrace: UserAgent{ 338 Agent: map[string]interface{}{}, 339 User: map[string]interface{}{}}, 340 }) 341 } 342 343 func TestDefaultResponseCode(t *testing.T) { 344 app := testApp(nil, nil, t) 345 w := newCompatibleResponseRecorder() 346 txn := app.StartTransaction("hello", w, &http.Request{}) 347 txn.Write([]byte("hello")) 348 txn.End() 349 350 app.ExpectTxnEvents(t, []internal.WantEvent{{ 351 Intrinsics: map[string]interface{}{ 352 "name": "WebTransaction/Go/hello", 353 "nr.apdexPerfZone": "S", 354 }, 355 AgentAttributes: map[string]interface{}{AttributeResponseCode: 200}, 356 UserAttributes: map[string]interface{}{}, 357 }}) 358 } 359 360 func TestNoResponseCode(t *testing.T) { 361 app := testApp(nil, nil, t) 362 w := newCompatibleResponseRecorder() 363 txn := app.StartTransaction("hello", w, &http.Request{}) 364 txn.End() 365 366 app.ExpectTxnEvents(t, []internal.WantEvent{{ 367 Intrinsics: map[string]interface{}{ 368 "name": "WebTransaction/Go/hello", 369 "nr.apdexPerfZone": "S", 370 }, 371 AgentAttributes: map[string]interface{}{}, 372 UserAttributes: map[string]interface{}{}, 373 }}) 374 } 375 376 func TestTxnEventAttributesDisabled(t *testing.T) { 377 agentAttributeTestcase(t, func(cfg *Config) { 378 cfg.TransactionEvents.Attributes.Enabled = false 379 }, AttributeExpect{ 380 TxnEvent: UserAgent{ 381 Agent: map[string]interface{}{}, 382 User: map[string]interface{}{}}, 383 Error: UserAgent{ 384 Agent: agent2, 385 User: user1}, 386 TxnTrace: UserAgent{ 387 Agent: agent2, 388 User: user1}, 389 }) 390 } 391 392 func TestErrorAttributesDisabled(t *testing.T) { 393 agentAttributeTestcase(t, func(cfg *Config) { 394 cfg.ErrorCollector.Attributes.Enabled = false 395 }, AttributeExpect{ 396 TxnEvent: UserAgent{ 397 Agent: agent1, 398 User: user1}, 399 Error: UserAgent{ 400 Agent: map[string]interface{}{}, 401 User: map[string]interface{}{}}, 402 TxnTrace: UserAgent{ 403 Agent: agent2, 404 User: user1}, 405 }) 406 } 407 408 func TestTxnTraceAttributesDisabled(t *testing.T) { 409 agentAttributeTestcase(t, func(cfg *Config) { 410 cfg.TransactionTracer.Attributes.Enabled = false 411 }, AttributeExpect{ 412 TxnEvent: UserAgent{ 413 Agent: agent1, 414 User: user1}, 415 Error: UserAgent{ 416 Agent: agent2, 417 User: user1}, 418 TxnTrace: UserAgent{ 419 Agent: map[string]interface{}{}, 420 User: map[string]interface{}{}}, 421 }) 422 } 423 424 var ( 425 allAgentAttributeNames = []string{ 426 AttributeResponseCode, 427 AttributeRequestMethod, 428 AttributeRequestAccept, 429 AttributeRequestContentType, 430 AttributeRequestContentLength, 431 AttributeRequestHost, 432 AttributeResponseContentType, 433 AttributeResponseContentLength, 434 AttributeHostDisplayName, 435 AttributeRequestUserAgent, 436 AttributeRequestReferer, 437 } 438 ) 439 440 func TestAgentAttributesExcluded(t *testing.T) { 441 agentAttributeTestcase(t, func(cfg *Config) { 442 cfg.Attributes.Exclude = allAgentAttributeNames 443 }, AttributeExpect{ 444 TxnEvent: UserAgent{ 445 Agent: map[string]interface{}{}, 446 User: user1}, 447 Error: UserAgent{ 448 Agent: map[string]interface{}{}, 449 User: user1}, 450 TxnTrace: UserAgent{ 451 Agent: map[string]interface{}{}, 452 User: user1}, 453 }) 454 } 455 456 func TestAgentAttributesExcludedFromErrors(t *testing.T) { 457 agentAttributeTestcase(t, func(cfg *Config) { 458 cfg.ErrorCollector.Attributes.Exclude = allAgentAttributeNames 459 }, AttributeExpect{ 460 TxnEvent: UserAgent{ 461 Agent: agent1, 462 User: user1}, 463 Error: UserAgent{ 464 Agent: map[string]interface{}{}, 465 User: user1}, 466 TxnTrace: UserAgent{ 467 Agent: agent2, 468 User: user1}, 469 }) 470 } 471 472 func TestAgentAttributesExcludedFromTxnEvents(t *testing.T) { 473 agentAttributeTestcase(t, func(cfg *Config) { 474 cfg.TransactionEvents.Attributes.Exclude = allAgentAttributeNames 475 }, AttributeExpect{ 476 TxnEvent: UserAgent{ 477 Agent: map[string]interface{}{}, 478 User: user1}, 479 Error: UserAgent{ 480 Agent: agent2, 481 User: user1}, 482 TxnTrace: UserAgent{ 483 Agent: agent2, 484 User: user1}, 485 }) 486 } 487 488 func TestAgentAttributesExcludedFromTxnTraces(t *testing.T) { 489 agentAttributeTestcase(t, func(cfg *Config) { 490 cfg.TransactionTracer.Attributes.Exclude = allAgentAttributeNames 491 }, AttributeExpect{ 492 TxnEvent: UserAgent{ 493 Agent: agent1, 494 User: user1}, 495 Error: UserAgent{ 496 Agent: agent2, 497 User: user1}, 498 TxnTrace: UserAgent{ 499 Agent: map[string]interface{}{}, 500 User: user1}, 501 }) 502 }