public TransactionTraceWireModelComponents(TransactionMetricName transactionMetricName, TimeSpan duration, bool isSynthetics, GenerateWireModel generateWireModel)
 {
     _generateWireModel    = generateWireModel;
     Duration              = duration;
     IsSynthetics          = isSynthetics;
     TransactionMetricName = transactionMetricName;
 }
Esempio n. 2
0
        public TransactionMetricName GetTransactionMetricName(ITransactionName transactionName)
        {
            var proposedTransactionMetricName = new TransactionMetricName(transactionName.IsWeb ? MetricNames.WebTransactionPrefix : MetricNames.OtherTransactionPrefix, transactionName.UnprefixedName);

            var vettedTransactionMetricName = _metricNameService.RenameTransaction(proposedTransactionMetricName);

            return(vettedTransactionMetricName);
        }
        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);
        }
Esempio n. 4
0
        private void SetIntrinsicAttributes(IAttributeValueCollection attribValues, ImmutableTransaction immutableTransaction, TransactionMetricName transactionMetricName, TimeSpan?apdexT, TimeSpan totalTime, TransactionMetricStatsCollection txStats)
        {
            // Required transaction attributes
            _attribDefs.GetTypeAttribute(TypeAttributeValue.Transaction).TrySetDefault(attribValues);
            _attribDefs.Timestamp.TrySetValue(attribValues, immutableTransaction.StartTime);

            _attribDefs.TransactionName.TrySetValue(attribValues, transactionMetricName.PrefixedName);
            _attribDefs.TransactionNameForError.TrySetValue(attribValues, transactionMetricName.PrefixedName);

            // Duration is just EndTime minus StartTime for non-web transactions and response time otherwise
            _attribDefs.Duration.TrySetValue(attribValues, immutableTransaction.ResponseTimeOrDuration);

            // Total time is the total amount of time spent, even when work is happening parallel, which means it is the sum of all exclusive times.
            // https://source.datanerd.us/agents/agent-specs/blob/master/Total-Time-Async.md
            _attribDefs.TotalTime.TrySetValue(attribValues, totalTime);

            // CPU time is the total time spent actually doing work rather than waiting. Basically, it's TotalTime minus TimeSpentWaiting.
            // Our agent does not yet the ability to calculate time spent waiting, so we cannot generate this metric.
            // https://source.datanerd.us/agents/agent-specs/blob/master/Total-Time-Async.md
            //attributes.Add(Attribute.BuildCpuTime(immutableTransaction.Duration));

            // Optional transaction attributes
            _attribDefs.QueueDuration.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.QueueTime);
            _attribDefs.ApdexPerfZone.TrySetValue(attribValues, ApdexStats.GetApdexPerfZoneOrNull(immutableTransaction.ResponseTimeOrDuration, apdexT));


            if (immutableTransaction.IsWebTransaction())
            {
                _attribDefs.WebDuration.TrySetValue(attribValues, immutableTransaction.ResponseTimeOrDuration);
            }

            var externalData = txStats.GetUnscopedStat(MetricNames.ExternalAll);

            if (externalData != null)
            {
                _attribDefs.ExternalDuration.TrySetValue(attribValues, externalData.Value1);
                _attribDefs.ExternalCallCount.TrySetValue(attribValues, (float)externalData.Value0);
            }

            var databaseData = txStats.GetUnscopedStat(MetricNames.DatastoreAll);

            if (databaseData != null)
            {
                _attribDefs.DatabaseDuration.TrySetValue(attribValues, databaseData.Value1);
                _attribDefs.DatabaseCallCount.TrySetValue(attribValues, databaseData.Value0);
            }

            if (_configurationService.Configuration.ErrorCollectorEnabled && immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.HasError)
            {
                var errorData = immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.ErrorData;

                _attribDefs.GetTypeAttribute(TypeAttributeValue.TransactionError).TrySetDefault(attribValues);

                _attribDefs.TimestampForError.TrySetValue(attribValues, errorData.NoticedAt);
                _attribDefs.ErrorClass.TrySetValue(attribValues, errorData.ErrorTypeName);
                _attribDefs.ErrorType.TrySetValue(attribValues, errorData.ErrorTypeName);
                _attribDefs.ErrorMessage.TrySetValue(attribValues, errorData.ErrorMessage);
                _attribDefs.ErrorDotMessage.TrySetValue(attribValues, errorData.ErrorMessage);
                _attribDefs.IsError.TrySetValue(attribValues, true);
                _attribDefs.ErrorEventSpanId.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.ErrorDataSpanId);

                if (errorData.IsExpected)
                {
                    _attribDefs.IsErrorExpected.TrySetValue(attribValues, true);
                }
            }

            var isCatParticipant              = IsCatParticipant(immutableTransaction);
            var isSyntheticsParticipant       = IsSyntheticsParticipant(immutableTransaction);
            var isDistributedTraceParticipant = immutableTransaction.TracingState != null && immutableTransaction.TracingState.HasDataForAttributes;

            // Add the tripId attribute unconditionally, when DT disabled, so it can be used to correlate with
            // this app's PageView events. If CrossApplicationReferrerTripId is null then this transaction started the first external request,
            // so use its guid.
            if (!_configurationService.Configuration.DistributedTracingEnabled)
            {
                var tripId = immutableTransaction.TransactionMetadata.CrossApplicationReferrerTripId ?? immutableTransaction.Guid;
                _attribDefs.TripId.TrySetValue(attribValues, tripId);
                _attribDefs.CatNrTripId.TrySetValue(attribValues, tripId);
            }

            if (isCatParticipant)
            {
                _attribDefs.NrGuid.TrySetValue(attribValues, immutableTransaction.Guid);
                _attribDefs.CatReferringPathHash.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.CrossApplicationReferrerPathHash);
                _attribDefs.CatPathHash.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.CrossApplicationPathHash);
                _attribDefs.CatNrPathHash.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.CrossApplicationPathHash);
                _attribDefs.ClientCrossProcessId.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.CrossApplicationReferrerProcessId);
                _attribDefs.CatReferringTransactionGuidForEvents.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.CrossApplicationReferrerTransactionGuid);
                _attribDefs.CatReferringTransactionGuidForTraces.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.CrossApplicationReferrerTransactionGuid);
                _attribDefs.CatAlternativePathHashes.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.CrossApplicationAlternatePathHashes);
            }
            else if (isDistributedTraceParticipant)
            {
                _attribDefs.ParentSpanId.TrySetValue(attribValues, immutableTransaction.TracingState.ParentId ?? immutableTransaction.TracingState.Guid);
                _attribDefs.ParentTransportType.TrySetValue(attribValues, immutableTransaction.TracingState.TransportType);
                _attribDefs.ParentTransportTypeForSpan.TrySetValue(attribValues, immutableTransaction.TracingState.TransportType);

                if (immutableTransaction.TracingState.HasDataForParentAttributes)
                {
                    _attribDefs.ParentTypeForDistributedTracing.TrySetValue(attribValues, immutableTransaction.TracingState.Type);
                    _attribDefs.ParentApp.TrySetValue(attribValues, immutableTransaction.TracingState.AppId);
                    _attribDefs.ParentAccount.TrySetValue(attribValues, immutableTransaction.TracingState.AccountId);
                    _attribDefs.ParentId.TrySetValue(attribValues, immutableTransaction.TracingState.TransactionId);
                    _attribDefs.ParentTransportDuration.TrySetValue(attribValues, immutableTransaction.TracingState.TransportDuration);

                    _attribDefs.ParentTypeForDistributedTracingForSpan.TrySetValue(attribValues, immutableTransaction.TracingState.Type);
                    _attribDefs.ParentAppForSpan.TrySetValue(attribValues, immutableTransaction.TracingState.AppId);
                    _attribDefs.ParentAccountForSpan.TrySetValue(attribValues, immutableTransaction.TracingState.AccountId);
                    _attribDefs.ParentTransportDurationForSpan.TrySetValue(attribValues, immutableTransaction.TracingState.TransportDuration);
                }
            }

            if (_configurationService.Configuration.DistributedTracingEnabled)
            {
                _attribDefs.Guid.TrySetValue(attribValues, immutableTransaction.Guid);
                _attribDefs.DistributedTraceId.TrySetValue(attribValues, immutableTransaction.TraceId);
                _attribDefs.Priority.TrySetValue(attribValues, immutableTransaction.Priority);
                _attribDefs.Sampled.TrySetValue(attribValues, immutableTransaction.Sampled);
            }

            if (isSyntheticsParticipant)
            {
                _attribDefs.NrGuid.TrySetValue(attribValues, immutableTransaction.Guid);

                _attribDefs.SyntheticsResourceId.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.SyntheticsResourceId);
                _attribDefs.SyntheticsResourceIdForTraces.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.SyntheticsResourceId);

                _attribDefs.SyntheticsJobId.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.SyntheticsJobId);
                _attribDefs.SyntheticsJobIdForTraces.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.SyntheticsJobId);

                _attribDefs.SyntheticsMonitorId.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.SyntheticsMonitorId);
                _attribDefs.SyntheticsMonitorIdForTraces.TrySetValue(attribValues, immutableTransaction.TransactionMetadata.SyntheticsMonitorId);
            }
        }
