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)); }
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); } }
IInternalTransaction DoBeginTransaction(IsolationLevel isolationLevel) { ++_transactionCount; if (_main == null) { ImplicitOpen(); _current = _main = new Primary(this, isolationLevel); } else { _current = _current.CreateSub(isolationLevel); } return(_current); }
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); }
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); }
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)); }
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> >()); } }
public TransactionFinalizedEvent(IInternalTransaction transaction) { Transaction = transaction; }
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}'"); }); } }
private void UpdateTransactionMetaData(IInternalTransaction transaction, SyntheticsHeader syntheticsHeader) { transaction.TransactionMetadata.SetSyntheticsResourceId(syntheticsHeader.ResourceId); transaction.TransactionMetadata.SetSyntheticsJobId(syntheticsHeader.JobId); transaction.TransactionMetadata.SetSyntheticsMonitorId(syntheticsHeader.MonitorId); }
private void UpdateReferrerCrossApplicationProcessId(IInternalTransaction transaction, string referrerCrossApplicationProcessId) { transaction.TransactionMetadata.SetCrossApplicationReferrerProcessId(referrerCrossApplicationProcessId); }