github.com/newrelic/go-agent@v3.26.0+incompatible/internal_synthetics_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  	"net/http"
     8  	"testing"
     9  
    10  	"github.com/newrelic/go-agent/internal"
    11  	"github.com/newrelic/go-agent/internal/cat"
    12  )
    13  
    14  // This collection of top-level tests affirms, for all possible combinations of
    15  // Old CAT, BetterCAT, and Synthetics, that when an inbound request contains a
    16  // synthetics header, the subsequent outbound request propagates that synthetics
    17  // header.  Synthetics uses an obfuscated JSON header, so this test requires a
    18  // really particular set of values, e.g. rrrrrrr-rrrr-1234-rrrr-rrrrrrrrrrrr.
    19  
    20  var (
    21  	trustedAccounts = func() map[int]struct{} {
    22  		ta := make(map[int]struct{})
    23  		ta[1] = struct{}{}   // Trust account 1, from syntheticsConnectReplyFn.
    24  		ta[444] = struct{}{} // Trust account 444, from syntheticsHeader.
    25  		return ta
    26  	}()
    27  
    28  	syntheticsConnectReplyFn = func(reply *internal.ConnectReply) {
    29  		reply.EncodingKey = "1234567890123456789012345678901234567890"
    30  		reply.CrossProcessID = "1#1"
    31  		reply.TrustedAccounts = trustedAccounts
    32  	}
    33  )
    34  
    35  func inboundSyntheticsRequestBuilder(oldCatEnabled bool, betterCatEnabled bool) *http.Request {
    36  	cfgFn := func(cfg *Config) {
    37  		cfg.CrossApplicationTracer.Enabled = oldCatEnabled
    38  		cfg.DistributedTracer.Enabled = betterCatEnabled
    39  	}
    40  	app := testApp(syntheticsConnectReplyFn, cfgFn, nil)
    41  	txn := app.StartTransaction("requester", nil, nil)
    42  	req, err := http.NewRequest("GET", "newrelic.com", nil)
    43  	if nil != err {
    44  		panic(err)
    45  	}
    46  
    47  	req.Header.Add(
    48  		"X-NewRelic-Synthetics",
    49  		"agMfAAECGxpLQkNAQUZHG0VKS0IcAwEHARtFSktCHEBBRkdERUpLQkNAQRYZFF1SU1pbWFkZX1xdUhQBAwEHGV9cXVIUWltYWV5fXF1SU1pbEB8WWFtaVVRdXB9eWVhbGgkLAwUfXllYWxpVVF1cX15ZWFtaVVQSbA==")
    50  
    51  	StartExternalSegment(txn, req)
    52  
    53  	if betterCatEnabled || !oldCatEnabled {
    54  		if cat.NewRelicIDName == req.Header.Get(cat.NewRelicIDName) {
    55  			panic("Header contains old cat header NewRelicIDName: " + req.Header.Get(cat.NewRelicIDName))
    56  		}
    57  		if cat.NewRelicTxnName == req.Header.Get(cat.NewRelicTxnName) {
    58  			panic("Header contains old cat header NewRelicTxnName: " + req.Header.Get(cat.NewRelicTxnName))
    59  		}
    60  	}
    61  
    62  	if oldCatEnabled {
    63  		if "" == req.Header.Get(cat.NewRelicIDName) {
    64  			panic("Missing old cat header NewRelicIDName: " + req.Header.Get(cat.NewRelicIDName))
    65  		}
    66  		if "" == req.Header.Get(cat.NewRelicTxnName) {
    67  			panic("Missing old cat header NewRelicTxnName: " + req.Header.Get(cat.NewRelicTxnName))
    68  		}
    69  	}
    70  
    71  	if "" == req.Header.Get(cat.NewRelicSyntheticsName) {
    72  		panic("missing synthetics header NewRelicSyntheticsName: " + req.Header.Get(cat.NewRelicSyntheticsName))
    73  	}
    74  
    75  	return req
    76  }
    77  
    78  func TestSyntheticsOldCAT(t *testing.T) {
    79  	cfgFn := func(cfg *Config) { cfg.CrossApplicationTracer.Enabled = true }
    80  	app := testApp(syntheticsConnectReplyFn, cfgFn, t)
    81  	clientTxn := app.StartTransaction(
    82  		"helloOldCAT",
    83  		nil,
    84  		inboundSyntheticsRequestBuilder(true, false))
    85  
    86  	req, err := http.NewRequest("GET", "newrelic.com", nil)
    87  
    88  	if nil != err {
    89  		panic(err)
    90  	}
    91  
    92  	StartExternalSegment(clientTxn, req)
    93  	clientTxn.End()
    94  
    95  	if "" == req.Header.Get(cat.NewRelicSyntheticsName) {
    96  		panic("Outbound request missing synthetics header NewRelicSyntheticsName: " + req.Header.Get(cat.NewRelicSyntheticsName))
    97  	}
    98  
    99  	expectedIntrinsics := map[string]interface{}{
   100  		"name":                        "WebTransaction/Go/helloOldCAT",
   101  		"client_cross_process_id":     "1#1",
   102  		"nr.syntheticsResourceId":     "rrrrrrr-rrrr-1234-rrrr-rrrrrrrrrrrr",
   103  		"nr.syntheticsJobId":          "jjjjjjj-jjjj-1234-jjjj-jjjjjjjjjjjj",
   104  		"nr.syntheticsMonitorId":      "mmmmmmm-mmmm-1234-mmmm-mmmmmmmmmmmm",
   105  		"nr.apdexPerfZone":            internal.MatchAnything,
   106  		"nr.tripId":                   internal.MatchAnything,
   107  		"nr.pathHash":                 internal.MatchAnything,
   108  		"nr.referringPathHash":        internal.MatchAnything,
   109  		"nr.referringTransactionGuid": internal.MatchAnything,
   110  		"nr.guid":                     internal.MatchAnything,
   111  	}
   112  
   113  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   114  		Intrinsics: expectedIntrinsics,
   115  	}})
   116  }
   117  
   118  func TestSyntheticsBetterCAT(t *testing.T) {
   119  	cfgFn := func(cfg *Config) {
   120  		cfg.CrossApplicationTracer.Enabled = false
   121  		cfg.DistributedTracer.Enabled = true
   122  	}
   123  	app := testApp(syntheticsConnectReplyFn, cfgFn, t)
   124  	clientTxn := app.StartTransaction(
   125  		"helloBetterCAT",
   126  		nil,
   127  		inboundSyntheticsRequestBuilder(false, true))
   128  
   129  	req, err := http.NewRequest("GET", "newrelic.com", nil)
   130  
   131  	if nil != err {
   132  		panic(err)
   133  	}
   134  
   135  	StartExternalSegment(clientTxn, req)
   136  	clientTxn.End()
   137  
   138  	if "" == req.Header.Get(cat.NewRelicSyntheticsName) {
   139  		panic("Outbound request missing synthetics header NewRelicSyntheticsName: " + req.Header.Get(cat.NewRelicSyntheticsName))
   140  	}
   141  
   142  	expectedIntrinsics := map[string]interface{}{
   143  		"name":                    "WebTransaction/Go/helloBetterCAT",
   144  		"nr.syntheticsResourceId": "rrrrrrr-rrrr-1234-rrrr-rrrrrrrrrrrr",
   145  		"nr.syntheticsJobId":      "jjjjjjj-jjjj-1234-jjjj-jjjjjjjjjjjj",
   146  		"nr.syntheticsMonitorId":  "mmmmmmm-mmmm-1234-mmmm-mmmmmmmmmmmm",
   147  		"nr.apdexPerfZone":        internal.MatchAnything,
   148  		"priority":                internal.MatchAnything,
   149  		"sampled":                 internal.MatchAnything,
   150  		"traceId":                 internal.MatchAnything,
   151  		"guid":                    internal.MatchAnything,
   152  	}
   153  
   154  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   155  		Intrinsics: expectedIntrinsics,
   156  	}})
   157  }
   158  
   159  func TestSyntheticsStandalone(t *testing.T) {
   160  	cfgFn := func(cfg *Config) {
   161  		cfg.AppName = "syntheticsReceiver"
   162  		cfg.CrossApplicationTracer.Enabled = false
   163  	}
   164  	app := testApp(syntheticsConnectReplyFn, cfgFn, t)
   165  	clientTxn := app.StartTransaction(
   166  		"helloSynthetics",
   167  		nil,
   168  		inboundSyntheticsRequestBuilder(false, false))
   169  
   170  	req, err := http.NewRequest("GET", "newrelic.com", nil)
   171  
   172  	if nil != err {
   173  		panic(err)
   174  	}
   175  
   176  	StartExternalSegment(clientTxn, req)
   177  	clientTxn.End()
   178  
   179  	if "" == req.Header.Get(cat.NewRelicSyntheticsName) {
   180  		panic("Outbound request missing synthetics header NewRelicSyntheticsName: " + req.Header.Get(cat.NewRelicSyntheticsName))
   181  	}
   182  
   183  	expectedIntrinsics := map[string]interface{}{
   184  		"name":                    "WebTransaction/Go/helloSynthetics",
   185  		"nr.syntheticsResourceId": "rrrrrrr-rrrr-1234-rrrr-rrrrrrrrrrrr",
   186  		"nr.syntheticsJobId":      "jjjjjjj-jjjj-1234-jjjj-jjjjjjjjjjjj",
   187  		"nr.syntheticsMonitorId":  "mmmmmmm-mmmm-1234-mmmm-mmmmmmmmmmmm",
   188  		"nr.apdexPerfZone":        internal.MatchAnything,
   189  		"nr.guid":                 internal.MatchAnything,
   190  	}
   191  
   192  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   193  		Intrinsics: expectedIntrinsics,
   194  	}})
   195  }