github.com/newrelic/go-agent@v3.26.0+incompatible/internal_config_test.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package newrelic 5 6 import ( 7 "encoding/json" 8 "net/http" 9 "os" 10 "reflect" 11 "regexp" 12 "strconv" 13 "strings" 14 "testing" 15 16 "github.com/newrelic/go-agent/internal" 17 "github.com/newrelic/go-agent/internal/utilization" 18 ) 19 20 var ( 21 fixRegex = regexp.MustCompile(`e\+\d+`) 22 ) 23 24 // In Go 1.8 Marshalling of numbers was changed: 25 // Before: "StackTraceThreshold":5e+08 26 // After: "StackTraceThreshold":500000000 27 func standardizeNumbers(input string) string { 28 return fixRegex.ReplaceAllStringFunc(input, func(s string) string { 29 n, err := strconv.Atoi(s[2:]) 30 if nil != err { 31 return s 32 } 33 return strings.Repeat("0", n) 34 }) 35 } 36 37 func TestCopyConfigReferenceFieldsPresent(t *testing.T) { 38 cfg := NewConfig("my appname", "0123456789012345678901234567890123456789") 39 cfg.Labels["zip"] = "zap" 40 cfg.ErrorCollector.IgnoreStatusCodes = append(cfg.ErrorCollector.IgnoreStatusCodes, 405) 41 cfg.Attributes.Include = append(cfg.Attributes.Include, "1") 42 cfg.Attributes.Exclude = append(cfg.Attributes.Exclude, "2") 43 cfg.TransactionEvents.Attributes.Include = append(cfg.TransactionEvents.Attributes.Include, "3") 44 cfg.TransactionEvents.Attributes.Exclude = append(cfg.TransactionEvents.Attributes.Exclude, "4") 45 cfg.ErrorCollector.Attributes.Include = append(cfg.ErrorCollector.Attributes.Include, "5") 46 cfg.ErrorCollector.Attributes.Exclude = append(cfg.ErrorCollector.Attributes.Exclude, "6") 47 cfg.TransactionTracer.Attributes.Include = append(cfg.TransactionTracer.Attributes.Include, "7") 48 cfg.TransactionTracer.Attributes.Exclude = append(cfg.TransactionTracer.Attributes.Exclude, "8") 49 cfg.BrowserMonitoring.Attributes.Include = append(cfg.BrowserMonitoring.Attributes.Include, "9") 50 cfg.BrowserMonitoring.Attributes.Exclude = append(cfg.BrowserMonitoring.Attributes.Exclude, "10") 51 cfg.SpanEvents.Attributes.Include = append(cfg.SpanEvents.Attributes.Include, "11") 52 cfg.SpanEvents.Attributes.Exclude = append(cfg.SpanEvents.Attributes.Exclude, "12") 53 cfg.TransactionTracer.Segments.Attributes.Include = append(cfg.TransactionTracer.Segments.Attributes.Include, "13") 54 cfg.TransactionTracer.Segments.Attributes.Exclude = append(cfg.TransactionTracer.Segments.Attributes.Exclude, "14") 55 cfg.Transport = &http.Transport{} 56 cfg.Logger = NewLogger(os.Stdout) 57 58 cp := copyConfigReferenceFields(cfg) 59 60 cfg.Labels["zop"] = "zup" 61 cfg.ErrorCollector.IgnoreStatusCodes[0] = 201 62 cfg.Attributes.Include[0] = "zap" 63 cfg.Attributes.Exclude[0] = "zap" 64 cfg.TransactionEvents.Attributes.Include[0] = "zap" 65 cfg.TransactionEvents.Attributes.Exclude[0] = "zap" 66 cfg.ErrorCollector.Attributes.Include[0] = "zap" 67 cfg.ErrorCollector.Attributes.Exclude[0] = "zap" 68 cfg.TransactionTracer.Attributes.Include[0] = "zap" 69 cfg.TransactionTracer.Attributes.Exclude[0] = "zap" 70 cfg.BrowserMonitoring.Attributes.Include[0] = "zap" 71 cfg.BrowserMonitoring.Attributes.Exclude[0] = "zap" 72 cfg.SpanEvents.Attributes.Include[0] = "zap" 73 cfg.SpanEvents.Attributes.Exclude[0] = "zap" 74 cfg.TransactionTracer.Segments.Attributes.Include[0] = "zap" 75 cfg.TransactionTracer.Segments.Attributes.Exclude[0] = "zap" 76 77 expect := internal.CompactJSONString(`[ 78 { 79 "pid":123, 80 "language":"go", 81 "agent_version":"0.2.2", 82 "host":"my-hostname", 83 "settings":{ 84 "AppName":"my appname", 85 "Attributes":{"Enabled":true,"Exclude":["2"],"Include":["1"]}, 86 "BrowserMonitoring":{ 87 "Attributes":{"Enabled":false,"Exclude":["10"],"Include":["9"]}, 88 "Enabled":true 89 }, 90 "CrossApplicationTracer":{"Enabled":true}, 91 "CustomInsightsEvents":{"Enabled":true}, 92 "DatastoreTracer":{ 93 "DatabaseNameReporting":{"Enabled":true}, 94 "InstanceReporting":{"Enabled":true}, 95 "QueryParameters":{"Enabled":true}, 96 "SlowQuery":{ 97 "Enabled":true, 98 "Threshold":10000000 99 } 100 }, 101 "DistributedTracer":{"Enabled":false}, 102 "Enabled":true, 103 "ErrorCollector":{ 104 "Attributes":{"Enabled":true,"Exclude":["6"],"Include":["5"]}, 105 "CaptureEvents":true, 106 "Enabled":true, 107 "IgnoreStatusCodes":[0,5,404,405] 108 }, 109 "HighSecurity":false, 110 "HostDisplayName":"", 111 "Labels":{"zip":"zap"}, 112 "Logger":"*logger.logFile", 113 "RuntimeSampler":{"Enabled":true}, 114 "SecurityPoliciesToken":"", 115 "ServerlessMode":{ 116 "AccountID":"", 117 "ApdexThreshold":500000000, 118 "Enabled":false, 119 "PrimaryAppID":"", 120 "TrustedAccountKey":"" 121 }, 122 "SpanEvents":{ 123 "Attributes":{ 124 "Enabled":true,"Exclude":["12"],"Include":["11"] 125 }, 126 "Enabled":true 127 }, 128 "TransactionEvents":{ 129 "Attributes":{"Enabled":true,"Exclude":["4"],"Include":["3"]}, 130 "Enabled":true, 131 "MaxSamplesStored": 10000 132 }, 133 "TransactionTracer":{ 134 "Attributes":{"Enabled":true,"Exclude":["8"],"Include":["7"]}, 135 "Enabled":true, 136 "SegmentThreshold":2000000, 137 "Segments":{"Attributes":{"Enabled":true,"Exclude":["14"],"Include":["13"]}}, 138 "StackTraceThreshold":500000000, 139 "Threshold":{ 140 "Duration":500000000, 141 "IsApdexFailing":true 142 } 143 }, 144 "Transport":"*http.Transport", 145 "Utilization":{ 146 "BillingHostname":"", 147 "DetectAWS":true, 148 "DetectAzure":true, 149 "DetectDocker":true, 150 "DetectGCP":true, 151 "DetectKubernetes":true, 152 "DetectPCF":true, 153 "LogicalProcessors":0, 154 "TotalRAMMIB":0 155 }, 156 "browser_monitoring.loader":"rum" 157 }, 158 "app_name":["my appname"], 159 "high_security":false, 160 "labels":[{"label_type":"zip","label_value":"zap"}], 161 "environment":[ 162 ["runtime.Compiler","comp"], 163 ["runtime.GOARCH","arch"], 164 ["runtime.GOOS","goos"], 165 ["runtime.Version","vers"], 166 ["runtime.NumCPU",8] 167 ], 168 "identifier":"my appname", 169 "utilization":{ 170 "metadata_version":5, 171 "logical_processors":16, 172 "total_ram_mib":1024, 173 "hostname":"my-hostname" 174 }, 175 "security_policies":{ 176 "record_sql":{"enabled":false}, 177 "attributes_include":{"enabled":false}, 178 "allow_raw_exception_messages":{"enabled":false}, 179 "custom_events":{"enabled":false}, 180 "custom_parameters":{"enabled":false} 181 }, 182 "metadata":{ 183 "NEW_RELIC_METADATA_ZAP":"zip" 184 }, 185 "event_harvest_config": { 186 "report_period_ms": 60000, 187 "harvest_limits": { 188 "analytic_event_data": 10000, 189 "custom_event_data": 10000, 190 "error_event_data": 100 191 } 192 } 193 }]`) 194 195 securityPoliciesInput := []byte(`{ 196 "record_sql": { "enabled": false, "required": false }, 197 "attributes_include": { "enabled": false, "required": false }, 198 "allow_raw_exception_messages": { "enabled": false, "required": false }, 199 "custom_events": { "enabled": false, "required": false }, 200 "custom_parameters": { "enabled": false, "required": false }, 201 "custom_instrumentation_editor": { "enabled": false, "required": false }, 202 "message_parameters": { "enabled": false, "required": false }, 203 "job_arguments": { "enabled": false, "required": false } 204 }`) 205 var sp internal.SecurityPolicies 206 err := json.Unmarshal(securityPoliciesInput, &sp) 207 if nil != err { 208 t.Fatal(err) 209 } 210 211 metadata := map[string]string{ 212 "NEW_RELIC_METADATA_ZAP": "zip", 213 } 214 js, err := configConnectJSONInternal(cp, 123, &utilization.SampleData, internal.SampleEnvironment, "0.2.2", sp.PointerIfPopulated(), metadata) 215 if nil != err { 216 t.Fatal(err) 217 } 218 out := standardizeNumbers(string(js)) 219 if out != expect { 220 t.Error(out) 221 } 222 } 223 224 func TestCopyConfigReferenceFieldsAbsent(t *testing.T) { 225 cfg := NewConfig("my appname", "0123456789012345678901234567890123456789") 226 cfg.Labels = nil 227 cfg.ErrorCollector.IgnoreStatusCodes = nil 228 229 cp := copyConfigReferenceFields(cfg) 230 231 expect := internal.CompactJSONString(`[ 232 { 233 "pid":123, 234 "language":"go", 235 "agent_version":"0.2.2", 236 "host":"my-hostname", 237 "settings":{ 238 "AppName":"my appname", 239 "Attributes":{"Enabled":true,"Exclude":null,"Include":null}, 240 "BrowserMonitoring":{ 241 "Attributes":{ 242 "Enabled":false, 243 "Exclude":null, 244 "Include":null 245 }, 246 "Enabled":true 247 }, 248 "CrossApplicationTracer":{"Enabled":true}, 249 "CustomInsightsEvents":{"Enabled":true}, 250 "DatastoreTracer":{ 251 "DatabaseNameReporting":{"Enabled":true}, 252 "InstanceReporting":{"Enabled":true}, 253 "QueryParameters":{"Enabled":true}, 254 "SlowQuery":{ 255 "Enabled":true, 256 "Threshold":10000000 257 } 258 }, 259 "DistributedTracer":{"Enabled":false}, 260 "Enabled":true, 261 "ErrorCollector":{ 262 "Attributes":{"Enabled":true,"Exclude":null,"Include":null}, 263 "CaptureEvents":true, 264 "Enabled":true, 265 "IgnoreStatusCodes":null 266 }, 267 "HighSecurity":false, 268 "HostDisplayName":"", 269 "Labels":null, 270 "Logger":null, 271 "RuntimeSampler":{"Enabled":true}, 272 "SecurityPoliciesToken":"", 273 "ServerlessMode":{ 274 "AccountID":"", 275 "ApdexThreshold":500000000, 276 "Enabled":false, 277 "PrimaryAppID":"", 278 "TrustedAccountKey":"" 279 }, 280 "SpanEvents":{ 281 "Attributes":{"Enabled":true,"Exclude":null,"Include":null}, 282 "Enabled":true 283 }, 284 "TransactionEvents":{ 285 "Attributes":{"Enabled":true,"Exclude":null,"Include":null}, 286 "Enabled":true, 287 "MaxSamplesStored": 10000 288 }, 289 "TransactionTracer":{ 290 "Attributes":{"Enabled":true,"Exclude":null,"Include":null}, 291 "Enabled":true, 292 "SegmentThreshold":2000000, 293 "Segments":{"Attributes":{"Enabled":true,"Exclude":null,"Include":null}}, 294 "StackTraceThreshold":500000000, 295 "Threshold":{ 296 "Duration":500000000, 297 "IsApdexFailing":true 298 } 299 }, 300 "Transport":null, 301 "Utilization":{ 302 "BillingHostname":"", 303 "DetectAWS":true, 304 "DetectAzure":true, 305 "DetectDocker":true, 306 "DetectGCP":true, 307 "DetectKubernetes":true, 308 "DetectPCF":true, 309 "LogicalProcessors":0, 310 "TotalRAMMIB":0 311 }, 312 "browser_monitoring.loader":"rum" 313 }, 314 "app_name":["my appname"], 315 "high_security":false, 316 "environment":[ 317 ["runtime.Compiler","comp"], 318 ["runtime.GOARCH","arch"], 319 ["runtime.GOOS","goos"], 320 ["runtime.Version","vers"], 321 ["runtime.NumCPU",8] 322 ], 323 "identifier":"my appname", 324 "utilization":{ 325 "metadata_version":5, 326 "logical_processors":16, 327 "total_ram_mib":1024, 328 "hostname":"my-hostname" 329 }, 330 "metadata":{}, 331 "event_harvest_config": { 332 "report_period_ms": 60000, 333 "harvest_limits": { 334 "analytic_event_data": 10000, 335 "custom_event_data": 10000, 336 "error_event_data": 100 337 } 338 } 339 }]`) 340 341 metadata := map[string]string{} 342 js, err := configConnectJSONInternal(cp, 123, &utilization.SampleData, internal.SampleEnvironment, "0.2.2", nil, metadata) 343 if nil != err { 344 t.Fatal(err) 345 } 346 out := standardizeNumbers(string(js)) 347 if out != expect { 348 t.Error(string(js)) 349 } 350 } 351 352 func TestValidate(t *testing.T) { 353 c := Config{ 354 License: "0123456789012345678901234567890123456789", 355 AppName: "my app", 356 Enabled: true, 357 } 358 if err := c.Validate(); nil != err { 359 t.Error(err) 360 } 361 c = Config{ 362 License: "", 363 AppName: "my app", 364 Enabled: true, 365 } 366 if err := c.Validate(); err != errLicenseLen { 367 t.Error(err) 368 } 369 c = Config{ 370 License: "", 371 AppName: "my app", 372 Enabled: false, 373 } 374 if err := c.Validate(); nil != err { 375 t.Error(err) 376 } 377 c = Config{ 378 License: "wronglength", 379 AppName: "my app", 380 Enabled: true, 381 } 382 if err := c.Validate(); err != errLicenseLen { 383 t.Error(err) 384 } 385 c = Config{ 386 License: "0123456789012345678901234567890123456789", 387 AppName: "too;many;app;names", 388 Enabled: true, 389 } 390 if err := c.Validate(); err != errAppNameLimit { 391 t.Error(err) 392 } 393 c = Config{ 394 License: "0123456789012345678901234567890123456789", 395 AppName: "", 396 Enabled: true, 397 } 398 if err := c.Validate(); err != errAppNameMissing { 399 t.Error(err) 400 } 401 c = Config{ 402 License: "0123456789012345678901234567890123456789", 403 AppName: "", 404 Enabled: false, 405 } 406 if err := c.Validate(); err != nil { 407 t.Error(err) 408 } 409 c = Config{ 410 License: "0123456789012345678901234567890123456789", 411 AppName: "my app", 412 Enabled: true, 413 HighSecurity: true, 414 } 415 if err := c.Validate(); err != nil { 416 t.Error(err) 417 } 418 } 419 420 func TestValidateWithPoliciesToken(t *testing.T) { 421 c := Config{ 422 License: "0123456789012345678901234567890123456789", 423 AppName: "my app", 424 Enabled: true, 425 HighSecurity: true, 426 SecurityPoliciesToken: "0123456789", 427 } 428 if err := c.Validate(); err != errHighSecurityWithSecurityPolicies { 429 t.Error(err) 430 } 431 c = Config{ 432 License: "0123456789012345678901234567890123456789", 433 AppName: "my app", 434 Enabled: true, 435 SecurityPoliciesToken: "0123456789", 436 } 437 if err := c.Validate(); err != nil { 438 t.Error(err) 439 } 440 } 441 442 func TestGatherMetadata(t *testing.T) { 443 metadata := gatherMetadata(func() []string { return nil }) 444 if !reflect.DeepEqual(metadata, map[string]string{}) { 445 t.Error(metadata) 446 } 447 metadata = gatherMetadata(func() []string { 448 return []string{ 449 "NEW_RELIC_METADATA_ZIP=zap", 450 "NEW_RELIC_METADATA_PIZZA=cheese", 451 "NEW_RELIC_METADATA_=hello", 452 "NEW_RELIC_METADATA_LOTS_OF_EQUALS=one=two", 453 "NEW_RELIC_METADATA_", 454 "NEW_RELIC_METADATA_NO_EQUALS", 455 "NEW_RELIC_METADATA_EMPTY=", 456 "NEW_RELIC_", 457 "hello=world", 458 } 459 }) 460 if !reflect.DeepEqual(metadata, map[string]string{ 461 "NEW_RELIC_METADATA_ZIP": "zap", 462 "NEW_RELIC_METADATA_PIZZA": "cheese", 463 "NEW_RELIC_METADATA_": "hello", 464 "NEW_RELIC_METADATA_LOTS_OF_EQUALS": "one=two", 465 "NEW_RELIC_METADATA_EMPTY": "", 466 }) { 467 t.Error(metadata) 468 } 469 } 470 471 func TestValidateServerless(t *testing.T) { 472 // AppName and License can be empty in serverless mode. 473 c := NewConfig("", "") 474 c.ServerlessMode.Enabled = true 475 if err := c.Validate(); nil != err { 476 t.Error(err) 477 } 478 }