public IInternalTransaction GetOrCreateInternalTransaction(ITransactionName initialTransactionName, Action onCreate = null, bool doNotTrackAsUnitOfWork = true) { var transaction = GetCurrentInternalTransaction(); if (transaction == null) { return(CreateInternalTransaction(initialTransactionName, onCreate)); } var currentNestedTransactionAttempts = transaction.NoticeNestedTransactionAttempt(); // If the transaction does not need to be root, then it really is a unit of work inside the current transaction, so increment the work counter to make sure all work is finished before the current transaction ends if (!doNotTrackAsUnitOfWork) { transaction.NoticeUnitOfWorkBegins(); } // We have a limit of 100 because 100 attempts to nest a transaction indicates that something has gone wrong (e.g. a transaction is never ending and is being reused over and over) if (currentNestedTransactionAttempts > 100) { Log.WarnFormat("Releasing the transaction because there were too many nested transaction attempts."); RemoveOutstandingInternalTransactions(true, true); return(CreateInternalTransaction(initialTransactionName, onCreate)); } return(transaction); }
public TransactionMetricName GetTransactionMetricName(ITransactionName transactionName) { var proposedTransactionMetricName = new TransactionMetricName(transactionName.IsWeb ? MetricNames.WebTransactionPrefix : MetricNames.OtherTransactionPrefix, transactionName.UnprefixedName); var vettedTransactionMetricName = _metricNameService.RenameTransaction(proposedTransactionMetricName); return(vettedTransactionMetricName); }
public void Test(TestCase testCase) { // ARRANGE SetUp(testCase); var transactionMetricName = GetTransactionMetricName(testCase.TransactionName); Mock.Arrange(() => _transactionMetricNameMaker.GetTransactionMetricName(Arg.IsAny <ITransactionName>())) .Returns(transactionMetricName); ITimer timer = Mock.Create <ITimer>(); var responseTime = TimeSpan.FromMilliseconds(testCase.ApplicationTimeMilliseconds); Mock.Arrange(() => timer.Duration).Returns(responseTime); ITransactionName name = TransactionName.ForWebTransaction(transactionMetricName.Prefix, transactionMetricName.UnPrefixedName); var priority = 0.5f; IInternalTransaction tx = new Transaction(_configuration, name, timer, DateTime.UtcNow, Mock.Create <ICallStackManager>(), Mock.Create <IDatabaseService>(), priority, Mock.Create <IDatabaseStatementParser>(), Mock.Create <IDistributedTracePayloadHandler>(), Mock.Create <IErrorService>(), _attribDefs); tx.TransactionMetadata.SetQueueTime(TimeSpan.FromMilliseconds(testCase.QueueTimeMilliseconds)); testCase.UserAttributes.ForEach(attr => tx.AddCustomAttribute(attr.Key, attr.Value)); tx.TransactionMetadata.SetCrossApplicationReferrerTripId(""); // ACT var browserMonitoringScript = _browserMonitoringScriptMaker.GetScript(tx); // ASSERT var extractedConfigurationDataJson = Regex.Match(browserMonitoringScript, @"NREUM.info = (\{.+\})").Groups[1].Value; var actualConfigurationData = JsonConvert.DeserializeObject <ExpectedBrowserMonitoringConfigurationData>(extractedConfigurationDataJson); NrAssert.Multiple ( () => Assert.AreEqual(testCase.ExpectedConfigurationData.Agent, actualConfigurationData.Agent), () => Assert.AreEqual(testCase.ExpectedConfigurationData.ApplicationId, actualConfigurationData.ApplicationId), () => Assert.AreEqual(testCase.ExpectedConfigurationData.ApplicationTimeMilliseconds, actualConfigurationData.ApplicationTimeMilliseconds), () => Assert.AreEqual(testCase.ExpectedConfigurationData.Beacon, actualConfigurationData.Beacon), () => Assert.AreEqual(testCase.ExpectedConfigurationData.BrowserLicenseKey, actualConfigurationData.BrowserLicenseKey), () => Assert.AreEqual(testCase.ExpectedConfigurationData.ErrorBeacon, actualConfigurationData.ErrorBeacon), () => Assert.AreEqual(testCase.ExpectedConfigurationData.ObfuscatedTransactionName, actualConfigurationData.ObfuscatedTransactionName), () => Assert.AreEqual(testCase.ExpectedConfigurationData.ObfuscatedUserAttributes, actualConfigurationData.ObfuscatedUserAttributes), () => Assert.AreEqual(testCase.ExpectedConfigurationData.QueueTimeMilliseconds, actualConfigurationData.QueueTimeMilliseconds) ); Teardown(); }
// The sqlObfuscator parameter should be the SQL obfuscator as defined by user configuration: obfuscate, off, or raw. public ImmutableTransaction(ITransactionName transactionName, IEnumerable <Segment> segments, IImmutableTransactionMetadata transactionMetadata, DateTime startTime, TimeSpan duration, TimeSpan?responseTime, string guid, bool ignoreAutoBrowserMonitoring, bool ignoreAllBrowserMonitoring, bool ignoreApdex, float priority, bool?sampled, string traceId, ITracingState tracingState, IAttributeDefinitions attribDefs) { TransactionName = transactionName; Segments = segments.Where(segment => segment != null).ToList(); TransactionMetadata = transactionMetadata; StartTime = startTime; Duration = duration; ResponseTimeOrDuration = IsWebTransaction() ? responseTime ?? Duration : Duration; Guid = guid; IgnoreAutoBrowserMonitoring = ignoreAutoBrowserMonitoring; IgnoreAllBrowserMonitoring = ignoreAllBrowserMonitoring; IgnoreApdex = ignoreApdex; Priority = priority; Sampled = sampled.HasValue ? sampled.Value : false; TraceId = traceId; TracingState = tracingState; _attribDefs = attribDefs; }
public bool TrySet(ITransactionName transactionName, TransactionNamePriority priority) { // We could define this lock to be more coarse grained if we added extra variables // to track the before/after stuff for logging, but finest is rarely enabled, and if it is // things are already slow, so just do the logging under the lock. lock (this) { if (Log.IsFinestEnabled) { if (_isFrozen) { _transaction.LogFinest($"Ignoring transaction name {FormatTransactionName(transactionName, priority)} because existing transaction name is frozen."); } else if (_currentTransactionName == null) { _transaction.LogFinest($"Setting transaction name to {FormatTransactionName(transactionName, priority)} from [nothing]"); } else if (priority > _highestPriority) { _transaction.LogFinest($"Setting transaction name to {FormatTransactionName(transactionName, priority)} from {FormatTransactionName(_currentTransactionName, _highestPriority)}"); } else { _transaction.LogFinest($"Ignoring transaction name {FormatTransactionName(transactionName, priority)} in favor of existing name {FormatTransactionName(_currentTransactionName, _highestPriority)}"); } } if (ChangeName(priority)) { _highestPriority = priority; _currentTransactionName = transactionName; return(true); } } return(false); }
private IInternalTransaction CreateInternalTransaction(ITransactionName initialTransactionName, Action onCreate) { RemoveOutstandingInternalTransactions(true, true); var transactionContext = GetFirstActivePrimaryContext(); if (transactionContext == null) { Log.Error("Unable to locate a valid TransactionContext."); return(null); } var priority = _tracePriorityManager.Create(); var transaction = new Transaction(_configuration, initialTransactionName, _timerFactory.StartNewTimer(), DateTime.UtcNow, _callStackManagerFactory.CreateCallStackManager(), _databaseService, priority, _databaseStatementParser, _distributedTracePayloadHandler, _errorService, _attribDefSvc.AttributeDefs); try { transactionContext.SetData(transaction); } catch (Exception exception) { Log.Error($"The chosen TransactionContext threw an exception when setting the data: {exception}"); return(null); } if (Log.IsFinestEnabled) { transaction.LogFinest($"Created transaction on {transactionContext}"); } if (onCreate != null) { onCreate(); } return(transaction); }
public CandidateTransactionName(ITransaction transaction, ITransactionName initialTransactionName) { _transaction = transaction; _currentTransactionName = initialTransactionName; _highestPriority = 0; }
private static string FormatTransactionName(ITransactionName transactionName, TransactionNamePriority priority) { return($"{transactionName.GetType().Name}{JsonConvert.SerializeObject(transactionName)} (priority {(int)priority}, {priority})"); }
public ImmutableTransactionBuilder IsOtherTransaction(string category, string name) { _transactionName = TransactionName.ForOtherTransaction(category, name); return(this); }