More sophisticated exception handling.
MODIFY
WalletWasabi/Bases/PeriodicRunner.cs
WalletWasabi/Bases/PeriodicRunner.cs
@@ -21,6 +21,8 @@ namespace WalletWasabi.Bases
public TimeSpan Period { get; }
private Task ForeverTask { get; set; }
public Exception LastException { get; set; }
+ public long LastExceptionCount { get; set; }
+ public DateTimeOffset LastExceptionFirstAppeared { get; set; }
protected PeriodicRunner(TimeSpan period, T defaultResult)
{
@@ -28,7 +30,14 @@ namespace WalletWasabi.Bases
Period = period;
ForeverTask = Task.CompletedTask;
Status = defaultResult;
+ ResetLastException();
+ }
+
+ private void ResetLastException()
+ {
LastException = null;
+ LastExceptionCount = 0;
+ LastExceptionFirstAppeared = DateTimeOffset.MinValue;
}
public abstract Task<T> ActionAsync(CancellationToken cancel);
@@ -45,6 +54,7 @@ namespace WalletWasabi.Bases
try
{
Status = await ActionAsync(Stop.Token).ConfigureAwait(false);
+ LogAndResetLastExceptionIfNotNull();
}
catch (Exception ex) when (ex is OperationCanceledException || ex is TaskCanceledException || ex is TimeoutException)
{
@@ -53,10 +63,22 @@ namespace WalletWasabi.Bases
catch (Exception ex)
{
// Only log one type of exception once.
- if (LastException is null || ex.GetType() != LastException.GetType() || ex.Message != LastException.Message)
+ if (LastException is null // If the exception never came.
+ || ex.GetType() != LastException.GetType() // Or the exception have different type from previous exception.
+ || ex.Message != LastException.Message) // Or the exception have different message from previous exception.
{
- Logger.LogError(ex);
+ // Then log and reset the last exception if another one came before.
+ LogAndResetLastExceptionIfNotNull();
+ // Set new exception and log it.
LastException = ex;
+ LastExceptionFirstAppeared = DateTimeOffset.UtcNow;
+ LastExceptionCount = 1;
+ Logger.LogError(ex);
+ }
+ else
+ {
+ // Increment the exception counter.
+ LastExceptionCount++;
}
}
finally
@@ -73,6 +95,15 @@ namespace WalletWasabi.Bases
}
}
+ private void LogAndResetLastExceptionIfNotNull()
+ {
+ if (LastException != null)
+ {
+ Logger.LogInfo($"Exception stopped coming. It came for {(DateTimeOffset.UtcNow - LastExceptionFirstAppeared).TotalSeconds} seconds, {LastExceptionCount} times: {LastException.ToTypeMessageString()}");
+ ResetLastException();
+ }
+ }
+
public async Task StopAsync()
{
Stop?.Cancel();

MODIFY
WalletWasabi/Extensions/ExceptionExtensions.cs
WalletWasabi/Extensions/ExceptionExtensions.cs
@@ -12,7 +12,7 @@ namespace System
{
var trimmed = Guard.Correct(ex.Message);
- if (trimmed == "")
+ if (trimmed.Length == 0)
{
if (ex is HwiException hwiEx)
{
@@ -40,7 +40,7 @@ namespace System
public static string ToUserFriendlyString(this HttpRequestException ex)
{
var trimmed = Guard.Correct(ex.Message);
- if (trimmed == "")
+ if (trimmed.Length == 0)
{
return ex.ToTypeMessageString();
}

More sophisticated exception handling.