using System; using System.Diagnostics; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Interceptors; namespace FrostFS.SDK.Client; [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "parameters are provided by GRPC infrastructure")] public class MetricsInterceptor(Action callback) : Interceptor { public override AsyncUnaryCall AsyncUnaryCall( TRequest request, ClientInterceptorContext context, AsyncUnaryCallContinuation continuation) { var call = continuation(request, context); return new AsyncUnaryCall( HandleUnaryResponse(call), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); } public override AsyncClientStreamingCall AsyncClientStreamingCall( ClientInterceptorContext context, AsyncClientStreamingCallContinuation continuation) { var call = continuation(context); return new AsyncClientStreamingCall( call.RequestStream, HandleStreamResponse(call), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); } private async Task HandleUnaryResponse(AsyncUnaryCall call) { var watch = new Stopwatch(); watch.Start(); var response = await call; watch.Stop(); var elapsed = watch.ElapsedTicks * 1_000_000 / Stopwatch.Frequency; callback(new CallStatistics { MethodName = call.ToString(), ElapsedMicroSeconds = elapsed }); return response; } private async Task HandleStreamResponse(AsyncClientStreamingCall call) { var watch = new Stopwatch(); watch.Start(); var response = await call; watch.Stop(); var elapsed = watch.ElapsedTicks * 1_000_000 / Stopwatch.Frequency; callback(new CallStatistics { MethodName = call.ToString(), ElapsedMicroSeconds = elapsed }); return response; } }