public void GetErrorEvent_InTransaction_IfStatusCodeIs404_ContainsCorrectAttributes()
        {
            var transaction          = BuildTestTransaction(statusCode: 404, uri: "http://www.newrelic.com/test?param=value", isSynthetics: false, isCAT: false, referrerUri: "http://referrer.uri");
            var immutableTransaction = transaction.ConvertToImmutableTransaction();

            var errorData             = transaction.TransactionMetadata.TransactionErrorState.ErrorData;
            var transactionMetricName = _transactionMetricNameMaker.GetTransactionMetricName(immutableTransaction.TransactionName);
            var txStats = new TransactionMetricStatsCollection(transactionMetricName);

            var attributes = _transactionAttributeMaker.GetAttributes(immutableTransaction, transactionMetricName, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15), txStats);

            var errorEvent = _errorEventMaker.GetErrorEvent(immutableTransaction, attributes);

            var intrinsicAttributes = errorEvent.IntrinsicAttributes().Keys.ToArray();
            var agentAttributes     = errorEvent.AgentAttributes().Keys.ToArray();
            var userAttributes      = errorEvent.UserAttributes().Keys.ToArray();

            NrAssert.Multiple(
                () => Assert.AreEqual(false, errorEvent.IsSynthetics),
                () => Assert.AreEqual(7, agentAttributes.Length),
                () => Assert.AreEqual(7, intrinsicAttributes.Length),
                () => Assert.AreEqual(0, userAttributes.Length),

                () => Assert.Contains("queue_wait_time_ms", agentAttributes),
                () => Assert.Contains("response.status", agentAttributes),
                () => Assert.Contains("http.statusCode", agentAttributes),
                () => Assert.Contains("original_url", agentAttributes),
                () => Assert.Contains("request.uri", agentAttributes),
                () => Assert.Contains("request.referer", agentAttributes),
                () => Assert.Contains("host.displayName", agentAttributes),

                () => Assert.Contains("duration", intrinsicAttributes),
                () => Assert.Contains("error.class", intrinsicAttributes),
                () => Assert.Contains("error.message", intrinsicAttributes),
                () => Assert.Contains("queueDuration", intrinsicAttributes),
                () => Assert.Contains("transactionName", intrinsicAttributes),
                () => Assert.Contains("timestamp", intrinsicAttributes),
                () => Assert.Contains("type", intrinsicAttributes)
                );
        }
        private void Transform(ImmutableTransaction immutableTransaction, TransactionMetricName transactionMetricName)
        {
            if (!immutableTransaction.Segments.Any())
            {
                throw new ArgumentException("Transaction does not have any segments");
            }

            FinishSegments(immutableTransaction.Segments);

            TryGenerateExplainPlans(immutableTransaction.Segments);

            var totalTime = GetTotalExclusiveTime(immutableTransaction.Segments);
            var transactionApdexMetricName = MetricNames.GetTransactionApdex(transactionMetricName);
            var apdexT = GetApdexT(immutableTransaction, transactionMetricName.PrefixedName);

            var txStats = new TransactionMetricStatsCollection(transactionMetricName);

            GenerateAndCollectSqlTrace(immutableTransaction, transactionMetricName, txStats);
            GenerateAndCollectMetrics(immutableTransaction, apdexT, transactionApdexMetricName, totalTime, txStats);

            // defer the creation of attributes until something asks for them.
            Func <IAttributeValueCollection> attributes = () => _transactionAttributeMaker.GetAttributes(immutableTransaction, transactionMetricName, apdexT, totalTime, txStats);

            attributes = attributes.Memoize();

            // Must generate errors first so other wire models get attribute updates
            if (immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.HasError)
            {
                GenerateAndCollectErrorEventTracesAndEvents(immutableTransaction, attributes.Invoke(), transactionMetricName);
            }

            GenerateAndCollectTransactionEvent(immutableTransaction, attributes);

            GenerateAndCollectTransactionTrace(immutableTransaction, transactionMetricName, attributes);

            GenerateAndCollectSpanEvents(immutableTransaction, transactionMetricName.PrefixedName, attributes);
        }
