private TimeSpan?GetApdexT(ImmutableTransaction immutableTransaction, string transactionApdexMetricName)
        {
            var apdexT = _metricNameService.TryGetApdex_t(transactionApdexMetricName);

            if (immutableTransaction.IsWebTransaction())
            {
                apdexT = apdexT ?? _configurationService.Configuration.TransactionTraceApdexT;
            }

            return(apdexT);
        }
        private void GetApdexMetrics(ImmutableTransaction immutableTransaction, TimeSpan apdexT, string transactionApdexMetricName, TransactionMetricStatsCollection txStats)
        {
            var isWebTransaction = immutableTransaction.IsWebTransaction();

            if (immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.HasError &&
                !immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.ErrorData.IsExpected)
            {
                MetricBuilder.TryBuildFrustratedApdexMetrics(isWebTransaction, transactionApdexMetricName, txStats);
            }
            else
            {
                MetricBuilder.TryBuildApdexMetrics(transactionApdexMetricName, isWebTransaction, immutableTransaction.ResponseTimeOrDuration, apdexT, txStats);
            }
        }
Beispiel #3
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);
            }
        }
        private void GenerateAndCollectMetrics(ImmutableTransaction immutableTransaction, TimeSpan?apdexT, string transactionApdexMetricName, TimeSpan totalTime, TransactionMetricStatsCollection txStats)
        {
            foreach (var segment in immutableTransaction.Segments)
            {
                GenerateSegmentMetrics(segment, txStats);
            }

            var isWebTransaction = immutableTransaction.IsWebTransaction();

            if (_configurationService.Configuration.DistributedTracingEnabled)
            {
                TimeSpan duration  = default;
                string   type      = default;
                string   account   = default;
                string   app       = default;
                string   transport = default;

                if (immutableTransaction.TracingState != null)
                {
                    duration = immutableTransaction.TracingState.TransportDuration;
                    type     = EnumNameCache <DistributedTracingParentType> .GetName(immutableTransaction.TracingState.Type);

                    account   = immutableTransaction.TracingState.AccountId;
                    app       = immutableTransaction.TracingState.AppId;
                    transport = EnumNameCache <TransportType> .GetName(immutableTransaction.TracingState.TransportType);
                }

                MetricBuilder.TryBuildDistributedTraceDurationByCaller(type, account, app, transport, isWebTransaction,
                                                                       immutableTransaction.Duration, txStats);

                if (immutableTransaction.TracingState != null)
                {
                    MetricBuilder.TryBuildDistributedTraceTransportDuration(type, account, app, transport, isWebTransaction, duration, txStats);
                }

                if (ErrorCollectionEnabled() && immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.HasError)
                {
                    MetricBuilder.TryBuildDistributedTraceErrorsByCaller(type, account, app, transport, isWebTransaction, txStats);
                }
            }

            MetricBuilder.TryBuildTransactionMetrics(isWebTransaction, immutableTransaction.ResponseTimeOrDuration, txStats);

            // 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
            MetricBuilder.TryBuildTotalTimeMetrics(isWebTransaction, totalTime, txStats);

            // 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
            //_metricBuilder.TryBuildCpuTimeRollupMetric(isWebTransaction, immutableTransaction.Duration, txStats),
            //_metricBuilder.TryBuildCpuTimeMetric(transactionMetricName, immutableTransaction.Duration, txStats)

            if (immutableTransaction.TransactionMetadata.QueueTime != null)
            {
                MetricBuilder.TryBuildQueueTimeMetric(immutableTransaction.TransactionMetadata.QueueTime.Value, txStats);
            }

            if (apdexT != null && !immutableTransaction.IgnoreApdex)
            {
                GetApdexMetrics(immutableTransaction, apdexT.Value, transactionApdexMetricName, txStats);
            }

            if (ErrorCollectionEnabled() && immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.HasError)
            {
                var isErrorExpected = immutableTransaction.TransactionMetadata.ReadOnlyTransactionErrorState.ErrorData.IsExpected;
                MetricBuilder.TryBuildErrorsMetrics(isWebTransaction, txStats, isErrorExpected);
            }

            var referrerCrossProcessId = immutableTransaction.TransactionMetadata.CrossApplicationReferrerProcessId;

            if (referrerCrossProcessId != null)
            {
                var catResponseTime = TimeSpan.FromSeconds(immutableTransaction.TransactionMetadata.CrossApplicationResponseTimeInSeconds);
                MetricBuilder.TryBuildClientApplicationMetric(referrerCrossProcessId, catResponseTime, catResponseTime, txStats);
            }

            using (_agentTimerService.StartNew("CollectMetrics"))
            {
                _metricAggregator.Collect(txStats);
            }
        }