Пример #1
0
        private string GetReferrerCrossApplicationProcessId <T>(IInternalTransaction transaction, T carrier, Func <T, string, IEnumerable <string> > getter)
        {
            var existingReferrerProcessId = transaction.TransactionMetadata.CrossApplicationReferrerProcessId;

            if (existingReferrerProcessId != null)
            {
                _catMetricCounters.Record(CATSupportabilityCondition.Request_Accept_Multiple);
                Log.Warn($"Already received inbound cross application request with referrer cross process id: {existingReferrerProcessId}");
                return(null);
            }

            return(_catHeaderHandler?.TryDecodeInboundRequestHeadersForCrossProcessId(carrier, getter));
        }
Пример #2
0
 private bool SetIsSampled(IInternalTransaction transaction)
 {
     // if Sampled has not been set, compute it now
     if (transaction.Sampled != null)
     {
         return((bool)transaction.Sampled);
     }
     else
     {
         transaction.SetSampled(_adaptiveSampler);
         return((bool)transaction.Sampled);
     }
 }
Пример #3
0
 IInternalTransaction DoBeginTransaction(IsolationLevel isolationLevel)
 {
     ++_transactionCount;
     if (_main == null)
     {
         ImplicitOpen();
         _current = _main = new Primary(this, isolationLevel);
     }
     else
     {
         _current = _current.CreateSub(isolationLevel);
     }
     return(_current);
 }
Пример #4
0
        private ImmutableTransaction BuildTestTransaction(bool ignoreAutoBrowserMonitoring = false, bool ignoreAllBrowserMonitoring = false)
        {
            var name     = TransactionName.ForWebTransaction("foo", "bar");
            var segments = Enumerable.Empty <Segment>();
            var metadata = new TransactionMetadata().ConvertToImmutableMetadata();
            var guid     = Guid.NewGuid().ToString();

            _internalTransaction = Mock.Create <IInternalTransaction>();
            Mock.Arrange(() => _internalTransaction.IgnoreAllBrowserMonitoring).Returns(ignoreAllBrowserMonitoring);
            Mock.Arrange(() => _internalTransaction.IgnoreAutoBrowserMonitoring).Returns(ignoreAutoBrowserMonitoring);

            var attribDefSvc = new AttributeDefinitionService((f) => new AttributeDefinitions(f));

            return(new ImmutableTransaction(name, segments, metadata, DateTime.UtcNow, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), guid, ignoreAutoBrowserMonitoring, ignoreAllBrowserMonitoring, false, 0.5f, false, string.Empty, null, attribDefSvc.AttributeDefs));
        }
        /// <summary>
        /// Estimates the duration of a transaction based on its segments.
        /// </summary>
        /// <returns>An estimate of the duration of a transaction.</returns>
        private static TimeSpan GetEstimatedTransactionDuration(IInternalTransaction internalTransaction, Segment lastStartedSegment, Segment lastFinishedSegment)
        {
            if (lastStartedSegment == null && lastFinishedSegment == null)
            {
                return(TimeSpan.FromMilliseconds(1));
            }

            var immutableTransaction = internalTransaction.ConvertToImmutableTransaction();

            var lastStartedSegmentEndTime  = lastStartedSegment?.CalculatedRelativeEndTime ?? new TimeSpan();
            var lastFinishedSegmentEndTime = lastFinishedSegment?.CalculatedRelativeEndTime ?? new TimeSpan();
            var maxEndTime = DateTimeMath.Max(lastStartedSegmentEndTime, lastFinishedSegmentEndTime);

            return(maxEndTime);
        }
        public bool SetTransactionOnAsyncContext(IInternalTransaction transaction)
        {
            if (_asyncContext == null)
            {
                return(false);
            }

            if (_asyncContext.GetData() == null)
            {
                _asyncContext.SetData(transaction);
                if (Log.IsFinestEnabled)
                {
                    transaction.LogFinest($"Attached to {_asyncContext}");
                }
            }

            return(true);
        }
