github.com/lulzWill/go-agent@v2.1.2+incompatible/internal_errors_test.go (about)

     1  package newrelic
     2  
     3  import (
     4  	"runtime"
     5  	"strconv"
     6  	"testing"
     7  
     8  	"github.com/lulzWill/go-agent/internal"
     9  )
    10  
    11  type myError struct{}
    12  
    13  func (e myError) Error() string { return "my msg" }
    14  
    15  func TestNoticeErrorBackground(t *testing.T) {
    16  	app := testApp(nil, nil, t)
    17  	txn := app.StartTransaction("hello", nil, nil)
    18  	err := txn.NoticeError(myError{})
    19  	if nil != err {
    20  		t.Error(err)
    21  	}
    22  	txn.End()
    23  	app.ExpectErrors(t, []internal.WantError{{
    24  		TxnName: "OtherTransaction/Go/hello",
    25  		Msg:     "my msg",
    26  		Klass:   "newrelic.myError",
    27  		Caller:  "go-agent.TestNoticeErrorBackground",
    28  		URL:     "",
    29  	}})
    30  	app.ExpectErrorEvents(t, []internal.WantEvent{{
    31  		Intrinsics: map[string]interface{}{
    32  			"error.class":     "newrelic.myError",
    33  			"error.message":   "my msg",
    34  			"transactionName": "OtherTransaction/Go/hello",
    35  		},
    36  	}})
    37  	app.ExpectMetrics(t, backgroundErrorMetrics)
    38  }
    39  
    40  func TestNoticeErrorWeb(t *testing.T) {
    41  	app := testApp(nil, nil, t)
    42  	txn := app.StartTransaction("hello", nil, helloRequest)
    43  	err := txn.NoticeError(myError{})
    44  	if nil != err {
    45  		t.Error(err)
    46  	}
    47  	txn.End()
    48  	app.ExpectErrors(t, []internal.WantError{{
    49  		TxnName: "WebTransaction/Go/hello",
    50  		Msg:     "my msg",
    51  		Klass:   "newrelic.myError",
    52  		Caller:  "go-agent.TestNoticeErrorWeb",
    53  		URL:     "/hello",
    54  	}})
    55  	app.ExpectErrorEvents(t, []internal.WantEvent{{
    56  		Intrinsics: map[string]interface{}{
    57  			"error.class":     "newrelic.myError",
    58  			"error.message":   "my msg",
    59  			"transactionName": "WebTransaction/Go/hello",
    60  		},
    61  	}})
    62  	app.ExpectMetrics(t, webErrorMetrics)
    63  }
    64  
    65  func TestNoticeErrorTxnEnded(t *testing.T) {
    66  	app := testApp(nil, nil, t)
    67  	txn := app.StartTransaction("hello", nil, nil)
    68  	txn.End()
    69  	err := txn.NoticeError(myError{})
    70  	if err != errAlreadyEnded {
    71  		t.Error(err)
    72  	}
    73  	txn.End()
    74  	app.ExpectErrors(t, []internal.WantError{})
    75  	app.ExpectErrorEvents(t, []internal.WantEvent{})
    76  	app.ExpectMetrics(t, backgroundMetrics)
    77  }
    78  
    79  func TestNoticeErrorHighSecurity(t *testing.T) {
    80  	cfgFn := func(cfg *Config) { cfg.HighSecurity = true }
    81  	app := testApp(nil, cfgFn, t)
    82  	txn := app.StartTransaction("hello", nil, nil)
    83  	err := txn.NoticeError(myError{})
    84  	if nil != err {
    85  		t.Error(err)
    86  	}
    87  	txn.End()
    88  	app.ExpectErrors(t, []internal.WantError{{
    89  		TxnName: "OtherTransaction/Go/hello",
    90  		Msg:     highSecurityErrorMsg,
    91  		Klass:   "newrelic.myError",
    92  		Caller:  "go-agent.TestNoticeErrorHighSecurity",
    93  	}})
    94  	app.ExpectErrorEvents(t, []internal.WantEvent{{
    95  		Intrinsics: map[string]interface{}{
    96  			"error.class":     "newrelic.myError",
    97  			"error.message":   highSecurityErrorMsg,
    98  			"transactionName": "OtherTransaction/Go/hello",
    99  		},
   100  	}})
   101  	app.ExpectMetrics(t, backgroundErrorMetrics)
   102  }
   103  
   104  func TestNoticeErrorMessageSecurityPolicy(t *testing.T) {
   105  	replyfn := func(reply *internal.ConnectReply) { reply.SecurityPolicies.AllowRawExceptionMessages.SetEnabled(false) }
   106  	app := testApp(replyfn, nil, t)
   107  	txn := app.StartTransaction("hello", nil, nil)
   108  	err := txn.NoticeError(myError{})
   109  	if nil != err {
   110  		t.Error(err)
   111  	}
   112  	txn.End()
   113  	app.ExpectErrors(t, []internal.WantError{{
   114  		TxnName: "OtherTransaction/Go/hello",
   115  		Msg:     securityPolicyErrorMsg,
   116  		Klass:   "newrelic.myError",
   117  		Caller:  "go-agent.TestNoticeErrorMessageSecurityPolicy",
   118  	}})
   119  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   120  		Intrinsics: map[string]interface{}{
   121  			"error.class":     "newrelic.myError",
   122  			"error.message":   securityPolicyErrorMsg,
   123  			"transactionName": "OtherTransaction/Go/hello",
   124  		},
   125  	}})
   126  	app.ExpectMetrics(t, backgroundErrorMetrics)
   127  }
   128  
   129  func TestNoticeErrorLocallyDisabled(t *testing.T) {
   130  	cfgFn := func(cfg *Config) { cfg.ErrorCollector.Enabled = false }
   131  	app := testApp(nil, cfgFn, t)
   132  	txn := app.StartTransaction("hello", nil, nil)
   133  	err := txn.NoticeError(myError{})
   134  	if errorsLocallyDisabled != err {
   135  		t.Error(err)
   136  	}
   137  	txn.End()
   138  	app.ExpectErrors(t, []internal.WantError{})
   139  	app.ExpectErrorEvents(t, []internal.WantEvent{})
   140  	app.ExpectMetrics(t, backgroundMetrics)
   141  }
   142  
   143  func TestNoticeErrorRemotelyDisabled(t *testing.T) {
   144  	replyfn := func(reply *internal.ConnectReply) { reply.CollectErrors = false }
   145  	app := testApp(replyfn, nil, t)
   146  	txn := app.StartTransaction("hello", nil, nil)
   147  	err := txn.NoticeError(myError{})
   148  	if errorsRemotelyDisabled != err {
   149  		t.Error(err)
   150  	}
   151  	txn.End()
   152  	app.ExpectErrors(t, []internal.WantError{})
   153  	app.ExpectErrorEvents(t, []internal.WantEvent{})
   154  	app.ExpectMetrics(t, backgroundMetrics)
   155  }
   156  
   157  func TestNoticeErrorNil(t *testing.T) {
   158  	app := testApp(nil, nil, t)
   159  	txn := app.StartTransaction("hello", nil, nil)
   160  	err := txn.NoticeError(nil)
   161  	if errNilError != err {
   162  		t.Error(err)
   163  	}
   164  	txn.End()
   165  	app.ExpectErrors(t, []internal.WantError{})
   166  	app.ExpectErrorEvents(t, []internal.WantEvent{})
   167  	app.ExpectMetrics(t, backgroundMetrics)
   168  }
   169  
   170  func TestNoticeErrorEventsLocallyDisabled(t *testing.T) {
   171  	cfgFn := func(cfg *Config) { cfg.ErrorCollector.CaptureEvents = false }
   172  	app := testApp(nil, cfgFn, t)
   173  	txn := app.StartTransaction("hello", nil, nil)
   174  	err := txn.NoticeError(myError{})
   175  	if nil != err {
   176  		t.Error(err)
   177  	}
   178  	txn.End()
   179  	app.ExpectErrors(t, []internal.WantError{{
   180  		TxnName: "OtherTransaction/Go/hello",
   181  		Msg:     "my msg",
   182  		Klass:   "newrelic.myError",
   183  		Caller:  "go-agent.TestNoticeErrorEventsLocallyDisabled",
   184  	}})
   185  	app.ExpectErrorEvents(t, []internal.WantEvent{})
   186  	app.ExpectMetrics(t, backgroundErrorMetrics)
   187  }
   188  
   189  func TestNoticeErrorEventsRemotelyDisabled(t *testing.T) {
   190  	replyfn := func(reply *internal.ConnectReply) { reply.CollectErrorEvents = false }
   191  	app := testApp(replyfn, nil, t)
   192  	txn := app.StartTransaction("hello", nil, nil)
   193  	err := txn.NoticeError(myError{})
   194  	if nil != err {
   195  		t.Error(err)
   196  	}
   197  	txn.End()
   198  	app.ExpectErrors(t, []internal.WantError{{
   199  		TxnName: "OtherTransaction/Go/hello",
   200  		Msg:     "my msg",
   201  		Klass:   "newrelic.myError",
   202  		Caller:  "go-agent.TestNoticeErrorEventsRemotelyDisabled",
   203  	}})
   204  	app.ExpectErrorEvents(t, []internal.WantEvent{})
   205  	app.ExpectMetrics(t, backgroundErrorMetrics)
   206  }
   207  
   208  type errorWithClass struct{ class string }
   209  
   210  func (e errorWithClass) Error() string      { return "my msg" }
   211  func (e errorWithClass) ErrorClass() string { return e.class }
   212  
   213  func TestErrorWithClasser(t *testing.T) {
   214  	app := testApp(nil, nil, t)
   215  	txn := app.StartTransaction("hello", nil, nil)
   216  	err := txn.NoticeError(errorWithClass{class: "zap"})
   217  	if nil != err {
   218  		t.Error(err)
   219  	}
   220  	txn.End()
   221  	app.ExpectErrors(t, []internal.WantError{{
   222  		TxnName: "OtherTransaction/Go/hello",
   223  		Msg:     "my msg",
   224  		Klass:   "zap",
   225  		Caller:  "go-agent.TestErrorWithClasser",
   226  		URL:     "",
   227  	}})
   228  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   229  		Intrinsics: map[string]interface{}{
   230  			"error.class":     "zap",
   231  			"error.message":   "my msg",
   232  			"transactionName": "OtherTransaction/Go/hello",
   233  		},
   234  	}})
   235  	app.ExpectMetrics(t, backgroundErrorMetrics)
   236  }
   237  
   238  func TestErrorWithClasserReturnsEmpty(t *testing.T) {
   239  	app := testApp(nil, nil, t)
   240  	txn := app.StartTransaction("hello", nil, nil)
   241  	err := txn.NoticeError(errorWithClass{class: ""})
   242  	if nil != err {
   243  		t.Error(err)
   244  	}
   245  	txn.End()
   246  	app.ExpectErrors(t, []internal.WantError{{
   247  		TxnName: "OtherTransaction/Go/hello",
   248  		Msg:     "my msg",
   249  		Klass:   "newrelic.errorWithClass",
   250  		Caller:  "go-agent.TestErrorWithClasserReturnsEmpty",
   251  		URL:     "",
   252  	}})
   253  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   254  		Intrinsics: map[string]interface{}{
   255  			"error.class":     "newrelic.errorWithClass",
   256  			"error.message":   "my msg",
   257  			"transactionName": "OtherTransaction/Go/hello",
   258  		},
   259  	}})
   260  	app.ExpectMetrics(t, backgroundErrorMetrics)
   261  }
   262  
   263  type withStackTrace struct{ trace []uintptr }
   264  
   265  func makeErrorWithStackTrace() error {
   266  	callers := make([]uintptr, 20)
   267  	written := runtime.Callers(1, callers)
   268  	return withStackTrace{
   269  		trace: callers[0:written],
   270  	}
   271  }
   272  
   273  func (e withStackTrace) Error() string         { return "my msg" }
   274  func (e withStackTrace) StackTrace() []uintptr { return e.trace }
   275  
   276  func TestErrorWithStackTrace(t *testing.T) {
   277  	app := testApp(nil, nil, t)
   278  	txn := app.StartTransaction("hello", nil, nil)
   279  	e := makeErrorWithStackTrace()
   280  	err := txn.NoticeError(e)
   281  	if nil != err {
   282  		t.Error(err)
   283  	}
   284  	txn.End()
   285  	app.ExpectErrors(t, []internal.WantError{{
   286  		TxnName: "OtherTransaction/Go/hello",
   287  		Msg:     "my msg",
   288  		Klass:   "newrelic.withStackTrace",
   289  		Caller:  "go-agent.makeErrorWithStackTrace",
   290  		URL:     "",
   291  	}})
   292  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   293  		Intrinsics: map[string]interface{}{
   294  			"error.class":     "newrelic.withStackTrace",
   295  			"error.message":   "my msg",
   296  			"transactionName": "OtherTransaction/Go/hello",
   297  		},
   298  	}})
   299  	app.ExpectMetrics(t, backgroundErrorMetrics)
   300  }
   301  
   302  func TestErrorWithStackTraceReturnsNil(t *testing.T) {
   303  	app := testApp(nil, nil, t)
   304  	txn := app.StartTransaction("hello", nil, nil)
   305  	e := withStackTrace{trace: nil}
   306  	err := txn.NoticeError(e)
   307  	if nil != err {
   308  		t.Error(err)
   309  	}
   310  	txn.End()
   311  	app.ExpectErrors(t, []internal.WantError{{
   312  		TxnName: "OtherTransaction/Go/hello",
   313  		Msg:     "my msg",
   314  		Klass:   "newrelic.withStackTrace",
   315  		Caller:  "go-agent.TestErrorWithStackTraceReturnsNil",
   316  		URL:     "",
   317  	}})
   318  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   319  		Intrinsics: map[string]interface{}{
   320  			"error.class":     "newrelic.withStackTrace",
   321  			"error.message":   "my msg",
   322  			"transactionName": "OtherTransaction/Go/hello",
   323  		},
   324  	}})
   325  	app.ExpectMetrics(t, backgroundErrorMetrics)
   326  }
   327  
   328  func TestNewrelicErrorNoAttributes(t *testing.T) {
   329  	app := testApp(nil, nil, t)
   330  	txn := app.StartTransaction("hello", nil, nil)
   331  	err := txn.NoticeError(Error{
   332  		Message: "my msg",
   333  		Class:   "my class",
   334  	})
   335  	if nil != err {
   336  		t.Error(err)
   337  	}
   338  	txn.End()
   339  	app.ExpectErrors(t, []internal.WantError{{
   340  		TxnName: "OtherTransaction/Go/hello",
   341  		Msg:     "my msg",
   342  		Klass:   "my class",
   343  		Caller:  "go-agent.TestNewrelicErrorNoAttributes",
   344  		URL:     "",
   345  	}})
   346  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   347  		Intrinsics: map[string]interface{}{
   348  			"error.class":     "my class",
   349  			"error.message":   "my msg",
   350  			"transactionName": "OtherTransaction/Go/hello",
   351  		},
   352  	}})
   353  	app.ExpectMetrics(t, backgroundErrorMetrics)
   354  }
   355  
   356  func TestNewrelicErrorValidAttributes(t *testing.T) {
   357  	extraAttributes := map[string]interface{}{
   358  		"zip": "zap",
   359  	}
   360  	app := testApp(nil, nil, t)
   361  	txn := app.StartTransaction("hello", nil, nil)
   362  	err := txn.NoticeError(Error{
   363  		Message:    "my msg",
   364  		Class:      "my class",
   365  		Attributes: extraAttributes,
   366  	})
   367  	if nil != err {
   368  		t.Error(err)
   369  	}
   370  	txn.End()
   371  	app.ExpectErrors(t, []internal.WantError{{
   372  		TxnName:        "OtherTransaction/Go/hello",
   373  		Msg:            "my msg",
   374  		Klass:          "my class",
   375  		Caller:         "go-agent.TestNewrelicErrorValidAttributes",
   376  		URL:            "",
   377  		UserAttributes: extraAttributes,
   378  	}})
   379  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   380  		Intrinsics: map[string]interface{}{
   381  			"error.class":     "my class",
   382  			"error.message":   "my msg",
   383  			"transactionName": "OtherTransaction/Go/hello",
   384  		},
   385  		UserAttributes: extraAttributes,
   386  	}})
   387  	app.ExpectMetrics(t, backgroundErrorMetrics)
   388  }
   389  
   390  func TestNewrelicErrorAttributesHighSecurity(t *testing.T) {
   391  	extraAttributes := map[string]interface{}{
   392  		"zip": "zap",
   393  	}
   394  	cfgFn := func(cfg *Config) { cfg.HighSecurity = true }
   395  	app := testApp(nil, cfgFn, t)
   396  	txn := app.StartTransaction("hello", nil, nil)
   397  	err := txn.NoticeError(Error{
   398  		Message:    "my msg",
   399  		Class:      "my class",
   400  		Attributes: extraAttributes,
   401  	})
   402  	if nil != err {
   403  		t.Error(err)
   404  	}
   405  	txn.End()
   406  	app.ExpectErrors(t, []internal.WantError{{
   407  		TxnName:        "OtherTransaction/Go/hello",
   408  		Msg:            "message removed by high security setting",
   409  		Klass:          "my class",
   410  		Caller:         "go-agent.TestNewrelicErrorAttributesHighSecurity",
   411  		URL:            "",
   412  		UserAttributes: map[string]interface{}{},
   413  	}})
   414  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   415  		Intrinsics: map[string]interface{}{
   416  			"error.class":     "my class",
   417  			"error.message":   "message removed by high security setting",
   418  			"transactionName": "OtherTransaction/Go/hello",
   419  		},
   420  		UserAttributes: map[string]interface{}{},
   421  	}})
   422  	app.ExpectMetrics(t, backgroundErrorMetrics)
   423  }
   424  
   425  func TestNewrelicErrorAttributesSecurityPolicy(t *testing.T) {
   426  	extraAttributes := map[string]interface{}{
   427  		"zip": "zap",
   428  	}
   429  	replyfn := func(reply *internal.ConnectReply) { reply.SecurityPolicies.CustomParameters.SetEnabled(false) }
   430  	app := testApp(replyfn, nil, t)
   431  	txn := app.StartTransaction("hello", nil, nil)
   432  	err := txn.NoticeError(Error{
   433  		Message:    "my msg",
   434  		Class:      "my class",
   435  		Attributes: extraAttributes,
   436  	})
   437  	if nil != err {
   438  		t.Error(err)
   439  	}
   440  	txn.End()
   441  	app.ExpectErrors(t, []internal.WantError{{
   442  		TxnName:        "OtherTransaction/Go/hello",
   443  		Msg:            "my msg",
   444  		Klass:          "my class",
   445  		Caller:         "go-agent.TestNewrelicErrorAttributesSecurityPolicy",
   446  		URL:            "",
   447  		UserAttributes: map[string]interface{}{},
   448  	}})
   449  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   450  		Intrinsics: map[string]interface{}{
   451  			"error.class":     "my class",
   452  			"error.message":   "my msg",
   453  			"transactionName": "OtherTransaction/Go/hello",
   454  		},
   455  		UserAttributes: map[string]interface{}{},
   456  	}})
   457  	app.ExpectMetrics(t, backgroundErrorMetrics)
   458  }
   459  
   460  func TestNewrelicErrorAttributeOverridesNormalAttribute(t *testing.T) {
   461  	extraAttributes := map[string]interface{}{
   462  		"zip": "zap",
   463  	}
   464  	app := testApp(nil, nil, t)
   465  	txn := app.StartTransaction("hello", nil, nil)
   466  	if err := txn.AddAttribute("zip", 123); nil != err {
   467  		t.Error(err)
   468  	}
   469  	err := txn.NoticeError(Error{
   470  		Message:    "my msg",
   471  		Class:      "my class",
   472  		Attributes: extraAttributes,
   473  	})
   474  	if nil != err {
   475  		t.Error(err)
   476  	}
   477  	txn.End()
   478  	app.ExpectErrors(t, []internal.WantError{{
   479  		TxnName:        "OtherTransaction/Go/hello",
   480  		Msg:            "my msg",
   481  		Klass:          "my class",
   482  		Caller:         "go-agent.TestNewrelicErrorAttributeOverridesNormalAttribute",
   483  		URL:            "",
   484  		UserAttributes: extraAttributes,
   485  	}})
   486  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   487  		Intrinsics: map[string]interface{}{
   488  			"error.class":     "my class",
   489  			"error.message":   "my msg",
   490  			"transactionName": "OtherTransaction/Go/hello",
   491  		},
   492  		UserAttributes: extraAttributes,
   493  	}})
   494  	app.ExpectMetrics(t, backgroundErrorMetrics)
   495  }
   496  
   497  func TestNewrelicErrorInvalidAttributes(t *testing.T) {
   498  	extraAttributes := map[string]interface{}{
   499  		"zip":     "zap",
   500  		"INVALID": struct{}{},
   501  	}
   502  	app := testApp(nil, nil, t)
   503  	txn := app.StartTransaction("hello", nil, nil)
   504  	err := txn.NoticeError(Error{
   505  		Message:    "my msg",
   506  		Class:      "my class",
   507  		Attributes: extraAttributes,
   508  	})
   509  	if _, ok := err.(internal.ErrInvalidAttributeType); !ok {
   510  		t.Error(err)
   511  	}
   512  	txn.End()
   513  	app.ExpectErrors(t, []internal.WantError{})
   514  	app.ExpectErrorEvents(t, []internal.WantEvent{})
   515  	app.ExpectMetrics(t, backgroundMetrics)
   516  }
   517  
   518  func TestExtraErrorAttributeRemovedThroughConfiguration(t *testing.T) {
   519  	cfgfn := func(cfg *Config) {
   520  		cfg.ErrorCollector.Attributes.Exclude = []string{"IGNORE_ME"}
   521  	}
   522  	app := testApp(nil, cfgfn, t)
   523  	txn := app.StartTransaction("hello", nil, nil)
   524  	err := txn.NoticeError(Error{
   525  		Message: "my msg",
   526  		Class:   "my class",
   527  		Attributes: map[string]interface{}{
   528  			"zip":       "zap",
   529  			"IGNORE_ME": 123,
   530  		},
   531  	})
   532  	if nil != err {
   533  		t.Error(err)
   534  	}
   535  	txn.End()
   536  	app.ExpectErrors(t, []internal.WantError{{
   537  		TxnName:        "OtherTransaction/Go/hello",
   538  		Msg:            "my msg",
   539  		Klass:          "my class",
   540  		Caller:         "go-agent.TestExtraErrorAttributeRemovedThroughConfiguration",
   541  		URL:            "",
   542  		UserAttributes: map[string]interface{}{"zip": "zap"},
   543  	}})
   544  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   545  		Intrinsics: map[string]interface{}{
   546  			"error.class":     "my class",
   547  			"error.message":   "my msg",
   548  			"transactionName": "OtherTransaction/Go/hello",
   549  		},
   550  		UserAttributes: map[string]interface{}{"zip": "zap"},
   551  	}})
   552  	app.ExpectMetrics(t, backgroundErrorMetrics)
   553  
   554  }
   555  
   556  func TestTooManyExtraErrorAttributes(t *testing.T) {
   557  	attrs := make(map[string]interface{})
   558  	for i := 0; i <= internal.AttributeErrorLimit; i++ {
   559  		attrs[strconv.Itoa(i)] = i
   560  	}
   561  	app := testApp(nil, nil, t)
   562  	txn := app.StartTransaction("hello", nil, nil)
   563  	err := txn.NoticeError(Error{
   564  		Message:    "my msg",
   565  		Class:      "my class",
   566  		Attributes: attrs,
   567  	})
   568  	if errTooManyErrorAttributes != err {
   569  		t.Error(err)
   570  	}
   571  	txn.End()
   572  	app.ExpectErrors(t, []internal.WantError{})
   573  	app.ExpectErrorEvents(t, []internal.WantEvent{})
   574  	app.ExpectMetrics(t, backgroundMetrics)
   575  }