Esempio n. 5
0
        public IAttributeValueCollection GetAttributes(ImmutableTransaction immutableTransaction, TransactionMetricName transactionMetricName, TimeSpan?apdexT, TimeSpan totalTime, TransactionMetricStatsCollection txStats)
        {
            var attribVals = new AttributeValueCollection(AttributeValueCollection.AllTargetModelTypes);

            SetUserAndAgentAttributes(attribVals, immutableTransaction.TransactionMetadata);
            SetIntrinsicAttributes(attribVals, immutableTransaction, transactionMetricName, apdexT, totalTime, txStats);

            return(attribVals);
        }
        private void GenerateAndCollectSqlTrace(ImmutableTransaction immutableTransaction, TransactionMetricName transactionMetricName, TransactionMetricStatsCollection txStats)
        {
            if (!_configurationService.Configuration.SlowSqlEnabled)
            {
                return;
            }

            var txSqlTrStats = new SqlTraceStatsCollection();

            foreach (var segment in immutableTransaction.Segments.Where(s => s.Data is DatastoreSegmentData))
            {
                var datastoreSegmentData = (DatastoreSegmentData)segment.Data;
                if (datastoreSegmentData.CommandText != null &&
                    segment.Duration >= _configurationService.Configuration.SqlExplainPlanThreshold)
                {
                    AddSqlTraceStats(txSqlTrStats, _sqlTraceMaker.TryGetSqlTrace(immutableTransaction, transactionMetricName, segment));
                }
            }

            if (txSqlTrStats.Collection.Count > 0)
            {
                using (_agentTimerService.StartNew("CollectSqlTrace"))
                {
                    _sqlTraceAggregator.Collect(txSqlTrStats);
                }

                MetricBuilder.TryBuildSqlTracesCollectedMetric(txSqlTrStats.TracesCollected, txStats);
            }
        }
        private void GenerateAndCollectTransactionTrace(ImmutableTransaction immutableTransaction, TransactionMetricName transactionMetricName, Func <IAttributeValueCollection> attributes)
        {
            if (!_configurationService.Configuration.TransactionTracerEnabled)
            {
                return;
            }

            var traceComponents = new TransactionTraceWireModelComponents(
                transactionMetricName,
                immutableTransaction.Duration,
                immutableTransaction.TransactionMetadata.IsSynthetics,
                () => _transactionTraceMaker.GetTransactionTrace(immutableTransaction, _segmentTreeMaker.BuildSegmentTrees(immutableTransaction.Segments), transactionMetricName, attributes.Invoke()));

            using (_agentTimerService.StartNew("CollectTransactionTrace"))
            {
                _transactionTraceAggregator.Collect(traceComponents);
            }
        }
        private void GenerateAndCollectErrorEventTracesAndEvents(ImmutableTransaction immutableTransaction, IAttributeValueCollection attributes, TransactionMetricName transactionMetricName)
        {
            var errorTrace = GenerateErrorTrace(immutableTransaction, attributes, transactionMetricName);

            if (errorTrace == null)
            {
                return;
            }

            using (_agentTimerService.StartNew("CollectErrorTrace"))
            {
                _errorTraceAggregator.Collect(errorTrace);
            }

            if (_configurationService.Configuration.ErrorCollectorCaptureEvents)
            {
                var errorEvent = _errorEventMaker.GetErrorEvent(immutableTransaction, attributes);
                using (_agentTimerService.StartNew("CollectErrorEvent"))
                {
                    _errorEventAggregator.Collect(errorEvent);
                }
            }
        }
        private ErrorTraceWireModel GenerateErrorTrace(ImmutableTransaction immutableTransaction, IAttributeValueCollection attributes, TransactionMetricName transactionMetricName)
        {
            if (!ErrorCollectionEnabled())
            {
                return(null);
            }

            return(_errorTraceMaker.GetErrorTrace(immutableTransaction, attributes, transactionMetricName));
        }
