diff --git a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Scenarios/DemoScenario.cs b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Scenarios/DemoScenario.cs index 3d34fd2994..55a3de0a9a 100644 --- a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Scenarios/DemoScenario.cs +++ b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/Scenarios/DemoScenario.cs @@ -7,8 +7,8 @@ namespace Volo.ClientSimulation.Demo.Scenarios { public DemoScenario() { - AddStep(new SleepScenarioStep(RandomHelper.GetRandom(1000, 5000))); - AddStep(new SleepScenarioStep(RandomHelper.GetRandom(2000, 6000))); + AddStep(new SleepScenarioStep("Wait1", RandomHelper.GetRandom(1000, 5000))); + AddStep(new SleepScenarioStep("Wait2", RandomHelper.GetRandom(2000, 6000))); } } } \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml b/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml index c63baf4af5..46e27b6eb3 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml +++ b/modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml @@ -18,6 +18,9 @@ + + Clients + @foreach (var client in Model.Snapshot.Clients) { @@ -40,12 +43,39 @@ @client.Scenario.DisplayText - @if (client.State != ClientState.Stopped) - { - | @client.Scenario.CurrentStep.DisplayText - } + @if (client.State != ClientState.Stopped) + { + | @client.Scenario.CurrentStep.DisplayText + } } + + + + Scenarios + + + + @foreach (var scenario in Model.Snapshot.Scenarios) + { + + + + @scenario.DisplayText + + + +@foreach (var step in scenario.Steps) +{ + @step.DisplayText: E: @step.ExecutionCount | S: @step.SuccessCount | A: @step.AvgExecutionDuration.ToString("0.00") ms. @Environment.NewLine +} + + + + + } + + \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/Scenario.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/Scenario.cs index b75542557f..752cafbe26 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/Scenario.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/Scenario.cs @@ -51,6 +51,10 @@ namespace Volo.ClientSimulation.Scenarios public void Reset() { CurrentStepIndex = 0; + foreach (var step in Steps) + { + step.Reset(); + } } public ScenarioSnapshot CreateSnapshot() diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioStep.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioStep.cs index 53df153fc5..8e150895f1 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioStep.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioStep.cs @@ -7,6 +7,14 @@ namespace Volo.ClientSimulation.Scenarios { public abstract class ScenarioStep { + protected int ExecutionCount; + protected int SuccessCount; + protected int FailCount; + protected double TotalExecutionDuration; + protected double MinExecutionDuration; + protected double MaxExecutionDuration; + protected double LastExecutionDuration; + public async Task RunAsync() { await BeforeExecuteAsync(); @@ -16,14 +24,32 @@ namespace Volo.ClientSimulation.Scenarios try { await ExecuteAsync(); + SuccessCount++; } catch { - + //TODO: Log! + FailCount++; } finally { stopwatch.Stop(); + + ExecutionCount++; + + LastExecutionDuration = stopwatch.Elapsed.TotalMilliseconds; + + TotalExecutionDuration += LastExecutionDuration; + + if (MinExecutionDuration > LastExecutionDuration) + { + MinExecutionDuration = LastExecutionDuration; + } + + if (MaxExecutionDuration < LastExecutionDuration) + { + MaxExecutionDuration = LastExecutionDuration; + } } await AfterExecuteAsync(); @@ -52,8 +78,29 @@ namespace Volo.ClientSimulation.Scenarios { return new ScenarioStepSnapshot { - DisplayText = GetDisplayText() + DisplayText = GetDisplayText(), + ExecutionCount = ExecutionCount, + LastExecutionDuration = LastExecutionDuration, + MaxExecutionDuration = MaxExecutionDuration, + MinExecutionDuration = MinExecutionDuration, + TotalExecutionDuration = TotalExecutionDuration, + AvgExecutionDuration = ExecutionCount == 0 + ? 0.0 + : TotalExecutionDuration / ExecutionCount, + FailCount = FailCount, + SuccessCount = SuccessCount }; } + + public virtual void Reset() + { + ExecutionCount = 0; + FailCount = 0; + SuccessCount = 0; + TotalExecutionDuration = 0; + MinExecutionDuration = 0.0; + MaxExecutionDuration = 0.0; + LastExecutionDuration = 0.0; + } } } \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/SleepScenarioStep.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/SleepScenarioStep.cs index 0aa5b1d526..42c350b26b 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/SleepScenarioStep.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/SleepScenarioStep.cs @@ -4,10 +4,13 @@ namespace Volo.ClientSimulation.Scenarios { public class SleepScenarioStep : ScenarioStep { + public string Name { get; } + public int Duration { get; } - public SleepScenarioStep(int duration = 1000) + public SleepScenarioStep(string name, int duration = 1000) { + Name = name; Duration = duration; } @@ -18,7 +21,7 @@ namespace Volo.ClientSimulation.Scenarios public override string GetDisplayText() { - return base.GetDisplayText() + $" ({Duration})"; + return base.GetDisplayText() + $" ({Name})"; } } } \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Simulation.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Simulation.cs index 3684965bbc..bfa464d8d1 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Simulation.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Simulation.cs @@ -105,9 +105,11 @@ namespace Volo.ClientSimulation public virtual SimulationSnapshot CreateSnapshot() { + SimulationSnapshot snapshot; + lock (SyncObj) { - return new SimulationSnapshot + snapshot = new SimulationSnapshot { State = State, Clients = Clients @@ -115,6 +117,10 @@ namespace Volo.ClientSimulation .ToList() }; } + + snapshot.CreateSummaries(); + + return snapshot; } public virtual void Dispose() diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSnapshot.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSnapshot.cs index 3e4363eda1..c8dcbcde3a 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSnapshot.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSnapshot.cs @@ -6,5 +6,21 @@ namespace Volo.ClientSimulation.Snapshot public class ScenarioStepSnapshot { public string DisplayText { get; set; } + + public int ExecutionCount { get; set; } + + public int SuccessCount { get; set; } + + public int FailCount { get; set; } + + public double AvgExecutionDuration { get; set; } + + public double TotalExecutionDuration { get; set; } + + public double MinExecutionDuration { get; set; } + + public double MaxExecutionDuration { get; set; } + + public double LastExecutionDuration { get; set; } } } \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSummarySnapshot.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSummarySnapshot.cs new file mode 100644 index 0000000000..e80dbdf982 --- /dev/null +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSummarySnapshot.cs @@ -0,0 +1,24 @@ +using System; + +namespace Volo.ClientSimulation.Snapshot +{ + [Serializable] + public class ScenarioStepSummarySnapshot + { + public string DisplayText { get; set; } + + public int ExecutionCount { get; set; } + + public int SuccessCount { get; set; } + + public int FailCount { get; set; } + + public double AvgExecutionDuration { get; set; } + + public double TotalExecutionDuration { get; set; } + + public double MinExecutionDuration { get; set; } + + public double MaxExecutionDuration { get; set; } + } +} \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioSummarySnapshot.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioSummarySnapshot.cs new file mode 100644 index 0000000000..402d936fc5 --- /dev/null +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioSummarySnapshot.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Volo.ClientSimulation.Snapshot +{ + [Serializable] + public class ScenarioSummarySnapshot + { + public string DisplayText { get; set; } + + public List Steps { get; set; } + } +} \ No newline at end of file diff --git a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/SimulationSnapshot.cs b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/SimulationSnapshot.cs index 0fe835e0aa..6e03ae231e 100644 --- a/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/SimulationSnapshot.cs +++ b/modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/SimulationSnapshot.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Volo.ClientSimulation.Snapshot { @@ -9,5 +10,59 @@ namespace Volo.ClientSimulation.Snapshot public SimulationState State { get; set; } public List Clients { get; set; } + + public List Scenarios { get; set; } + + public void CreateSummaries() + { + var scenarioDictionary = new Dictionary(); + + foreach (var client in Clients) + { + var scenarioSummary = scenarioDictionary.GetOrAdd( + client.Scenario.DisplayText, + () => new ScenarioSummarySnapshot + { + DisplayText = client.Scenario.DisplayText, + Steps = new List() + } + ); + + foreach (var scenarioStep in client.Scenario.Steps) + { + var scenarioStepSummary = scenarioSummary.Steps.FirstOrDefault(s => s.DisplayText == scenarioStep.DisplayText); + if (scenarioStepSummary == null) + { + scenarioStepSummary = new ScenarioStepSummarySnapshot + { + DisplayText = scenarioStep.DisplayText + }; + + scenarioSummary.Steps.Add(scenarioStepSummary); + } + + scenarioStepSummary.ExecutionCount += scenarioStep.ExecutionCount; + scenarioStepSummary.SuccessCount += scenarioStep.SuccessCount; + scenarioStepSummary.FailCount += scenarioStep.FailCount; + scenarioStepSummary.TotalExecutionDuration += scenarioStep.TotalExecutionDuration; + + if (scenarioStepSummary.MinExecutionDuration > scenarioStep.MinExecutionDuration) + { + scenarioStepSummary.MinExecutionDuration = scenarioStep.MinExecutionDuration; + } + + if (scenarioStepSummary.MaxExecutionDuration < scenarioStep.MaxExecutionDuration) + { + scenarioStepSummary.MaxExecutionDuration = scenarioStep.MaxExecutionDuration; + } + + scenarioStepSummary.AvgExecutionDuration = scenarioStepSummary.ExecutionCount == 0 + ? 0.0 + : scenarioStepSummary.TotalExecutionDuration / scenarioStepSummary.ExecutionCount; + } + } + + Scenarios = scenarioDictionary.Values.ToList(); + } } }
+@foreach (var step in scenario.Steps) +{ + @step.DisplayText: E: @step.ExecutionCount | S: @step.SuccessCount | A: @step.AvgExecutionDuration.ToString("0.00") ms. @Environment.NewLine +} +