示例#3
0
        public void GetSpanEvent_ReturnsSpanEventPerSegment_ValidateCount()
        {
            // ARRANGE
            var segments = new List <Segment>()
            {
                _baseGenericSegment.CreateSimilar(TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(5), new List <KeyValuePair <string, object> >()),
                _childGenericSegment.CreateSimilar(TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(5), new List <KeyValuePair <string, object> >())
            };
            var immutableTransaction = BuildTestTransaction(segments, sampled: true, hasIncomingPayload: false);

            var transactionMetricName = _transactionMetricNameMaker.GetTransactionMetricName(immutableTransaction.TransactionName);
            var metricStatsCollection = new TransactionMetricStatsCollection(transactionMetricName);
            var transactionAttribs    = _transactionAttribMaker.GetAttributes(immutableTransaction, transactionMetricName, TimeSpan.FromSeconds(1), immutableTransaction.Duration, metricStatsCollection);

            // ACT
            var spanEvents = _spanEventMaker.GetSpanEvents(immutableTransaction, TransactionName, transactionAttribs);

            // ASSERT
            // +1 is for the faux root segment.
            Assert.AreEqual(segments.Count + 1, spanEvents.Count());
        }
        public void Test(TestCase testCase)
        {
            Mock.Arrange(() => _configuration.ApplicationNames).Returns(new[] { testCase.AppName });

            // ConvertToImmutableTransaction a transaction for the test data
            _transaction = GetTransactionBuilderFor(_configuration, testCase);

            // Simulate external requests as dictated by the test data
            var namePriority = 10;
            var expectedAndActualOutboundRequestPayloads = new Dictionary <CrossApplicationRequestData, CrossApplicationRequestData>();

            testCase.OutboundRequests?.ForEach(request =>
            {
                var transactionName = GetTransactionNameFromString(request.OutboundTxnName);
                _transaction.CandidateTransactionName.TrySet(transactionName, (TransactionNamePriority)namePriority++);
                var outboundHeaders       = _agent.CurrentTransaction.GetRequestMetadata().ToDictionary();
                var actualOutboundPayload = _catHeaderHandler.TryDecodeInboundRequestHeaders(outboundHeaders, GetHeaderValue);
                var requestData           = new CrossApplicationRequestData(
                    (string)request.ExpectedOutboundPayload[0],
                    (bool)request.ExpectedOutboundPayload[1],
                    (string)request.ExpectedOutboundPayload[2],
                    (string)request.ExpectedOutboundPayload[3]
                    );
                expectedAndActualOutboundRequestPayloads.Add(requestData, actualOutboundPayload);
                _transaction.TransactionMetadata.MarkHasCatResponseHeaders();

                List <string> GetHeaderValue(Dictionary <string, string> headers, string key)
                {
                    var headerValues = new List <string>();
                    foreach (var item in headers)
                    {
                        if (item.Key.Equals(key, StringComparison.OrdinalIgnoreCase))
                        {
                            headerValues.Add(item.Value);
                        }
                    }
                    return(headerValues);
                }
            });

            // Simulate the transaction ending (this logic is normally performed by Agent.EndTransaction)
            _transaction.CandidateTransactionName.TrySet(GetTransactionNameFromString(testCase.TransactionName), (TransactionNamePriority)9999);
            var currentTransactionName       = _transaction.CandidateTransactionName.CurrentTransactionName;
            var currentTransactionMetricName = _transactionMetricNameMaker.GetTransactionMetricName(currentTransactionName);
            var pathHash = _pathHashMaker.CalculatePathHash(currentTransactionMetricName.PrefixedName, _transaction.TransactionMetadata.CrossApplicationReferrerPathHash);

            _transaction.TransactionMetadata.SetCrossApplicationPathHash(pathHash);
            var transaction = _transaction.ConvertToImmutableTransaction();
            var totalTime   = transaction.Duration;

            // Get the attributes that would be created for this transaction
            var transactionMetricName = _transactionMetricNameMaker.GetTransactionMetricName(transaction.TransactionName);
            var txStats    = new TransactionMetricStatsCollection(transactionMetricName);
            var attributes = _transactionAttributeMaker.GetAttributes(transaction, transactionMetricName, null, totalTime, txStats);
            var intrinsics = attributes.GetAttributeValuesDic(AttributeClassification.Intrinsics);

            // Run assertions
            testCase.ExpectedIntrinsicFields.ForEach(kvp =>
            {
                Assert.True(intrinsics.ContainsKey(kvp.Key), $"Expected intrinsic attribute '{kvp.Key}' was not found");
                Assert.AreEqual(kvp.Value, intrinsics[kvp.Key], $"Attribute '{kvp.Key}': expected value '{kvp.Value}' but found '{intrinsics[kvp.Key]}'");
            });

            testCase.NonExpectedIntrinsicFields.ForEach(field =>
            {
                Assert.False(intrinsics.ContainsKey(field), $"Found unexpected intrinsic attribute '{field}'");
            });

            if (testCase.OutboundRequests != null)
            {
                expectedAndActualOutboundRequestPayloads.ForEach(kvp =>
                {
                    var expected = kvp.Key;
                    var actual   = kvp.Value;
                    Assert.NotNull(actual, "Outbound request did not have any CAT headers");
                    Assert.AreEqual(expected.TransactionGuid, actual.TransactionGuid, $"Expected outbound.TransactionGuid to be '{expected.TransactionGuid}' but found '{actual.TransactionGuid}'");
                    Assert.AreEqual(expected.PathHash, actual.PathHash, $"Expected outbound.PathHash to be '{expected.TransactionGuid}' but found '{actual.TransactionGuid}'");
                    Assert.AreEqual(expected.TripId, actual.TripId, $"Expected outbound.TripId to be '{expected.TransactionGuid}' but found '{actual.TransactionGuid}'");
                    Assert.AreEqual(expected.Unused, actual.Unused, $"Expected outbound.Unused to be '{expected.Unused}' but found '{actual.Unused}'");
                });
            }
        }