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  }