Esempio n. 10
0
        public SqlTraceWireModel TryGetSqlTrace(ImmutableTransaction immutableTransaction, TransactionMetricName transactionMetricName, Segment segment)
        {
            var segmentData = segment.Data as DatastoreSegmentData;

            if (segment.Duration == null || segmentData == null)
            {
                return(null);
            }

            var transactionName = transactionMetricName.PrefixedName;

            var uri = _attribDefs.RequestUri.IsAvailableForAny(AttributeDestinations.SqlTrace)
                ? immutableTransaction.TransactionMetadata.Uri ?? "<unknown>"
                : "<unknown>";

            var sql   = _databaseService.GetObfuscatedSql(segmentData.CommandText, segmentData.DatastoreVendorName);
            var sqlId = _databaseService.GetSqlId(segmentData.CommandText, segmentData.DatastoreVendorName);

            var       metricName    = segmentData.GetTransactionTraceName();
            const int count         = 1;
            var       totalCallTime = segment.Duration.Value;
            var       parameterData = new Dictionary <string, object>(); // Explain plans will go here

            if (segmentData.ExplainPlan != null)
            {
                parameterData.Add("explain_plan", new ExplainPlanWireModel(segmentData.ExplainPlan));
            }

            if (_configurationService.Configuration.InstanceReportingEnabled)
            {
                parameterData.Add("host", segmentData.Host);
                parameterData.Add("port_path_or_id", segmentData.PortPathOrId);
            }

            if (_configurationService.Configuration.DatabaseNameReportingEnabled)
            {
                parameterData.Add("database_name", segmentData.DatabaseName);
            }

            if (segmentData.QueryParameters != null)
            {
                parameterData["query_parameters"] = segmentData.QueryParameters;
            }

            var sqlTraceData = new SqlTraceWireModel(transactionName, uri, sqlId, sql, metricName, count, totalCallTime, totalCallTime, totalCallTime, parameterData);

            return(sqlTraceData);
        }
