Skip to content

Commit

Permalink
dh: Add ServicePointOnExceptionLogging handler
Browse files Browse the repository at this point in the history
  • Loading branch information
rmandvikar committed Apr 17, 2024
1 parent c680d3e commit 22f5bee
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/rm.DelegatingHandlers/ServicePointOnExceptionLoggingHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Serilog;

namespace rm.DelegatingHandlers;

/// <summary>
/// Logs <see cref="ServicePoint"/> stats for <see cref="HttpRequestMessage.RequestUri"/> with exception.
/// </summary>
public class ServicePointOnExceptionLoggingHandler : DelegatingHandler
{
private readonly ILogger logger;

/// <inheritdoc cref="ServicePointOnExceptionLoggingHandler" />
public ServicePointOnExceptionLoggingHandler(
ILogger logger)
{
this.logger = logger?.ForContext(GetType())
?? throw new ArgumentNullException(nameof(logger));
}

protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
try
{
return await base.SendAsync(request, cancellationToken)
.ConfigureAwait(false);
}
catch (Exception ex)
{
var servicePoint = ServicePointManager.FindServicePoint(request.RequestUri);
var props = ServicePointHelpers.GetServicePointEnrichers(servicePoint);

logger.ForContext(props)
.Error(ex, "ServicePoint stats");

throw;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Net.Http;
using AutoFixture;
using AutoFixture.AutoMoq;
using Moq;
using NUnit.Framework;
using rm.DelegatingHandlers;
using Serilog;
using Serilog.Core;

namespace rm.DelegatingHandlersTest;

[TestFixture]
public class ServicePointOnExceptionLoggingHandlerTests
{
[Test]
public async Task Does_Not_Log_ServicePoint_Stats()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());

var loggerMock = fixture.Freeze<Mock<ILogger>>();
loggerMock.Setup(x => x.ForContext(It.IsAny<Type>())).Returns(loggerMock.Object);
loggerMock.Setup(x => x.ForContext(It.IsAny<IEnumerable<ILogEventEnricher>>())).Returns(loggerMock.Object);
var servicePointOnExceptionLoggingHandler = new ServicePointOnExceptionLoggingHandler(loggerMock.Object);

using var invoker = HttpMessageInvokerFactory.Create(
fixture.Create<HttpMessageHandler>(), servicePointOnExceptionLoggingHandler);

using var requestMessage = fixture.Create<HttpRequestMessage>();
using var _ = await invoker.SendAsync(requestMessage, CancellationToken.None);

loggerMock.Verify((x) =>
x.Error(It.IsAny<string>()),
Times.Never);
}

[Test]
public void Logs_ServicePoint_Stats_During_Exception()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());

var loggerMock = fixture.Freeze<Mock<ILogger>>();
loggerMock.Setup(x => x.ForContext(It.IsAny<Type>())).Returns(loggerMock.Object);
loggerMock.Setup(x => x.ForContext(It.IsAny<IEnumerable<ILogEventEnricher>>())).Returns(loggerMock.Object);
var servicePointOnExceptionLoggingHandler = new ServicePointOnExceptionLoggingHandler(loggerMock.Object);
var throwingHandler = new ThrowingHandler(new TurnDownForWhatException());

using var invoker = HttpMessageInvokerFactory.Create(
fixture.Create<HttpMessageHandler>(), servicePointOnExceptionLoggingHandler, throwingHandler);

using var requestMessage = fixture.Create<HttpRequestMessage>();
var ex = Assert.ThrowsAsync<TurnDownForWhatException>(async () =>
{
using var _ = await invoker.SendAsync(requestMessage, CancellationToken.None);
});

loggerMock.Verify((x) =>
x.Error(ex, "ServicePoint stats"),
Times.Once);
}
}

0 comments on commit 22f5bee

Please sign in to comment.