Пример #7
0
        private string GetOutboundHeader(DistributedTraceHeaderType headerType, IInternalTransaction transaction, DateTime timestamp)
        {
            switch (headerType)
            {
            case DistributedTraceHeaderType.W3cTraceparent:
                return(BuildTraceParent(transaction));

            case DistributedTraceHeaderType.W3cTracestate:
                return(BuildTracestate(transaction, timestamp));

            case DistributedTraceHeaderType.NewRelic:
                var distributedTracePayload = TryGetOutboundDistributedTraceApiModelInternal(transaction, transaction.CurrentSegment, timestamp);
                if (!distributedTracePayload.IsEmpty())
                {
                    return(distributedTracePayload.HttpSafe());
                }
                return(string.Empty);
            }

            return(string.Empty);
        }
Пример #8
0
        private IDistributedTracePayload TryGetOutboundDistributedTraceApiModelInternal(IInternalTransaction transaction, ISegment segment, DateTime timestamp)
        {
            var accountId = _configurationService.Configuration.AccountId;
            var appId     = _configurationService.Configuration.PrimaryApplicationId;

            if (!_configurationService.Configuration.SpanEventsEnabled && !_configurationService.Configuration.TransactionEventsEnabled)
            {
                Log.Finest("Did not generate payload because Span Events and Transaction Events were both disabled, preventing a traceable payload.");
                return(DistributedTraceApiModel.EmptyModel);
            }

            transaction.SetSampled(_adaptiveSampler);
            var transactionIsSampled = transaction.Sampled;

            if (transactionIsSampled.HasValue == false)
            {
                Log.Error("Did not generate payload because transaction sampled value was null.");
                return(DistributedTraceApiModel.EmptyModel);
            }

            var payloadGuid   = _configurationService.Configuration.SpanEventsEnabled ? segment?.SpanId : null;
            var trustKey      = _configurationService.Configuration.TrustedAccountKey;
            var transactionId = (_configurationService.Configuration.TransactionEventsEnabled) ? transaction.Guid : null;
            var traceId       = transaction.TraceId;

            var distributedTracePayload = DistributedTracePayload.TryBuildOutgoingPayload(
                DistributedTraceTypeDefault,
                accountId,
                appId,
                payloadGuid,
                traceId,
                trustKey,
                transaction.Priority,
                transactionIsSampled,
                timestamp,
                transactionId);

            if (distributedTracePayload == null)
            {
                return(DistributedTraceApiModel.EmptyModel);
            }

            string encodedPayload;

            try
            {
                encodedPayload = DistributedTracePayload.SerializeAndEncodeDistributedTracePayload(distributedTracePayload);
            }
            catch (Exception ex)
            {
                Log.Error($"Failed to get encoded distributed trace headers for outbound request: {ex}");
                _agentHealthReporter.ReportSupportabilityDistributedTraceCreatePayloadException();
                return(DistributedTraceApiModel.EmptyModel);
            }

            transaction.TransactionMetadata.HasOutgoingTraceHeaders = true;

            if (_configurationService.Configuration.PayloadSuccessMetricsEnabled)
            {
                _agentHealthReporter.ReportSupportabilityDistributedTraceCreatePayloadSuccess();
            }

            return(new DistributedTraceApiModel(encodedPayload));
        }
