< Summary - ZhEaIsNsAaBn.Libraries coverage (affected: 23 packages)

Information
Class: ZhEaIsNsAaBn.Utilities.APIExceptionHandlers.BaseExceptionHandler<T>
Assembly: ZhEaIsNsAaBn.Utilities.APIExceptionHandlers
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/UtilitiesPackages/ZhEaIsNsAaBn.Utilities.APIExceptionHandlers/GlobalHandlers/BaseExceptionHandler.cs
Line coverage
100%
Covered lines: 30
Uncovered lines: 0
Coverable lines: 30
Total lines: 107
Line coverage: 100%
Branch coverage
56%
Covered branches: 9
Total branches: 16
Branch coverage: 56.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)50%44100%
get_Logger()100%11100%
get_Environment()100%11100%
get_Settings()100%11100%
GenerateError(...)100%11100%
GenerateErrors()50%22100%
GetTraceId(...)50%44100%
GetTransId(...)66.66%66100%
Options(...)100%11100%

File(s)

/home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/UtilitiesPackages/ZhEaIsNsAaBn.Utilities.APIExceptionHandlers/GlobalHandlers/BaseExceptionHandler.cs

#LineLine coverage
 1using Microsoft.Extensions.Options;
 2
 3namespace ZhEaIsNsAaBn.Utilities.APIExceptionHandlers;
 4
 5/// <summary>
 6/// Shared logging and JSON writing for the exception handlers. The HTTP status comes from the app's <see cref="APIRespo
 7/// (registered with <c>AddAPIResponses</c>; defaults otherwise), so an exception answers with the same status as the sa
 8/// <see cref="Error"/> returned from an endpoint.
 9/// </summary>
 10/// <typeparam name="T">The handler type (its logger category).</typeparam>
 11public abstract class BaseExceptionHandler< T >
 12    where T : BaseExceptionHandler<T>
 13{
 2614    private static readonly JsonSerializerOptions Compact  = Options( false );
 2615    private static readonly JsonSerializerOptions Indented = Options( true );
 16
 17    private readonly ILogger<T>           _logger;
 18    private readonly IWebHostEnvironment  _environment;
 19    private readonly APIResponsesSettings _settings;
 20
 21
 22    /// <summary>Stores the shared services.</summary>
 23    /// <param name="logger">The handler's logger.</param>
 24    /// <param name="environment">The host environment; JSON is indented in Development.</param>
 25    /// <param name="settings">The status mapping; defaults when <see langword="null"/>.</param>
 26    /// <exception cref="ArgumentNullException"><paramref name="logger"/> or <paramref name="environment"/> is <see lang
 51027    protected BaseExceptionHandler( ILogger<T> logger, IWebHostEnvironment environment, IOptions<APIResponsesSettings>? 
 28    {
 51029        ArgumentNullException.ThrowIfNull( logger );
 51030        ArgumentNullException.ThrowIfNull( environment );
 31
 51032        _logger      = logger;
 51033        _environment = environment;
 51034        _settings    = settings?.Value ?? new APIResponsesSettings();
 51035    }
 36
 37
 38    /// <summary>The handler's logger.</summary>
 8239    protected ILogger<T> Logger => _logger;
 40
 41    /// <summary>The host environment.</summary>
 9042    protected IWebHostEnvironment Environment => _environment;
 43
 44    /// <summary>The status mapping (codes, categories, fallback).</summary>
 8245    protected APIResponsesSettings Settings => _settings;
 46
 47
 48    /// <summary>Answers with <paramref name="error"/>; see <see cref="GenerateErrors"/>.</summary>
 49    /// <param name="httpContext">The request.</param>
 50    /// <param name="error">The error.</param>
 51    /// <param name="cancellationToken">Token to cancel the write.</param>
 52    /// <returns>A task that completes when the body is written.</returns>
 7053    protected ValueTask GenerateError( HttpContext httpContext, Error error, CancellationToken cancellationToken ) => Ge
 54
 55    /// <summary>
 56    /// Sets the HTTP status from the first error (<see cref="APIResponsesSettings.StatusFor"/>) and writes the errors a
 57    /// <see cref="BaseResponse"/> with the same <c>status</c>, the trace id and the transaction id.
 58    /// </summary>
 59    /// <param name="httpContext">The request.</param>
 60    /// <param name="errors">The errors.</param>
 61    /// <param name="cancellationToken">Token to cancel the write.</param>
 62    /// <returns>A task that completes when the body is written.</returns>
 63    protected async ValueTask GenerateErrors( HttpContext httpContext, List<Error> errors, CancellationToken cancellatio
 64    {
 8265        ArgumentNullException.ThrowIfNull( httpContext );
 8266        ArgumentNullException.ThrowIfNull( errors );
 67
 8268        var status = (int) Settings.StatusFor( errors );
 69
 8270        BaseResponse response = errors;
 8271        response.Status = status;
 8272        response.TraceId = GetTraceId( httpContext );
 8273        response.TransId = GetTransId( httpContext );
 74
 75
 8276        httpContext.Response.StatusCode  = status;
 8277        httpContext.Response.ContentType = "application/json";
 78
 79
 8280        var json = JsonSerializer.Serialize( response, Environment.IsDevelopment() ? Indented : Compact );
 8281        await httpContext.Response.WriteAsync( json, cancellationToken ).ConfigureAwait( false );
 8282    }
 83
 84    /// <summary>The trace id of the current activity, else the request's <see cref="HttpContext.TraceIdentifier"/>.</su
 85    /// <param name="httpContext">The request.</param>
 86    /// <returns>The trace id.</returns>
 87    protected static string GetTraceId( HttpContext httpContext )
 88    {
 8289        ArgumentNullException.ThrowIfNull( httpContext );
 90
 8291        return System.Diagnostics.Activity.Current?.TraceId.ToString() ?? httpContext.TraceIdentifier;
 92    }
 93
 94    /// <summary>The transaction id: <c>HttpContext.Items["transId"]</c> (as <c>ToAPI</c> uses), else the <c>TransId</c>
 95    /// <param name="httpContext">The request.</param>
 96    /// <returns>The transaction id.</returns>
 97    protected static string GetTransId( HttpContext httpContext )
 98    {
 8299        ArgumentNullException.ThrowIfNull( httpContext );
 100
 82101        return httpContext.Items[ "transId" ]?.ToString() ?? httpContext.Request.Headers[ "TransId" ].FirstOrDefault() ?
 102    }
 103
 104
 105    private static JsonSerializerOptions Options( bool indented )
 52106        => new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenW
 107}