Esempio n. 11
0
        /// <summary>
        /// Gets an <see cref="NewRelic.Agent.Core.WireModels.ErrorTraceWireModel"/> given
        /// a transaction, transaction attributes and an error referenced by an <see cref="NewRelic.Agent.Core.Errors.ErrorData"/>
        /// occurring inside of a transaction.
        /// </summary>
        /// <remarks>
        /// The <param name="errorData"></param> passed to this method is assumed to contain valid error information.
        /// The method won't throw if it is not but will send meaningless data in some of the attributes.
        /// </remarks>
        /// <param name="immutableTransaction"></param>
        /// <param name="transactionAttributes"></param>
        /// <param name="transactionMetricName"></param>
        /// <param name="errorData"></param>
        /// <returns></returns>
        public ErrorTraceWireModel GetErrorTrace(ImmutableTransaction immutableTransaction, IAttributeValueCollection transactionAttributes, TransactionMetricName transactionMetricName)
        {
            var errorData = immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.ErrorData;

            var stackTrace = GetFormattedStackTrace(errorData);

            var timestamp                = errorData.NoticedAt;
            var path                     = transactionMetricName.PrefixedName;
            var message                  = errorData.ErrorMessage;
            var exceptionClassName       = errorData.ErrorTypeName;
            var errorAttributesWireModel = GetErrorTraceAttributes(transactionAttributes, stackTrace);
            var guid                     = immutableTransaction.Guid;

            return(new ErrorTraceWireModel(timestamp, path, message, exceptionClassName, errorAttributesWireModel, guid));
        }
        public TransactionTraceWireModel GetTransactionTrace(ImmutableTransaction immutableTransaction, IEnumerable <ImmutableSegmentTreeNode> segmentTrees, TransactionMetricName transactionMetricName, IAttributeValueCollection attribValues)
        {
            segmentTrees = segmentTrees.ToList();

            if (!segmentTrees.Any())
            {
                throw new ArgumentException("There must be at least one segment to create a trace");
            }

            var filteredAttributes = new AttributeValueCollection(attribValues, AttributeDestinations.TransactionTrace);

            // See spec for details on these fields: https://source.datanerd.us/agents/agent-specs/blob/master/Transaction-Trace-LEGACY.md
            var    startTime = immutableTransaction.StartTime;
            var    duration  = immutableTransaction.ResponseTimeOrDuration;
            string uri       = null;

            if (_attribDefs.RequestUri.IsAvailableForAny(AttributeDestinations.TransactionTrace))
            {
                uri = immutableTransaction.TransactionMetadata.Uri?.TrimAfterAChar(StringSeparators.QuestionMarkChar) ?? "/Unknown";
            }

            var guid          = immutableTransaction.Guid;
            var xraySessionId = null as ulong?; // The .NET agent does not support xray sessions

            var isSynthetics         = immutableTransaction.TransactionMetadata.IsSynthetics;
            var syntheticsResourceId = immutableTransaction.TransactionMetadata.SyntheticsResourceId;
            var rootSegment          = GetRootSegment(segmentTrees, immutableTransaction);


            var traceData = new TransactionTraceData(startTime, rootSegment, attribValues);

            var trace = new TransactionTraceWireModel(startTime, duration, transactionMetricName.PrefixedName, uri, traceData, guid, xraySessionId, syntheticsResourceId, isSynthetics);

            return(trace);
        }