Skip to content
This repository has been archived by the owner on Jul 18, 2024. It is now read-only.

Commit

Permalink
Add process statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed Jun 27, 2024
1 parent d98cff2 commit 51edc29
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 18 deletions.
15 changes: 10 additions & 5 deletions CSharpInteractive.Tests/ProcessMonitorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class ProcessMonitorTests
{
private readonly Mock<ILog<ProcessMonitor>> _log = new();
private readonly Mock<IEnvironment> _environment = new();
private readonly Mock<IStatistics> _statistics = new();
private readonly Mock<IStartInfo> _startInfo = new();

public ProcessMonitorTests()
Expand Down Expand Up @@ -70,7 +71,8 @@ internal void ShouldCreateResultWhenFinishedWithSuccess(ProcessState state, stri
var result = monitor.Finished(_startInfo.Object, 22, state, 33);

// Then
result.Description.ShouldBe([new Text("99 \"Abc xyz\" process ", color), new Text(stateDescription, color), new Text(" (in 22 ms)"), new Text(" with exit code 33"), new Text(".")]);
result.Description.ShouldBe([new Text("99 \"Abc xyz\" process ", color), new Text(stateDescription, Color.Success), new Text(" (in 22 ms)"), new Text(" with exit code 33"), new Text(".")]);
_statistics.Verify(i => i.RegisterProcessResult(result));
}

[Fact]
Expand All @@ -85,7 +87,8 @@ public void ShouldCreateResultWhenFailed()
var result = monitor.Finished(_startInfo.Object, 22, ProcessState.Failed, 33);

// Then
result.Description.ShouldBe([new Text("99 \"Abc xyz\" process ", Color.Highlighted), new Text("failed", Color.Highlighted), new Text(" (in 22 ms)"), new Text(" with exit code 33"), new Text(".")]);
result.Description.ShouldBe([new Text("99 \"Abc xyz\" process ", Color.Highlighted), new Text("failed", Color.Error), new Text(" (in 22 ms)"), new Text(" with exit code 33"), new Text(".")]);
_statistics.Verify(i => i.RegisterProcessResult(result));
}

[Fact]
Expand All @@ -99,7 +102,8 @@ public void ShouldCreateResultWhenFailedToStart()
var result = monitor.Finished(_startInfo.Object, 22, ProcessState.Failed);

// Then
result.Description.ShouldBe([new Text("\"Abc xyz\" process ", Color.Highlighted), new Text("failed to start", Color.Highlighted), new Text(" (in 22 ms)"), new Text(".")]);
result.Description.ShouldBe([new Text("\"Abc xyz\" process ", Color.Highlighted), new Text("failed to start", Color.Error), new Text(" (in 22 ms)"), new Text(".")]);
_statistics.Verify(i => i.RegisterProcessResult(result));
}

[Fact]
Expand All @@ -114,9 +118,10 @@ public void ShouldCreateResultWhenCanceled()
var result = monitor.Finished(_startInfo.Object, 22, ProcessState.Canceled);

// Then
result.Description.ShouldBe([new Text("99 \"Abc xyz\" process ", Color.Highlighted), new Text("canceled", Color.Highlighted), new Text(" (in 22 ms)"), new Text(".")]);
result.Description.ShouldBe([new Text("99 \"Abc xyz\" process ", Color.Highlighted), new Text("canceled", Color.Warning), new Text(" (in 22 ms)"), new Text(".")]);
_statistics.Verify(i => i.RegisterProcessResult(result));
}

private ProcessMonitor CreateInstance() =>
new(_log.Object, _environment.Object);
new(_log.Object, _environment.Object, _statistics.Object);
}
4 changes: 4 additions & 0 deletions CSharpInteractive/IStatistics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ internal interface IStatistics
IReadOnlyCollection<string> Errors { get; }

IReadOnlyCollection<string> Warnings { get; }

IReadOnlyCollection<ProcessResult> ProcessResults { get; }

TimeSpan TimeElapsed { get; }

Expand All @@ -13,4 +15,6 @@ internal interface IStatistics
void RegisterError(string error);

void RegisterWarning(string warning);

void RegisterProcessResult(ProcessResult result);
}
40 changes: 30 additions & 10 deletions CSharpInteractive/ProcessMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace CSharpInteractive;

internal class ProcessMonitor(
ILog<ProcessMonitor> log,
IEnvironment environment) : IProcessMonitor
IEnvironment environment,
IStatistics statistics) : IProcessMonitor
{
private int? _processId;

Expand Down Expand Up @@ -38,27 +39,46 @@ public void Started(IStartInfo startInfo, int processId)
}
}

