github.com/newrelic/go-agent@v3.26.0+incompatible/internal/errors_test.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package internal 5 6 import ( 7 "encoding/json" 8 "errors" 9 "testing" 10 "time" 11 ) 12 13 var ( 14 emptyStackTrace = make([]uintptr, 0) 15 ) 16 17 func testExpectedJSON(t testing.TB, expect string, actual string) { 18 // Type assertion to support early Go versions. 19 if h, ok := t.(interface { 20 Helper() 21 }); ok { 22 h.Helper() 23 } 24 compactExpect := CompactJSONString(expect) 25 if compactExpect != actual { 26 t.Errorf("\nexpect=%s\nactual=%s\n", compactExpect, actual) 27 } 28 } 29 30 func TestErrorTraceMarshal(t *testing.T) { 31 he := &tracedError{ 32 ErrorData: ErrorData{ 33 When: time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC), 34 Stack: emptyStackTrace, 35 Msg: "my_msg", 36 Klass: "my_class", 37 }, 38 TxnEvent: TxnEvent{ 39 FinalName: "my_txn_name", 40 Attrs: nil, 41 BetterCAT: BetterCAT{ 42 Enabled: true, 43 ID: "txn-id", 44 Priority: 0.5, 45 }, 46 TotalTime: 2 * time.Second, 47 }, 48 } 49 js, err := json.Marshal(he) 50 if nil != err { 51 t.Error(err) 52 } 53 54 expect := ` 55 [ 56 1.41713646e+12, 57 "my_txn_name", 58 "my_msg", 59 "my_class", 60 { 61 "agentAttributes":{}, 62 "userAttributes":{}, 63 "intrinsics":{ 64 "totalTime":2, 65 "guid":"txn-id", 66 "traceId":"txn-id", 67 "priority":0.500000, 68 "sampled":false 69 }, 70 "stack_trace":[] 71 } 72 ]` 73 testExpectedJSON(t, expect, string(js)) 74 } 75 76 func TestErrorTraceMarshalOldCAT(t *testing.T) { 77 he := &tracedError{ 78 ErrorData: ErrorData{ 79 When: time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC), 80 Stack: emptyStackTrace, 81 Msg: "my_msg", 82 Klass: "my_class", 83 }, 84 TxnEvent: TxnEvent{ 85 FinalName: "my_txn_name", 86 Attrs: nil, 87 BetterCAT: BetterCAT{ 88 Enabled: false, 89 }, 90 TotalTime: 2 * time.Second, 91 }, 92 } 93 js, err := json.Marshal(he) 94 if nil != err { 95 t.Error(err) 96 } 97 98 expect := ` 99 [ 100 1.41713646e+12, 101 "my_txn_name", 102 "my_msg", 103 "my_class", 104 { 105 "agentAttributes":{}, 106 "userAttributes":{}, 107 "intrinsics":{ 108 "totalTime":2 109 }, 110 "stack_trace":[] 111 } 112 ]` 113 testExpectedJSON(t, expect, string(js)) 114 } 115 116 func TestErrorTraceAttributes(t *testing.T) { 117 aci := sampleAttributeConfigInput 118 aci.ErrorCollector.Exclude = append(aci.ErrorCollector.Exclude, "zap") 119 aci.ErrorCollector.Exclude = append(aci.ErrorCollector.Exclude, AttributeHostDisplayName.name()) 120 cfg := CreateAttributeConfig(aci, true) 121 attr := NewAttributes(cfg) 122 attr.Agent.Add(AttributeHostDisplayName, "exclude me", nil) 123 attr.Agent.Add(attributeRequestURI, "my_request_uri", nil) 124 AddUserAttribute(attr, "zap", 123, DestAll) 125 AddUserAttribute(attr, "zip", 456, DestAll) 126 127 he := &tracedError{ 128 ErrorData: ErrorData{ 129 When: time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC), 130 Stack: nil, 131 Msg: "my_msg", 132 Klass: "my_class", 133 }, 134 TxnEvent: TxnEvent{ 135 FinalName: "my_txn_name", 136 Attrs: attr, 137 BetterCAT: BetterCAT{ 138 Enabled: true, 139 ID: "txn-id", 140 Priority: 0.5, 141 }, 142 TotalTime: 2 * time.Second, 143 }, 144 } 145 js, err := json.Marshal(he) 146 if nil != err { 147 t.Error(err) 148 } 149 expect := ` 150 [ 151 1.41713646e+12, 152 "my_txn_name", 153 "my_msg", 154 "my_class", 155 { 156 "agentAttributes":{"request.uri":"my_request_uri"}, 157 "userAttributes":{"zip":456}, 158 "intrinsics":{ 159 "totalTime":2, 160 "guid":"txn-id", 161 "traceId":"txn-id", 162 "priority":0.500000, 163 "sampled":false 164 } 165 } 166 ]` 167 testExpectedJSON(t, expect, string(js)) 168 } 169 170 func TestErrorTraceAttributesOldCAT(t *testing.T) { 171 aci := sampleAttributeConfigInput 172 aci.ErrorCollector.Exclude = append(aci.ErrorCollector.Exclude, "zap") 173 aci.ErrorCollector.Exclude = append(aci.ErrorCollector.Exclude, AttributeHostDisplayName.name()) 174 cfg := CreateAttributeConfig(aci, true) 175 attr := NewAttributes(cfg) 176 attr.Agent.Add(AttributeHostDisplayName, "exclude me", nil) 177 attr.Agent.Add(attributeRequestURI, "my_request_uri", nil) 178 AddUserAttribute(attr, "zap", 123, DestAll) 179 AddUserAttribute(attr, "zip", 456, DestAll) 180 181 he := &tracedError{ 182 ErrorData: ErrorData{ 183 When: time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC), 184 Stack: nil, 185 Msg: "my_msg", 186 Klass: "my_class", 187 }, 188 TxnEvent: TxnEvent{ 189 FinalName: "my_txn_name", 190 Attrs: attr, 191 BetterCAT: BetterCAT{ 192 Enabled: false, 193 }, 194 TotalTime: 2 * time.Second, 195 }, 196 } 197 js, err := json.Marshal(he) 198 if nil != err { 199 t.Error(err) 200 } 201 expect := ` 202 [ 203 1.41713646e+12, 204 "my_txn_name", 205 "my_msg", 206 "my_class", 207 { 208 "agentAttributes":{"request.uri":"my_request_uri"}, 209 "userAttributes":{"zip":456}, 210 "intrinsics":{ 211 "totalTime":2 212 } 213 } 214 ]` 215 testExpectedJSON(t, expect, string(js)) 216 } 217 218 func TestErrorsLifecycle(t *testing.T) { 219 ers := NewTxnErrors(5) 220 221 when := time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC) 222 ers.Add(TxnErrorFromResponseCode(when, 15)) 223 ers.Add(TxnErrorFromResponseCode(when, 400)) 224 ers.Add(TxnErrorFromPanic(when, errors.New("oh no panic"))) 225 ers.Add(TxnErrorFromPanic(when, 123)) 226 ers.Add(TxnErrorFromPanic(when, 123)) 227 228 he := newHarvestErrors(4) 229 MergeTxnErrors(&he, ers, TxnEvent{ 230 FinalName: "txnName", 231 Attrs: nil, 232 BetterCAT: BetterCAT{ 233 Enabled: true, 234 ID: "txn-id", 235 Priority: 0.5, 236 }, 237 TotalTime: 2 * time.Second, 238 }) 239 js, err := he.Data("agentRunID", time.Now()) 240 if nil != err { 241 t.Error(err) 242 } 243 expect := CompactJSONString(` 244 [ 245 "agentRunID", 246 [ 247 [ 248 1.41713646e+12, 249 "txnName", 250 "response code 15", 251 "15", 252 { 253 "agentAttributes":{}, 254 "userAttributes":{}, 255 "intrinsics":{ 256 "totalTime":2, 257 "guid":"txn-id", 258 "traceId":"txn-id", 259 "priority":0.500000, 260 "sampled":false 261 } 262 } 263 ], 264 [ 265 1.41713646e+12, 266 "txnName", 267 "Bad Request", 268 "400", 269 { 270 "agentAttributes":{}, 271 "userAttributes":{}, 272 "intrinsics":{ 273 "totalTime":2, 274 "guid":"txn-id", 275 "traceId":"txn-id", 276 "priority":0.500000, 277 "sampled":false 278 } 279 } 280 ], 281 [ 282 1.41713646e+12, 283 "txnName", 284 "oh no panic", 285 "panic", 286 { 287 "agentAttributes":{}, 288 "userAttributes":{}, 289 "intrinsics":{ 290 "totalTime":2, 291 "guid":"txn-id", 292 "traceId":"txn-id", 293 "priority":0.500000, 294 "sampled":false 295 } 296 } 297 ], 298 [ 299 1.41713646e+12, 300 "txnName", 301 "123", 302 "panic", 303 { 304 "agentAttributes":{}, 305 "userAttributes":{}, 306 "intrinsics":{ 307 "totalTime":2, 308 "guid":"txn-id", 309 "traceId":"txn-id", 310 "priority":0.500000, 311 "sampled":false 312 } 313 } 314 ] 315 ] 316 ]`) 317 if string(js) != expect { 318 t.Error(string(js), expect) 319 } 320 } 321 322 func BenchmarkErrorsJSON(b *testing.B) { 323 when := time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC) 324 max := 20 325 ers := NewTxnErrors(max) 326 327 for i := 0; i < max; i++ { 328 ers.Add(ErrorData{ 329 When: time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC), 330 Msg: "error message", 331 Klass: "error class", 332 }) 333 } 334 335 cfg := CreateAttributeConfig(sampleAttributeConfigInput, true) 336 attr := NewAttributes(cfg) 337 attr.Agent.Add(attributeRequestMethod, "GET", nil) 338 AddUserAttribute(attr, "zip", 456, DestAll) 339 340 he := newHarvestErrors(max) 341 MergeTxnErrors(&he, ers, TxnEvent{ 342 FinalName: "WebTransaction/Go/hello", 343 Attrs: attr, 344 }) 345 346 b.ReportAllocs() 347 b.ResetTimer() 348 349 for n := 0; n < b.N; n++ { 350 js, err := he.Data("agentRundID", when) 351 if nil != err || nil == js { 352 b.Fatal(err, js) 353 } 354 } 355 }