public static string GetExecutionSummary(ExecutionOptionsClass executionOptions, dynamic loadGeneratee, Func <byte[]> loadGenerator) { StringBuilder summary = new StringBuilder(); summary.AppendLine("-----INITIAL PARAMETERS-----"); summary.AppendLine($"Execution started: { DateTime.Now.ToUniversalTime() }"); summary.AppendLine(ReturnAllProperties(executionOptions)); summary.AppendLine($"Sample payload: { Encoding.UTF8.GetString(loadGenerator()) }"); summary.AppendLine("-----INTERACTIVITY-----"); summary.AppendLine("Press Q/A to increase/decrease the target throughput"); summary.AppendLine("Press W/S to increase/decrease batch size"); summary.AppendLine("Press Escape to cancel all threads and gracefully exit"); summary.AppendLine("-----EXECUTION LOG FOLLOWS-----"); return(summary.ToString()); }
public static int Main(string[] args) { bool isConsoleRedirected = Console.IsInputRedirected || Console.IsErrorRedirected || Console.IsOutputRedirected; int exitCode = 0; OrchestratorClass loadOrchestrator; dynamic loadGeneratee = null; System.Timers.Timer telemetryTimer = new System.Timers.Timer(); Func <byte[]> func; DateTime terminationDT = DateTime.MaxValue; ExecutionOptionsClass executionOptions = new ExecutionOptionsClass(); try { Parser.Default.ParseArguments <ExecutionOptionsClass>(args) .WithParsed <ExecutionOptionsClass>(parsedOptions => { executionOptions = parsedOptions; telemetryTimer = new System.Timers.Timer(executionOptions.Checkpoint); if (executionOptions.TerminateAfter > 0) { terminationDT = DateTime.Now.AddSeconds(executionOptions.TerminateAfter); } }) .WithNotParsed <ExecutionOptionsClass>(errors => { Console.WriteLine("Failed to parse command line arguments"); foreach (Error error in errors) { Console.WriteLine(error.ToString()); } exitCode = -1; }); switch (executionOptions.Service) { case "eh": loadGeneratee = new EHLoadGeneratorClass( executionOptions.ConnectionString, executionOptions.EntityPath ); break; case "sb": loadGeneratee = new SBLoadGeneratorClass( executionOptions.ConnectionString, executionOptions.EntityPath ); break; } func = () => { return(loadGeneratee.GeneratePayload(executionOptions.GenerateJson, executionOptions.MessageSize)); }; Console.WriteLine(HelperRoutines.GetExecutionSummary(executionOptions, loadGeneratee, func)); loadOrchestrator = new OrchestratorClass( loadGeneratee, executionOptions.TargetThroughput, executionOptions.MessagesToSend, executionOptions.BatchSize, executionOptions.DryRun, func); loadOrchestrator.Start(); if (executionOptions.Checkpoint > 0) { telemetryTimer.Elapsed += (sender, e) => { Console.WriteLine(loadOrchestrator.GetStatusSnapshot()); }; telemetryTimer.Start(); } do { if (DateTime.Now >= terminationDT) { loadOrchestrator.Stop(); String dt = DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff"); Console.WriteLine($"[{dt}], terminating after {executionOptions.TerminateAfter} seconds..."); break; } if (loadOrchestrator.isJobDone) { String dt = DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff"); Console.WriteLine($"[{dt}] Exiting..."); break; } if (!isConsoleRedirected && Console.KeyAvailable) { var ch = Console.ReadKey(true).Key; String dt = DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff"); switch (ch) { case ConsoleKey.Escape: Console.WriteLine($"[{dt}] Exiting..."); loadOrchestrator.Stop(); break; case ConsoleKey.Q: executionOptions.TargetThroughput = executionOptions.TargetThroughput + 10; Console.WriteLine($"[{dt}] New target throughput: {executionOptions.TargetThroughput} msg/sec"); loadOrchestrator.Stop(); func = () => { return(loadGeneratee.GeneratePayload(executionOptions.GenerateJson, executionOptions.MessageSize)); }; loadOrchestrator = new OrchestratorClass( loadGeneratee, executionOptions.TargetThroughput, executionOptions.MessagesToSend, executionOptions.BatchSize, executionOptions.DryRun, func); loadOrchestrator.Start(); break; case ConsoleKey.A: executionOptions.TargetThroughput = executionOptions.TargetThroughput >= 10 ? executionOptions.TargetThroughput - 10 : 0; Console.WriteLine($"[{dt}] New target throughput: {executionOptions.TargetThroughput} msg/sec"); loadOrchestrator.Stop(); func = () => { return(loadGeneratee.GeneratePayload(executionOptions.GenerateJson, executionOptions.MessageSize)); }; loadOrchestrator = new OrchestratorClass( loadGeneratee, executionOptions.TargetThroughput, executionOptions.MessagesToSend, executionOptions.BatchSize, executionOptions.DryRun, func); loadOrchestrator.Start(); break; case ConsoleKey.W: executionOptions.BatchSize = executionOptions.BatchSize + 10; Console.WriteLine($"[{dt}] New batch size: {executionOptions.BatchSize}"); loadOrchestrator.Stop(); func = () => { return(loadGeneratee.GeneratePayload(executionOptions.GenerateJson, executionOptions.MessageSize)); }; loadOrchestrator = new OrchestratorClass( loadGeneratee, executionOptions.TargetThroughput, executionOptions.MessagesToSend, executionOptions.BatchSize, executionOptions.DryRun, func); loadOrchestrator.Start(); break; case ConsoleKey.S: executionOptions.BatchSize = executionOptions.BatchSize > 10 ? executionOptions.BatchSize - 10 : 1; Console.WriteLine($"[{dt}] New batch size: {executionOptions.BatchSize}"); loadOrchestrator.Stop(); func = () => { return(loadGeneratee.GeneratePayload(executionOptions.GenerateJson, executionOptions.MessageSize)); }; loadOrchestrator = new OrchestratorClass( loadGeneratee, executionOptions.TargetThroughput, executionOptions.MessagesToSend, executionOptions.BatchSize, executionOptions.DryRun, func); loadOrchestrator.Start(); break; } } // Thread.Sleep(300); // sit and relax } while (true); } catch (Exception e) { // Exceptions from all subroutines will bubble up to here exitCode = -1; Console.WriteLine(); Console.WriteLine($"Exception: {e.Message}"); } finally { if (telemetryTimer.Enabled) { telemetryTimer.Stop(); } Console.WriteLine(); Console.WriteLine($"Execution completed, exit code {exitCode}"); } return(exitCode); }