public static Func <TRequest, Task <TResponse> > WithAlteredPipeline <TRequest, TResponse>(this Func <TRequest, Task <TResponse> > operation, [CallerMemberName] string name = null, Func <PolicyBuilder <TResponse>, string, AsyncPolicy <TResponse> > retryPolicy = null, Action <TRequest> requestLog = null, Action <TResponse> responseLog = null) where TRequest : IAlteredRequest where TResponse : IAlteredResponse, new() => operation //.WithXRaySegment(name) .WithUnhandledException(name) .WithRetry(name, retryPolicy) .WithCopyRequestId() .WithLogRequest(requestLog ?? (request => { AlteredLog.Information(new { Name = name, request.RequestId, Request = request }); })) .WithCreateRequestId() .WithMeasureRequestDuration() .WithLogResponse(responseLog ?? (response => { AlteredLog.Information(new { Name = name, response.RequestId, Response = response }); }));
public static AsyncPolicy <T> AlteredRetryPolicy <T>(this PolicyBuilder <T> p, string name) where T : IAlteredResponse => Policy.WrapAsync( p.WaitAndRetryAsync( DecorrelatedJitter(MaxRetries, MinDelay, MaxDelay), (response, timeSpan, numRetries, context) => { AlteredLog.Warning(new { Name = name, response.Result.RequestId, Response = new { StatusCode = (int)RetryStatusCode, response.Result.RequestDuration, RetryAfter = timeSpan.TotalMilliseconds, NumRetries = numRetries, Context = context.ToDictionary() // response.Exception? already logged } }); }), p.CircuitBreakerAsync(MaxCircuitFails, CircuitBreakDuration, (response, state, timeSpan, context) => { AlteredLog.Error(new { Name = name, response.Result.RequestId, Response = new { StatusCode = (int)CircuitBreakStatusCode, response.Result.RequestDuration, RetryAfter = timeSpan.TotalMilliseconds, CircuitState = state, Context = context.ToDictionary() } }); }, (context) => { AlteredLog.Error(new { Name = name, Response = new { StatusCode = (int)CircuitResetStatusCode, Context = context.ToDictionary() } }); }, () => { // half-open }));
public static IWebHostBuilder UseAlteredConfigure(this IWebHostBuilder builder) => builder .Configure(applicationBuilder => { if (pendingConfigurations.TryRemove(builder, out List <Action <IApplicationBuilder> > configurations)) { foreach (var configuration in configurations) { configuration(applicationBuilder); } AlteredLog.Debug(new { Name = nameof(AlteredConfigureExtensions.UseAlteredConfigure), Properties = applicationBuilder.Properties.Select(kvp => kvp.Key).ToList(), Features = applicationBuilder.ServerFeatures.Select(kvp => kvp.Key.Name).ToList() }); } });
public static Func <TRequest, Task <TResponse> > WithUnhandledException <TRequest, TResponse, TException>(this Func <TRequest, Task <TResponse> > func, string name, Func <TException, StatusCode> getErrorCode = null) where TRequest : IRequestId where TResponse : IStatusCode, new() where TException : Exception => async(request) => { var clock = Stopwatch.StartNew(); try { var response = await func(request); return(response); } catch (TException e) { var errorCode = getErrorCode?.Invoke(e) ?? HttpStatusCode.InternalServerError; var response = new TResponse { StatusCode = errorCode }; AlteredLog.Error(new { Name = name, request.RequestId, Response = new { StatusCode = (int)response.StatusCode, RequestDuration = clock.Elapsed.TotalMilliseconds, Exception = new { //e.StackTrace, StackTrace = new StackTrace(e).ToString(), e.Source, e.Message, Data = e.Data.ToDictionary().ToDictionary(kvp => $"{kvp.Key}", kvp => $"{kvp.Value}") } } }); return(response); } };
static AlteredLog AlteredTime(AlteredLog o) { o.AlteredTime = DateTime.UtcNow; return(o); }