public ProcessResult Finished(IStartInfo startInfo, long elapsedMilliseconds, ProcessState state, int? exitCode = default, Exception? error = default) =>
new(
public ProcessResult Finished(IStartInfo startInfo, long elapsedMilliseconds, ProcessState state, int? exitCode = default, Exception? error = default)
{
var result = new ProcessResult(
startInfo,
state,
elapsedMilliseconds,
GetFooter(startInfo,exitCode, elapsedMilliseconds, state).ToArray(),
GetFooter(startInfo, exitCode, elapsedMilliseconds, state).ToArray(),
exitCode,
error);

statistics.RegisterProcessResult(result);
return result;
}

private IEnumerable<Text> GetFooter(IStartInfo startInfo, int? exitCode, long elapsedMilliseconds, ProcessState? state)
{
// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
var stateText = state switch
string? stateText;
Color stateColor;
// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
switch (state)
{
ProcessState.Failed => exitCode.HasValue ? "failed" : "failed to start",
ProcessState.Canceled => "canceled",
_ => "finished"
};
case ProcessState.Failed:
stateText = exitCode.HasValue ? "failed" : "failed to start";
stateColor = Color.Error;
break;

case ProcessState.Canceled:
stateText = "canceled";
stateColor = Color.Warning;
break;

default:
stateText = "finished";
stateColor = Color.Success;
break;
}

yield return new Text($"{startInfo.GetDescription(_processId)} process ", Color.Highlighted);
yield return new Text(stateText, Color.Highlighted);
yield return new Text(stateText, stateColor);
yield return new Text($" (in {elapsedMilliseconds} ms)");
if (exitCode.HasValue)
{
Expand Down
20 changes: 20 additions & 0 deletions CSharpInteractive/Statistics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal class Statistics : IStatistics
private readonly Stopwatch _stopwatch = new();
private readonly List<string> _errors = [];
private readonly List<string> _warnings = [];
private readonly List<ProcessResult> _processResult = [];

public IReadOnlyCollection<string> Errors
{
Expand All @@ -33,6 +34,17 @@ public IReadOnlyCollection<string> Warnings
}
}

public IReadOnlyCollection<ProcessResult> ProcessResults
{
get
{
lock (_processResult)
{
return new ReadOnlyCollection<ProcessResult>(_processResult);
}
}
}

public TimeSpan TimeElapsed => _stopwatch.Elapsed;

public IDisposable Start()
Expand Down Expand Up @@ -64,4 +76,12 @@ public void RegisterWarning(string warning)
}
}
}

public void RegisterProcessResult(ProcessResult result)
{
lock (_processResult)
{
_processResult.Add(result);
}
}
}
14 changes: 11 additions & 3 deletions CSharpInteractive/StatisticsPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ internal class StatisticsPresenter(ILog<StatisticsPresenter> log) : IPresenter<I
{
public void Show(IStatistics statistics)
{
foreach (var error in statistics.Errors)
log.Info();
log.Info(new Text("Summary:", Color.Header));

foreach (var processResult in statistics.ProcessResults)
{
log.Info(Text.Tab, new Text(error, Color.Error));
log.Info(Text.Tab + processResult.Description);
}

foreach (var warning in statistics.Warnings)
{
log.Info(Text.Tab, new Text(warning, Color.Warning));
}

foreach (var error in statistics.Errors)
{
log.Info(Text.Tab, new Text(error, Color.Error));
}

if (statistics.Warnings.Count > 0)
{
Expand Down
16 changes: 16 additions & 0 deletions CSharpInteractive/Text.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ public override string ToString()

return sb.ToString();
}

public static Text[] operator +(Text text1, Text text2)
{
var newText = new Text[2];
newText[0] = text1;
newText[1] = text2;
return newText;
}

public static Text[] operator +(Text[] text, Text text2)
{
Expand All @@ -49,4 +57,12 @@ public override string ToString()
Array.Copy(text, 0, newText, 1, text.Length);
return newText;
}

public static Text[] Join(Text[] text1, Text[] text2)
{
var newText = new Text[text1.Length + text2.Length];
Array.Copy(text1, 0, newText, 0, text1.Length);
Array.Copy(text2, 0, newText, text1.Length, text2.Length);
return newText;
}
}

0 comments on commit 51edc29

Please sign in to comment.