Пример #9
0
 public IDistributedTracePayload TryGetOutboundDistributedTraceApiModel(IInternalTransaction transaction, ISegment segment = null)
 {
     return(TryGetOutboundDistributedTraceApiModelInternal(transaction, segment, DateTime.UtcNow));
 }
        public IEnumerable <KeyValuePair <string, string> > TryGetOutboundSyntheticsRequestHeader(IInternalTransaction transaction)
        {
            var metadata = transaction.TransactionMetadata;

            if (!metadata.IsSynthetics)
            {
                return(Enumerable.Empty <KeyValuePair <string, string> >());
            }

            long accountId;

            if (!long.TryParse(_configurationService.Configuration.CrossApplicationTracingCrossProcessId.Split(StringSeparators.Hash)[0], out accountId))
            {
                return(Enumerable.Empty <KeyValuePair <string, string> >());
            }

            var syntheticsHeader = new SyntheticsHeader(SyntheticsHeader.SupportedHeaderVersion, accountId, metadata.SyntheticsResourceId, metadata.SyntheticsJobId, metadata.SyntheticsMonitorId)
            {
                EncodingKey = _configurationService.Configuration.EncodingKey
            };

            var obfuscatedHeader = syntheticsHeader.TryGetObfuscated();

            if (obfuscatedHeader == null)
            {
                return(Enumerable.Empty <KeyValuePair <string, string> >());
            }

            return(new[]
            {
                new KeyValuePair <string, string>(SyntheticsHeader.HeaderKey, obfuscatedHeader)
            });
        }
        public IEnumerable <KeyValuePair <string, string> > TryGetOutboundResponseHeaders(IInternalTransaction transaction, TransactionMetricName transactionMetricName)
        {
            try
            {
                if (!_configurationService.Configuration.CrossApplicationTracingEnabled)
                {
                    return(Enumerable.Empty <KeyValuePair <string, string> >());
                }

                var refereeCrossProcessId = _configurationService.Configuration.CrossApplicationTracingCrossProcessId;
                if (refereeCrossProcessId == null)
                {
                    Log.Error("Failed to get cross process id for outbound response.");
                    _supportabilityMetrics.Record(CATSupportabilityCondition.Response_Create_Failure_XProcID);
                    return(Enumerable.Empty <KeyValuePair <string, string> >());
                }

                var encodedAppData = GetEncodedAppData(transaction, transactionMetricName, refereeCrossProcessId);

                _supportabilityMetrics.Record(CATSupportabilityCondition.Response_Create_Success);

                return(new Dictionary <string, string>
                {
                    { AppDataHttpHeader, encodedAppData },
                });
            }
            catch (Exception ex)
            {
                Log.Error($"Failed to get encoded CAT headers for outbound response: {ex}");
                _supportabilityMetrics.Record(CATSupportabilityCondition.Response_Create_Failure);
                return(Enumerable.Empty <KeyValuePair <string, string> >());
            }
        }
        public IEnumerable <KeyValuePair <string, string> > TryGetOutboundRequestHeaders(IInternalTransaction transaction)
        {
            try
            {
                if (!_configurationService.Configuration.CrossApplicationTracingEnabled)
                {
                    return(Enumerable.Empty <KeyValuePair <string, string> >());
                }

                var crossProcessId = _configurationService.Configuration.CrossApplicationTracingCrossProcessId;
                if (crossProcessId == null)
                {
                    Log.Error("Failed to get cross process id for outbound request.");
                    _supportabilityMetrics.Record(CATSupportabilityCondition.Request_Create_Failure_XProcID);
                    return(Enumerable.Empty <KeyValuePair <string, string> >());
                }

                var encodedNewRelicId      = GetEncodedNewRelicId(crossProcessId);
                var encodedTransactionData = GetEncodedTransactionData(transaction);

                _supportabilityMetrics.Record(CATSupportabilityCondition.Request_Create_Success);

                return(new Dictionary <string, string>
                {
                    { NewRelicIdHttpHeader, encodedNewRelicId },
                    { TransactionDataHttpHeader, encodedTransactionData }
                });
            }
            catch (Exception ex)
            {
                Log.Error($"Failed to get encoded CAT headers for outbound request: {ex}");

                _supportabilityMetrics.Record(CATSupportabilityCondition.Request_Create_Failure);

                return(Enumerable.Empty <KeyValuePair <string, string> >());
            }
        }
Пример #13
0
 public TransactionFinalizedEvent(IInternalTransaction transaction)
 {
     Transaction = transaction;
 }
Пример #14
0
        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}'");
                });
            }
        }
Пример #15
0
 private void UpdateTransactionMetaData(IInternalTransaction transaction, SyntheticsHeader syntheticsHeader)
 {
     transaction.TransactionMetadata.SetSyntheticsResourceId(syntheticsHeader.ResourceId);
     transaction.TransactionMetadata.SetSyntheticsJobId(syntheticsHeader.JobId);
     transaction.TransactionMetadata.SetSyntheticsMonitorId(syntheticsHeader.MonitorId);
 }
Пример #16
0
 private void UpdateReferrerCrossApplicationProcessId(IInternalTransaction transaction, string referrerCrossApplicationProcessId)
 {
     transaction.TransactionMetadata.SetCrossApplicationReferrerProcessId(referrerCrossApplicationProcessId);
 }