private async Task RunEventsAsync(Run run) { var config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .Build(); IRunnerSettings runnerSettings = config.GetSection(nameof(RunnerSettings)).Get <RunnerSettings>(); Console.WriteLine("Warming up thread pool..."); System.Threading.ThreadPool.SetMaxThreads(32767, 32767); System.Threading.ThreadPool.SetMinThreads(32767, 32767); Console.WriteLine("Nesting events..."); //Remove any sessions with no events run.Sessions.RemoveAll(s => s.Events.Count == 0); foreach (Session session in run.Sessions) { var nestedEvents = new List <Event>(); Transaction parentTransaction = null; foreach (Event evt in session.Events) { if (parentTransaction != null && evt.TransactionId != "0") { parentTransaction.Events.Add(evt); } else { nestedEvents.Add(evt); } if (evt is Transaction transaction) { switch (transaction.TransactionState) { case "Begin": parentTransaction = transaction; break; case "Commit": case "Rollback": parentTransaction = session.Events .Where(e => ((e as Transaction)?.Events.Contains(parentTransaction)).GetValueOrDefault()) .SingleOrDefault() as Transaction; break; } } } session.Events = nestedEvents; } Console.WriteLine("Preparing 15 second buckets of sessions..."); var buckets = run.Sessions.GroupBy(s => { Event firstEvt = s.Events.First(); return(firstEvt.Timestamp.ToString("ddHHmm") + firstEvt.Timestamp.Second / runnerSettings.BucketInterval); }) .OrderBy(g => g.Key) .Select(g => g.OrderBy(s => s.Events.First().Timestamp) .ToList() ).ToList(); Console.WriteLine("Kicking off executions..."); var tasks = new List <Task>(); var eventExecutor = new EventExecutor(); var replayOrigin = DateTimeOffset.UtcNow; foreach (var bucket in buckets) { var bucketTimestamp = bucket.First().Events.First().Timestamp; TimeSpan timeToDelay = bucketTimestamp.Subtract(run.EventCaptureOrigin).Subtract(DateTimeOffset.UtcNow.Subtract(replayOrigin)); if (timeToDelay.TotalMilliseconds > 0) { await Task.Delay(timeToDelay); } Console.WriteLine("Starting bucket: " + bucketTimestamp); tasks.Add(eventExecutor.ExecuteSessionEventsAsync(run.EventCaptureOrigin, replayOrigin, bucket, run.ConnectionString, runnerSettings)); Console.WriteLine("Ending Delay: " + bucketTimestamp); } Console.WriteLine("Waiting for unfinished executions to complete..."); await Task.WhenAll(tasks); Console.WriteLine("Executions complete."); this.Exceptions.AddRange(eventExecutor.Exceptions); }
public Task RunAsync(Run run, DateTimeOffset restorePoint, int durationInMinutes, string[] storedProcedureNamesToExclude) { var matchCriteria = StoredProcedureSearch.CreateMatchCriteria(storedProcedureNamesToExclude); if (matchCriteria.Any()) { if (durationInMinutes > 0) { foreach (var session in run.Sessions) { session.Events.RemoveAll(e => !(!matchCriteria.Any(mc => ((e as Rpc)?.Procedure?.Equals(mc, StringComparison.CurrentCultureIgnoreCase)) .GetValueOrDefault()) && e.Timestamp > restorePoint && e.Timestamp < run.EventCaptureOrigin.AddMinutes(durationInMinutes))); } } else { foreach (var session in run.Sessions) { session.Events.RemoveAll(e => !(!matchCriteria.Any(mc => ((e as Rpc)?.Procedure?.Equals(mc, StringComparison.CurrentCultureIgnoreCase)) .GetValueOrDefault()) && e.Timestamp > restorePoint)); } } } else { if (durationInMinutes > 0) { foreach (var session in run.Sessions) { session.Events.RemoveAll(e => !(e.Timestamp > restorePoint && e.Timestamp < run.EventCaptureOrigin.AddMinutes(durationInMinutes))); } } else { foreach (var session in run.Sessions) { session.Events.RemoveAll(e => !(e.Timestamp > restorePoint)); } } } foreach (var session in run.Sessions) { session.Events.RemoveAll(e => { if (e is Rpc rpc) { return(rpc.Statement.Contains("OPENROWSET", StringComparison.CurrentCultureIgnoreCase) || rpc.Statement.Contains("OPENDATASOURCE", StringComparison.CurrentCultureIgnoreCase)); } return(false); }); } run.EventCaptureOrigin = restorePoint; return(RunEventsAsync(run)); }
public async Task Run(Run run) { //Prepare threads in thread pool System.Threading.ThreadPool.SetMaxThreads(32767, 32767); System.Threading.ThreadPool.SetMinThreads(32767, 32767); Console.WriteLine("Preparing 15 second buckets..."); //DuplicateEvents(run, 4); //synthetically increase load //var matchCriteria = new List<string>() //{ // "something I want to exclude" //}; var allEvents = run.Sessions.SelectMany(s => s.Events) //.Where(e => !matchCriteria.Any(mc => ((e as Rpc)?.ObjectName.Contains(mc, StringComparison.CurrentCultureIgnoreCase)).GetValueOrDefault())) //leave these out .ToList(); var allDependentEvents = allEvents.Where(e => e.TransactionId != "0" && ((e is Rpc) || (e as Transaction)?.TransactionState != "Begin")).ToList(); var allIndependentEvents = allEvents.Where(e => e.TransactionId == "0" || (e as Transaction)?.TransactionState == "Begin"); var groups = allIndependentEvents.GroupBy(r => r.Timestamp.ToString("ddhhmm") + r.Timestamp.Second / 15).OrderBy(g => g.Key); var buckets = new Dictionary <string, List <Event> >(); foreach (var group in groups) { var trxStarts = group.Where(e => e.TransactionId != "0").Select(e => (e as Transaction)).ToList(); var startHash = new HashSet <string>(trxStarts.Select(x => x.TransactionId)); var startDict = new Dictionary <string, Transaction>(); foreach (var trx in trxStarts) { trx.Events = new List <Event>(); startDict.Add(trx.TransactionId, trx); } var bucket = new List <Event>(group); foreach (var evt in allDependentEvents) { if (startHash.Contains(evt.TransactionId)) { startDict[evt.TransactionId].Events.Add(evt); } } foreach (var trx in trxStarts) { trx.Events = trx.Events.OrderBy(e => e.EventSequence).ToList(); //Avoid stragglers at end of trace that don't include a commit or rollback if (!trx.Events.Any(e => (e as Transaction)?.TransactionState == "Commit" || (e as Transaction)?.TransactionState == "Rollback")) { Event model; if (trx.Events.Count > 0) { model = trx.Events.Last(); } else { model = trx; } trx.Events.Add(new Transaction { TransactionId = model.TransactionId, TransactionState = "Commit", EventSequence = (int.Parse(model.EventSequence) + 1).ToString(), Timestamp = model.Timestamp.AddMilliseconds(100) }); } } buckets.Add(group.Key, bucket); } var bucketEvents = buckets.SelectMany(b => b.Value.Select(e => e)); var orphanEvents = allEvents.Except(bucketEvents); foreach (var evt in orphanEvents) { string key = evt.Timestamp.ToString("ddhhmm") + evt.Timestamp.Second / 15; if (buckets.TryGetValue(key, out var events)) { events.Add(evt); } else { buckets.Add(key, new List <Event> { evt }); } } var orderedBuckets = buckets.OrderBy(b => b.Key).Select(b => b.Value.OrderBy(e => e.Timestamp).ToList()).ToList(); Console.WriteLine("Kicking off executions..."); List <Task> tasks = new List <Task>(); var eventExecutor = new EventExecutor(); DateTimeOffset replayOrigin = DateTimeOffset.UtcNow; foreach (var bucket in orderedBuckets) { Console.WriteLine("Starting bucket: " + bucket[0].Timestamp); tasks.Add(eventExecutor.ExecuteEvents(run.EventCaptureOrigin, replayOrigin, bucket, run.ConnectionString)); await Task.Delay(15000); Console.WriteLine("Ending Delay: " + bucket[0].Timestamp); } Console.WriteLine("Waiting for unfinished executions to complete..."); await Task.WhenAll(tasks); Console.WriteLine("Executions complete."); this.Exceptions.AddRange(eventExecutor.Exceptions); }