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); } }