All checks were successful
DCO / DCO (pull_request) Successful in 47s
Signed-off-by: Pavel Gross <p.gross@yadro.com>
163 lines
No EOL
4.7 KiB
C#
163 lines
No EOL
4.7 KiB
C#
using System;
|
|
using System.Threading;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace FrostFS.SDK.ClientV2;
|
|
|
|
// clientStatusMonitor count error rate and other statistics for connection.
|
|
public class ClientStatusMonitor : IClientStatus
|
|
{
|
|
private static readonly MethodIndex[] MethodIndexes =
|
|
[
|
|
MethodIndex.methodBalanceGet,
|
|
MethodIndex.methodContainerPut,
|
|
MethodIndex.methodContainerGet,
|
|
MethodIndex.methodContainerList,
|
|
MethodIndex.methodContainerDelete,
|
|
MethodIndex.methodEndpointInfo,
|
|
MethodIndex.methodNetworkInfo,
|
|
MethodIndex.methodNetMapSnapshot,
|
|
MethodIndex.methodObjectPut,
|
|
MethodIndex.methodObjectDelete,
|
|
MethodIndex.methodObjectGet,
|
|
MethodIndex.methodObjectHead,
|
|
MethodIndex.methodObjectRange,
|
|
MethodIndex.methodObjectPatch,
|
|
MethodIndex.methodSessionCreate,
|
|
MethodIndex.methodAPEManagerAddChain,
|
|
MethodIndex.methodAPEManagerRemoveChain,
|
|
MethodIndex.methodAPEManagerListChains
|
|
];
|
|
|
|
public static string GetMethodName(MethodIndex index)
|
|
{
|
|
return index switch
|
|
{
|
|
MethodIndex.methodBalanceGet => "BalanceGet",
|
|
MethodIndex.methodContainerPut => "ContainerPut",
|
|
MethodIndex.methodContainerGet => "ContainerGet",
|
|
MethodIndex.methodContainerList => "ContainerList",
|
|
MethodIndex.methodContainerDelete => "ContainerDelete",
|
|
MethodIndex.methodEndpointInfo => "EndpointInfo",
|
|
MethodIndex.methodNetworkInfo => "NetworkInfo",
|
|
MethodIndex.methodNetMapSnapshot => "NetMapSnapshot",
|
|
MethodIndex.methodObjectPut => "ObjectPut",
|
|
MethodIndex.methodObjectDelete => "ObjectDelete",
|
|
MethodIndex.methodObjectGet => "ObjectGet",
|
|
MethodIndex.methodObjectHead => "ObjectHead",
|
|
MethodIndex.methodObjectRange => "ObjectRange",
|
|
MethodIndex.methodObjectPatch => "ObjectPatch",
|
|
MethodIndex.methodSessionCreate => "SessionCreate",
|
|
MethodIndex.methodAPEManagerAddChain => "APEManagerAddChain",
|
|
MethodIndex.methodAPEManagerRemoveChain => "APEManagerRemoveChain",
|
|
MethodIndex.methodAPEManagerListChains => "APEManagerListChains",
|
|
_ => throw new ArgumentException("Unknown method", nameof(index)),
|
|
};
|
|
}
|
|
|
|
private readonly object _lock = new();
|
|
|
|
private readonly ILogger? logger;
|
|
private int healthy;
|
|
|
|
public ClientStatusMonitor(ILogger? logger, string address)
|
|
{
|
|
this.logger = logger;
|
|
healthy = (int)HealthyStatus.Healthy;
|
|
|
|
Address = address;
|
|
Methods = new MethodStatus[MethodIndexes.Length];
|
|
|
|
for (int i = 0; i < MethodIndexes.Length; i++)
|
|
{
|
|
Methods[i] = new MethodStatus(GetMethodName(MethodIndexes[i]));
|
|
}
|
|
}
|
|
|
|
public string Address { get; }
|
|
|
|
internal uint ErrorThreshold { get; set; }
|
|
|
|
public uint CurrentErrorCount { get; set; }
|
|
|
|
public ulong OverallErrorCount { get; set; }
|
|
|
|
public MethodStatus[] Methods { get; private set; }
|
|
|
|
public bool IsHealthy()
|
|
{
|
|
var res = Interlocked.CompareExchange(ref healthy, -1, -1) == (int)HealthyStatus.Healthy;
|
|
return res;
|
|
}
|
|
|
|
public bool IsDialed()
|
|
{
|
|
return Interlocked.CompareExchange(ref healthy, -1, -1) != (int)HealthyStatus.UnhealthyOnDial;
|
|
}
|
|
|
|
public void SetHealthy()
|
|
{
|
|
Interlocked.Exchange(ref healthy, (int)HealthyStatus.Healthy);
|
|
}
|
|
public void SetUnhealthy()
|
|
{
|
|
Interlocked.Exchange(ref healthy, (int)HealthyStatus.UnhealthyOnRequest);
|
|
}
|
|
|
|
public void SetUnhealthyOnDial()
|
|
{
|
|
Interlocked.Exchange(ref healthy, (int)HealthyStatus.UnhealthyOnDial);
|
|
}
|
|
|
|
public void IncErrorRate()
|
|
{
|
|
bool thresholdReached;
|
|
lock (_lock)
|
|
{
|
|
CurrentErrorCount++;
|
|
OverallErrorCount++;
|
|
|
|
thresholdReached = CurrentErrorCount >= ErrorThreshold;
|
|
|
|
if (thresholdReached)
|
|
{
|
|
SetUnhealthy();
|
|
CurrentErrorCount = 0;
|
|
}
|
|
}
|
|
|
|
if (thresholdReached && logger != null)
|
|
{
|
|
FrostFsMessages.ErrorЕhresholdReached(logger, Address, ErrorThreshold);
|
|
}
|
|
}
|
|
|
|
public uint GetCurrentErrorRate()
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return CurrentErrorCount;
|
|
}
|
|
}
|
|
|
|
public ulong GetOverallErrorRate()
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return OverallErrorCount;
|
|
}
|
|
}
|
|
|
|
public StatusSnapshot[] MethodsStatus()
|
|
{
|
|
var result = new StatusSnapshot[Methods.Length];
|
|
|
|
for (int i = 0; i < result.Length; i++)
|
|
{
|
|
result[i] = Methods[i].Snapshot!;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
} |