github.com/newrelic/go-agent@v3.26.0+incompatible/internal_attributes_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  	"errors"
     8  	"net/http"
     9  	"net/url"
    10  	"testing"
    11  
    12  	"github.com/newrelic/go-agent/internal"
    13  )
    14  
    15  func TestAddAttributeHighSecurity(t *testing.T) {
    16  	cfgfn := func(cfg *Config) {
    17  		cfg.HighSecurity = true
    18  	}
    19  	app := testApp(nil, cfgfn, t)
    20  	txn := app.StartTransaction("hello", nil, nil)
    21  
    22  	if err := txn.AddAttribute(`key`, 1); err != errHighSecurityEnabled {
    23  		t.Error(err)
    24  	}
    25  	txn.End()
    26  
    27  	app.ExpectTxnEvents(t, []internal.WantEvent{{
    28  		Intrinsics: map[string]interface{}{
    29  			"name": "OtherTransaction/Go/hello",
    30  		},
    31  		AgentAttributes: nil,
    32  		UserAttributes:  map[string]interface{}{},
    33  	}})
    34  }
    35  
    36  func TestAddAttributeSecurityPolicyDisablesParameters(t *testing.T) {
    37  	replyfn := func(reply *internal.ConnectReply) {
    38  		reply.SecurityPolicies.CustomParameters.SetEnabled(false)
    39  	}
    40  	app := testApp(replyfn, nil, t)
    41  	txn := app.StartTransaction("hello", nil, nil)
    42  
    43  	if err := txn.AddAttribute(`key`, 1); err != errSecurityPolicy {
    44  		t.Error(err)
    45  	}
    46  	txn.End()
    47  
    48  	app.ExpectTxnEvents(t, []internal.WantEvent{{
    49  		Intrinsics: map[string]interface{}{
    50  			"name": "OtherTransaction/Go/hello",
    51  		},
    52  		AgentAttributes: nil,
    53  		UserAttributes:  map[string]interface{}{},
    54  	}})
    55  }
    56  
    57  func TestAddAttributeSecurityPolicyDisablesInclude(t *testing.T) {
    58  	replyfn := func(reply *internal.ConnectReply) {
    59  		reply.SecurityPolicies.AttributesInclude.SetEnabled(false)
    60  	}
    61  	cfgfn := func(cfg *Config) {
    62  		cfg.TransactionEvents.Attributes.Include = append(cfg.TransactionEvents.Attributes.Include,
    63  			AttributeRequestUserAgent)
    64  	}
    65  	val := "dont-include-me-in-txn-events"
    66  	app := testApp(replyfn, cfgfn, t)
    67  	req := &http.Request{}
    68  	req.Header = make(http.Header)
    69  	req.Header.Add("User-Agent", val)
    70  	txn := app.StartTransaction("hello", nil, req)
    71  	txn.NoticeError(errors.New("hello"))
    72  	txn.End()
    73  	app.ExpectTxnEvents(t, []internal.WantEvent{{
    74  		Intrinsics: map[string]interface{}{
    75  			"name":             "WebTransaction/Go/hello",
    76  			"nr.apdexPerfZone": "F",
    77  		},
    78  		AgentAttributes: map[string]interface{}{},
    79  		UserAttributes:  map[string]interface{}{},
    80  	}})
    81  	app.ExpectErrors(t, []internal.WantError{{
    82  		TxnName:         "WebTransaction/Go/hello",
    83  		Msg:             "hello",
    84  		Klass:           "*errors.errorString",
    85  		AgentAttributes: map[string]interface{}{AttributeRequestUserAgent: val},
    86  		UserAttributes:  map[string]interface{}{},
    87  	}})
    88  }
    89  
    90  func TestUserAttributeBasics(t *testing.T) {
    91  	cfgfn := func(cfg *Config) {
    92  		cfg.TransactionTracer.Threshold.IsApdexFailing = false
    93  		cfg.TransactionTracer.Threshold.Duration = 0
    94  	}
    95  	app := testApp(nil, cfgfn, t)
    96  	txn := app.StartTransaction("hello", nil, nil)
    97  
    98  	txn.NoticeError(errors.New("zap"))
    99  
   100  	if err := txn.AddAttribute(`int\key`, 1); nil != err {
   101  		t.Error(err)
   102  	}
   103  	if err := txn.AddAttribute(`str\key`, `zip\zap`); nil != err {
   104  		t.Error(err)
   105  	}
   106  	err := txn.AddAttribute("invalid_value", struct{}{})
   107  	if _, ok := err.(internal.ErrInvalidAttributeType); !ok {
   108  		t.Error(err)
   109  	}
   110  	err = txn.AddAttribute("nil_value", nil)
   111  	if _, ok := err.(internal.ErrInvalidAttributeType); !ok {
   112  		t.Error(err)
   113  	}
   114  	txn.End()
   115  	if err := txn.AddAttribute("already_ended", "zap"); err != errAlreadyEnded {
   116  		t.Error(err)
   117  	}
   118  
   119  	agentAttributes := map[string]interface{}{}
   120  	userAttributes := map[string]interface{}{`int\key`: 1, `str\key`: `zip\zap`}
   121  
   122  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   123  		Intrinsics: map[string]interface{}{
   124  			"name": "OtherTransaction/Go/hello",
   125  		},
   126  		AgentAttributes: agentAttributes,
   127  		UserAttributes:  userAttributes,
   128  	}})
   129  	app.ExpectErrors(t, []internal.WantError{{
   130  		TxnName:         "OtherTransaction/Go/hello",
   131  		Msg:             "zap",
   132  		Klass:           "*errors.errorString",
   133  		AgentAttributes: agentAttributes,
   134  		UserAttributes:  userAttributes,
   135  	}})
   136  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   137  		Intrinsics: map[string]interface{}{
   138  			"error.class":     "*errors.errorString",
   139  			"error.message":   "zap",
   140  			"transactionName": "OtherTransaction/Go/hello",
   141  		},
   142  		AgentAttributes: agentAttributes,
   143  		UserAttributes:  userAttributes,
   144  	}})
   145  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   146  		MetricName:      "OtherTransaction/Go/hello",
   147  		NumSegments:     0,
   148  		AgentAttributes: agentAttributes,
   149  		UserAttributes:  userAttributes,
   150  	}})
   151  }
   152  
   153  func TestUserAttributeConfiguration(t *testing.T) {
   154  	cfgfn := func(cfg *Config) {
   155  		cfg.TransactionEvents.Attributes.Exclude = []string{"only_errors", "only_txn_traces"}
   156  		cfg.ErrorCollector.Attributes.Exclude = []string{"only_txn_events", "only_txn_traces"}
   157  		cfg.TransactionTracer.Attributes.Exclude = []string{"only_txn_events", "only_errors"}
   158  		cfg.Attributes.Exclude = []string{"completed_excluded"}
   159  		cfg.TransactionTracer.Threshold.IsApdexFailing = false
   160  		cfg.TransactionTracer.Threshold.Duration = 0
   161  	}
   162  	app := testApp(nil, cfgfn, t)
   163  	txn := app.StartTransaction("hello", nil, nil)
   164  
   165  	txn.NoticeError(errors.New("zap"))
   166  
   167  	if err := txn.AddAttribute("only_errors", 1); nil != err {
   168  		t.Error(err)
   169  	}
   170  	if err := txn.AddAttribute("only_txn_events", 2); nil != err {
   171  		t.Error(err)
   172  	}
   173  	if err := txn.AddAttribute("only_txn_traces", 3); nil != err {
   174  		t.Error(err)
   175  	}
   176  	if err := txn.AddAttribute("completed_excluded", 4); nil != err {
   177  		t.Error(err)
   178  	}
   179  	txn.End()
   180  
   181  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   182  		Intrinsics: map[string]interface{}{
   183  			"name": "OtherTransaction/Go/hello",
   184  		},
   185  		AgentAttributes: map[string]interface{}{},
   186  		UserAttributes:  map[string]interface{}{"only_txn_events": 2},
   187  	}})
   188  	app.ExpectErrors(t, []internal.WantError{{
   189  		TxnName:         "OtherTransaction/Go/hello",
   190  		Msg:             "zap",
   191  		Klass:           "*errors.errorString",
   192  		AgentAttributes: map[string]interface{}{},
   193  		UserAttributes:  map[string]interface{}{"only_errors": 1},
   194  	}})
   195  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   196  		Intrinsics: map[string]interface{}{
   197  			"error.class":     "*errors.errorString",
   198  			"error.message":   "zap",
   199  			"transactionName": "OtherTransaction/Go/hello",
   200  		},
   201  		AgentAttributes: map[string]interface{}{},
   202  		UserAttributes:  map[string]interface{}{"only_errors": 1},
   203  	}})
   204  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   205  		MetricName:      "OtherTransaction/Go/hello",
   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  		AttributeRequestURI:            "/hello",
   237  	}
   238  	// Agent attributes expected in errors and traces from usualAttributeTestTransaction.
   239  	agent2 = mergeAttributes(agent1, map[string]interface{}{
   240  		AttributeRequestUserAgent: "Mozilla/5.0",
   241  		AttributeRequestReferer:   "http://en.wikipedia.org/zip",
   242  	})
   243  	// User attributes expected from usualAttributeTestTransaction.
   244  	user1 = map[string]interface{}{
   245  		"myStr": "hello",
   246  	}
   247  )
   248  
   249  func agentAttributeTestcase(t testing.TB, cfgfn func(cfg *Config), e AttributeExpect) {
   250  	app := testApp(nil, func(cfg *Config) {
   251  		cfg.HostDisplayName = `my\host\display\name`
   252  		cfg.TransactionTracer.Threshold.IsApdexFailing = false
   253  		cfg.TransactionTracer.Threshold.Duration = 0
   254  		if nil != cfgfn {
   255  			cfgfn(cfg)
   256  		}
   257  	}, t)
   258  	w := newCompatibleResponseRecorder()
   259  	txn := app.StartTransaction("hello", w, helloRequest)
   260  	txn.NoticeError(errors.New("zap"))
   261  
   262  	hdr := txn.Header()
   263  	hdr.Set("Content-Type", `text/plain; charset=us-ascii`)
   264  	hdr.Set("Content-Length", `345`)
   265  
   266  	txn.WriteHeader(404)
   267  	txn.AddAttribute("myStr", "hello")
   268  
   269  	txn.End()
   270  
   271  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   272  		Intrinsics: map[string]interface{}{
   273  			"name":             "WebTransaction/Go/hello",
   274  			"nr.apdexPerfZone": "F",
   275  		},
   276  		AgentAttributes: e.TxnEvent.Agent,
   277  		UserAttributes:  e.TxnEvent.User,
   278  	}})
   279  	app.ExpectErrors(t, []internal.WantError{{
   280  		TxnName:         "WebTransaction/Go/hello",
   281  		Msg:             "zap",
   282  		Klass:           "*errors.errorString",
   283  		AgentAttributes: e.Error.Agent,
   284  		UserAttributes:  e.Error.User,
   285  	}})
   286  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   287  		Intrinsics: map[string]interface{}{
   288  			"error.class":     "*errors.errorString",
   289  			"error.message":   "zap",
   290  			"transactionName": "WebTransaction/Go/hello",
   291  		},
   292  		AgentAttributes: e.Error.Agent,
   293  		UserAttributes:  e.Error.User,
   294  	}})
   295  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   296  		MetricName:      "WebTransaction/Go/hello",
   297  		NumSegments:     0,
   298  		AgentAttributes: e.TxnTrace.Agent,
   299  		UserAttributes:  e.TxnTrace.User,
   300  	}})
   301  }
   302  
   303  type UserAgent struct {
   304  	User  map[string]interface{}
   305  	Agent map[string]interface{}
   306  }
   307  
   308  type AttributeExpect struct {
   309  	TxnEvent UserAgent
   310  	Error    UserAgent
   311  	TxnTrace UserAgent
   312  }
   313  
   314  func TestAgentAttributes(t *testing.T) {
   315  	agentAttributeTestcase(t, nil, AttributeExpect{
   316  		TxnEvent: UserAgent{
   317  			Agent: agent1,
   318  			User:  user1},
   319  		Error: UserAgent{
   320  			Agent: agent2,
   321  			User:  user1},
   322  	})
   323  }
   324  
   325  func TestAttributesDisabled(t *testing.T) {
   326  	agentAttributeTestcase(t, func(cfg *Config) {
   327  		cfg.Attributes.Enabled = false
   328  	}, AttributeExpect{
   329  		TxnEvent: UserAgent{
   330  			Agent: map[string]interface{}{},
   331  			User:  map[string]interface{}{}},
   332  		Error: UserAgent{
   333  			Agent: map[string]interface{}{},
   334  			User:  map[string]interface{}{}},
   335  		TxnTrace: UserAgent{
   336  			Agent: map[string]interface{}{},
   337  			User:  map[string]interface{}{}},
   338  	})
   339  }
   340  
   341  func TestDefaultResponseCode(t *testing.T) {
   342  	app := testApp(nil, nil, t)
   343  	w := newCompatibleResponseRecorder()
   344  	txn := app.StartTransaction("hello", w, &http.Request{})
   345  	txn.Write([]byte("hello"))
   346  	txn.End()
   347  
   348  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   349  		Intrinsics: map[string]interface{}{
   350  			"name":             "WebTransaction/Go/hello",
   351  			"nr.apdexPerfZone": "S",
   352  		},
   353  		AgentAttributes: map[string]interface{}{AttributeResponseCode: 200},
   354  		UserAttributes:  map[string]interface{}{},
   355  	}})
   356  }
   357  
   358  func TestNoResponseCode(t *testing.T) {
   359  	app := testApp(nil, nil, t)
   360  	w := newCompatibleResponseRecorder()
   361  	txn := app.StartTransaction("hello", w, &http.Request{})
   362  	txn.End()
   363  
   364  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   365  		Intrinsics: map[string]interface{}{
   366  			"name":             "WebTransaction/Go/hello",
   367  			"nr.apdexPerfZone": "S",
   368  		},
   369  		AgentAttributes: map[string]interface{}{},
   370  		UserAttributes:  map[string]interface{}{},
   371  	}})
   372  }
   373  
   374  func TestTxnEventAttributesDisabled(t *testing.T) {
   375  	agentAttributeTestcase(t, func(cfg *Config) {
   376  		cfg.TransactionEvents.Attributes.Enabled = false
   377  	}, AttributeExpect{
   378  		TxnEvent: UserAgent{
   379  			Agent: map[string]interface{}{},
   380  			User:  map[string]interface{}{}},
   381  		Error: UserAgent{
   382  			Agent: agent2,
   383  			User:  user1},
   384  		TxnTrace: UserAgent{
   385  			Agent: agent2,
   386  			User:  user1},
   387  	})
   388  }
   389  
   390  func TestErrorAttributesDisabled(t *testing.T) {
   391  	agentAttributeTestcase(t, func(cfg *Config) {
   392  		cfg.ErrorCollector.Attributes.Enabled = false
   393  	}, AttributeExpect{
   394  		TxnEvent: UserAgent{
   395  			Agent: agent1,
   396  			User:  user1},
   397  		Error: UserAgent{
   398  			Agent: map[string]interface{}{},
   399  			User:  map[string]interface{}{}},
   400  		TxnTrace: UserAgent{
   401  			Agent: agent2,
   402  			User:  user1},
   403  	})
   404  }
   405  
   406  func TestTxnTraceAttributesDisabled(t *testing.T) {
   407  	agentAttributeTestcase(t, func(cfg *Config) {
   408  		cfg.TransactionTracer.Attributes.Enabled = false
   409  	}, AttributeExpect{
   410  		TxnEvent: UserAgent{
   411  			Agent: agent1,
   412  			User:  user1},
   413  		Error: UserAgent{
   414  			Agent: agent2,
   415  			User:  user1},
   416  		TxnTrace: UserAgent{
   417  			Agent: map[string]interface{}{},
   418  			User:  map[string]interface{}{}},
   419  	})
   420  }
   421  
   422  var (
   423  	allAgentAttributeNames = []string{
   424  		AttributeResponseCode,
   425  		AttributeRequestMethod,
   426  		AttributeRequestAccept,
   427  		AttributeRequestContentType,
   428  		AttributeRequestContentLength,
   429  		AttributeRequestHost,
   430  		AttributeRequestURI,
   431  		AttributeResponseContentType,
   432  		AttributeResponseContentLength,
   433  		AttributeHostDisplayName,
   434  		AttributeRequestUserAgent,
   435  		AttributeRequestReferer,
   436  	}
   437  )
   438  
   439  func TestAgentAttributesExcluded(t *testing.T) {
   440  	agentAttributeTestcase(t, func(cfg *Config) {
   441  		cfg.Attributes.Exclude = allAgentAttributeNames
   442  	}, AttributeExpect{
   443  		TxnEvent: UserAgent{
   444  			Agent: map[string]interface{}{},
   445  			User:  user1},
   446  		Error: UserAgent{
   447  			Agent: map[string]interface{}{},
   448  			User:  user1},
   449  		TxnTrace: UserAgent{
   450  			Agent: map[string]interface{}{},
   451  			User:  user1},
   452  	})
   453  }
   454  
   455  func TestAgentAttributesExcludedFromErrors(t *testing.T) {
   456  	agentAttributeTestcase(t, func(cfg *Config) {
   457  		cfg.ErrorCollector.Attributes.Exclude = allAgentAttributeNames
   458  	}, AttributeExpect{
   459  		TxnEvent: UserAgent{
   460  			Agent: agent1,
   461  			User:  user1},
   462  		Error: UserAgent{
   463  			Agent: map[string]interface{}{},
   464  			User:  user1},
   465  		TxnTrace: UserAgent{
   466  			Agent: agent2,
   467  			User:  user1},
   468  	})
   469  }
   470  
   471  func TestAgentAttributesExcludedFromTxnEvents(t *testing.T) {
   472  	agentAttributeTestcase(t, func(cfg *Config) {
   473  		cfg.TransactionEvents.Attributes.Exclude = allAgentAttributeNames
   474  	}, AttributeExpect{
   475  		TxnEvent: UserAgent{
   476  			Agent: map[string]interface{}{},
   477  			User:  user1},
   478  		Error: UserAgent{
   479  			Agent: agent2,
   480  			User:  user1},
   481  		TxnTrace: UserAgent{
   482  			Agent: agent2,
   483  			User:  user1},
   484  	})
   485  }
   486  
   487  func TestAgentAttributesExcludedFromTxnTraces(t *testing.T) {
   488  	agentAttributeTestcase(t, func(cfg *Config) {
   489  		cfg.TransactionTracer.Attributes.Exclude = allAgentAttributeNames
   490  	}, AttributeExpect{
   491  		TxnEvent: UserAgent{
   492  			Agent: agent1,
   493  			User:  user1},
   494  		Error: UserAgent{
   495  			Agent: agent2,
   496  			User:  user1},
   497  		TxnTrace: UserAgent{
   498  			Agent: map[string]interface{}{},
   499  			User:  user1},
   500  	})
   501  }
   502  
   503  func TestRequestURIPresent(t *testing.T) {
   504  	cfgfn := func(cfg *Config) {
   505  		cfg.TransactionTracer.Threshold.IsApdexFailing = false
   506  		cfg.TransactionTracer.Threshold.Duration = 0
   507  	}
   508  	app := testApp(nil, cfgfn, t)
   509  	txn := app.StartTransaction("hello", nil, nil)
   510  	u, err := url.Parse("/hello?remove=me")
   511  	if nil != err {
   512  		t.Error(err)
   513  	}
   514  	txn.SetWebRequest(customRequest{u: u})
   515  	txn.NoticeError(errors.New("zap"))
   516  	txn.End()
   517  
   518  	agentAttributes := map[string]interface{}{"request.uri": "/hello"}
   519  	userAttributes := map[string]interface{}{}
   520  
   521  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   522  		Intrinsics: map[string]interface{}{
   523  			"name":             "WebTransaction/Go/hello",
   524  			"nr.apdexPerfZone": "F",
   525  		},
   526  		AgentAttributes: agentAttributes,
   527  		UserAttributes:  userAttributes,
   528  	}})
   529  	app.ExpectErrors(t, []internal.WantError{{
   530  		TxnName:         "WebTransaction/Go/hello",
   531  		Msg:             "zap",
   532  		Klass:           "*errors.errorString",
   533  		AgentAttributes: agentAttributes,
   534  		UserAttributes:  userAttributes,
   535  	}})
   536  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   537  		Intrinsics: map[string]interface{}{
   538  			"error.class":     "*errors.errorString",
   539  			"error.message":   "zap",
   540  			"transactionName": "WebTransaction/Go/hello",
   541  		},
   542  		AgentAttributes: agentAttributes,
   543  		UserAttributes:  userAttributes,
   544  	}})
   545  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   546  		MetricName:      "WebTransaction/Go/hello",
   547  		NumSegments:     0,
   548  		AgentAttributes: agentAttributes,
   549  		UserAttributes:  userAttributes,
   550  	}})
   551  }
   552  
   553  func TestRequestURIExcluded(t *testing.T) {
   554  	cfgfn := func(cfg *Config) {
   555  		cfg.TransactionTracer.Threshold.IsApdexFailing = false
   556  		cfg.TransactionTracer.Threshold.Duration = 0
   557  		cfg.Attributes.Exclude = append(cfg.Attributes.Exclude, AttributeRequestURI)
   558  	}
   559  	app := testApp(nil, cfgfn, t)
   560  	txn := app.StartTransaction("hello", nil, nil)
   561  	u, err := url.Parse("/hello?remove=me")
   562  	if nil != err {
   563  		t.Error(err)
   564  	}
   565  	txn.SetWebRequest(customRequest{u: u})
   566  	txn.NoticeError(errors.New("zap"))
   567  	txn.End()
   568  
   569  	agentAttributes := map[string]interface{}{}
   570  	userAttributes := map[string]interface{}{}
   571  
   572  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   573  		Intrinsics: map[string]interface{}{
   574  			"name":             "WebTransaction/Go/hello",
   575  			"nr.apdexPerfZone": "F",
   576  		},
   577  		AgentAttributes: agentAttributes,
   578  		UserAttributes:  userAttributes,
   579  	}})
   580  	app.ExpectErrors(t, []internal.WantError{{
   581  		TxnName:         "WebTransaction/Go/hello",
   582  		Msg:             "zap",
   583  		Klass:           "*errors.errorString",
   584  		AgentAttributes: agentAttributes,
   585  		UserAttributes:  userAttributes,
   586  	}})
   587  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   588  		Intrinsics: map[string]interface{}{
   589  			"error.class":     "*errors.errorString",
   590  			"error.message":   "zap",
   591  			"transactionName": "WebTransaction/Go/hello",
   592  		},
   593  		AgentAttributes: agentAttributes,
   594  		UserAttributes:  userAttributes,
   595  	}})
   596  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   597  		MetricName:      "WebTransaction/Go/hello",
   598  		NumSegments:     0,
   599  		AgentAttributes: agentAttributes,
   600  		UserAttributes:  userAttributes,
   601  	}})
   602  }
   603  
   604  func TestMessageAttributes(t *testing.T) {
   605  	// test that adding message attributes as agent attributes filters them,
   606  	// but as user attributes does not filter them.
   607  	app := testApp(nil, nil, t)
   608  
   609  	txn := app.StartTransaction("hello1", nil, nil)
   610  	txn.(internal.AddAgentAttributer).AddAgentAttribute(internal.AttributeMessageRoutingKey, "myRoutingKey", nil)
   611  	txn.(internal.AddAgentAttributer).AddAgentAttribute(internal.AttributeMessageExchangeType, "myExchangeType", nil)
   612  	txn.(internal.AddAgentAttributer).AddAgentAttribute(internal.AttributeMessageCorrelationID, "myCorrelationID", nil)
   613  	txn.(internal.AddAgentAttributer).AddAgentAttribute(internal.AttributeMessageQueueName, "myQueueName", nil)
   614  	txn.(internal.AddAgentAttributer).AddAgentAttribute(internal.AttributeMessageReplyTo, "myReplyTo", nil)
   615  	txn.End()
   616  
   617  	txn = app.StartTransaction("hello2", nil, nil)
   618  	txn.AddAttribute(AttributeMessageRoutingKey, "myRoutingKey")
   619  	txn.AddAttribute(AttributeMessageExchangeType, "myExchangeType")
   620  	txn.AddAttribute(AttributeMessageCorrelationID, "myCorrelationID")
   621  	txn.AddAttribute(AttributeMessageQueueName, "myQueueName")
   622  	txn.AddAttribute(AttributeMessageReplyTo, "myReplyTo")
   623  	txn.End()
   624  
   625  	app.ExpectTxnEvents(t, []internal.WantEvent{
   626  		{
   627  			UserAttributes: map[string]interface{}{},
   628  			AgentAttributes: map[string]interface{}{
   629  				"message.queueName":  "myQueueName",
   630  				"message.routingKey": "myRoutingKey",
   631  			},
   632  			Intrinsics: map[string]interface{}{
   633  				"name": "OtherTransaction/Go/hello1",
   634  			},
   635  		},
   636  		{
   637  			UserAttributes: map[string]interface{}{
   638  				"message.queueName":     "myQueueName",
   639  				"message.routingKey":    "myRoutingKey",
   640  				"message.exchangeType":  "myExchangeType",
   641  				"message.replyTo":       "myReplyTo",
   642  				"message.correlationId": "myCorrelationID",
   643  			},
   644  			AgentAttributes: map[string]interface{}{},
   645  			Intrinsics: map[string]interface{}{
   646  				"name": "OtherTransaction/Go/hello2",
   647  			},
   648  		},
   649  	})
   650  }