< Summary

Information
Class: IceRpc.Logger.LoggerMiddleware
Assembly: IceRpc.Logger
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Logger/LoggerMiddleware.cs
Tag: 1856_27024993493
Line coverage
100%
Covered lines: 39
Uncovered lines: 0
Coverable lines: 39
Total lines: 111
Line coverage: 100%
Branch coverage
75%
Covered branches: 3
Total branches: 4
Branch coverage: 75%
Method coverage
100%
Covered methods: 3
Fully covered methods: 3
Total methods: 3
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
DispatchAsync(...)50%22100%
PerformDispatchAsync()100%22100%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Logger/LoggerMiddleware.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using IceRpc.Extensions.DependencyInjection;
 4using Microsoft.Extensions.Logging;
 5using System.Net;
 6
 7namespace IceRpc.Logger;
 8
 9/// <summary>A middleware that writes a log entry to an <see cref="ILogger" /> for each dispatch.</summary>
 10/// <seealso cref="LoggerRouterExtensions"/>
 11/// <seealso cref="LoggerDispatcherBuilderExtensions"/>
 12public class LoggerMiddleware : IDispatcher
 13{
 14    private readonly IDispatcher _next;
 15    private readonly ILogger _logger;
 16
 17    /// <summary>Constructs a logger middleware.</summary>
 18    /// <param name="next">The next dispatcher in the dispatch pipeline.</param>
 19    /// <param name="logger">The logger to log to.</param>
 320    public LoggerMiddleware(IDispatcher next, ILogger logger)
 321    {
 322        _next = next;
 323        _logger = logger;
 324    }
 25
 26    /// <inheritdoc/>
 27    public ValueTask<OutgoingResponse> DispatchAsync(IncomingRequest request, CancellationToken cancellationToken)
 328    {
 329        return _logger.IsEnabled(LogLevel.Information) ?
 330            PerformDispatchAsync() :
 331            _next.DispatchAsync(request, cancellationToken);
 32
 33        async ValueTask<OutgoingResponse> PerformDispatchAsync()
 334        {
 35            try
 336            {
 337                OutgoingResponse response = await _next.DispatchAsync(request, cancellationToken).ConfigureAwait(false);
 38
 239                if (response.StatusCode == StatusCode.Ok)
 140                {
 141                    _logger.LogDispatch(
 142                        request.Path,
 143                        request.Operation,
 144                        request.ConnectionContext.TransportConnectionInformation.LocalNetworkAddress,
 145                        request.ConnectionContext.TransportConnectionInformation.RemoteNetworkAddress);
 146                }
 47                else
 148                {
 149                    _logger.LogDispatchError(
 150                        request.Path,
 151                        request.Operation,
 152                        request.ConnectionContext.TransportConnectionInformation.LocalNetworkAddress,
 153                        request.ConnectionContext.TransportConnectionInformation.RemoteNetworkAddress,
 154                        response.StatusCode,
 155                        response.ErrorMessage!);
 156                }
 257                return response;
 58            }
 159            catch (Exception exception)
 160            {
 161                _logger.LogDispatchException(
 162                    exception,
 163                    request.Path,
 164                    request.Operation);
 165                throw;
 66            }
 267        }
 368    }
 69}
 70
 71/// <summary>Provides extension methods for <see cref="ILogger" />. They are used by <see cref="LoggerMiddleware" />.
 72/// </summary>
 73internal static partial class LoggerMiddlewareLoggerExtensions
 74{
 75    [LoggerMessage(
 76        EventId = (int)LoggerMiddlewareEventId.Dispatch,
 77        EventName = nameof(LoggerMiddlewareEventId.Dispatch),
 78        Level = LogLevel.Information,
 79        Message = "Dispatch of {Operation} to {Path} over {LocalNetworkAddress}<->{RemoteNetworkAddress} returned a resp
 80    internal static partial void LogDispatch(
 81        this ILogger logger,
 82        string path,
 83        string operation,
 84        EndPoint? localNetworkAddress,
 85        EndPoint? remoteNetworkAddress);
 86
 87    [LoggerMessage(
 88        EventId = (int)LoggerMiddlewareEventId.DispatchError,
 89        EventName = nameof(LoggerMiddlewareEventId.DispatchError),
 90        Level = LogLevel.Information,
 91        Message = "Dispatch of {Operation} to {Path} over {LocalNetworkAddress}<->{RemoteNetworkAddress} returned a resp
 92    internal static partial void LogDispatchError(
 93        this ILogger logger,
 94        string path,
 95        string operation,
 96        EndPoint? localNetworkAddress,
 97        EndPoint? remoteNetworkAddress,
 98        StatusCode statusCode,
 99        string errorMessage);
 100
 101    [LoggerMessage(
 102        EventId = (int)LoggerMiddlewareEventId.DispatchException,
 103        EventName = nameof(LoggerMiddlewareEventId.DispatchException),
 104        Level = LogLevel.Information,
 105        Message = "Failed to dispatch {Operation} to {Path}")]
 106    internal static partial void LogDispatchException(
 107        this ILogger logger,
 108        Exception exception,
 109        string path,
 110        string operation);
 111}