RollingHealthMetrics
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Polly.CircuitBreaker.Health
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal sealed class RollingHealthMetrics : HealthMetrics
{
[System.Runtime.CompilerServices.NullableContext(0)]
private sealed class HealthWindow
{
public int Successes { get; set; }
public int Failures { get; set; }
public DateTimeOffset StartedAt { get; set; }
}
private readonly TimeSpan _samplingDuration;
private readonly TimeSpan _windowDuration;
private readonly Queue<HealthWindow> _windows;
[System.Runtime.CompilerServices.Nullable(2)]
private HealthWindow _currentWindow;
public RollingHealthMetrics(TimeSpan samplingDuration, short numberOfWindows, TimeProvider timeProvider)
: base(timeProvider)
{
_samplingDuration = samplingDuration;
_windowDuration = TimeSpan.FromTicks(_samplingDuration.Ticks / numberOfWindows);
_windows = new Queue<HealthWindow>();
}
public override void IncrementSuccess()
{
UpdateCurrentWindow().Successes++;
}
public override void IncrementFailure()
{
UpdateCurrentWindow().Failures++;
}
public override void Reset()
{
_currentWindow = null;
_windows.Clear();
}
public override HealthInfo GetHealthInfo()
{
UpdateCurrentWindow();
int num = 0;
int num2 = 0;
foreach (HealthWindow window in _windows) {
num += window.Successes;
num2 += window.Failures;
}
return HealthInfo.Create(num, num2);
}
private HealthWindow UpdateCurrentWindow()
{
DateTimeOffset utcNow = base.TimeProvider.GetUtcNow();
if (_currentWindow == null || utcNow - _currentWindow.StartedAt >= _windowDuration) {
_currentWindow = new HealthWindow {
StartedAt = utcNow
};
_windows.Enqueue(_currentWindow);
}
while (utcNow - _windows.Peek().StartedAt >= _samplingDuration) {
_windows.Dequeue();
}
return _currentWindow;
}
}
}