Advertisements

Extending Solid.Http for logging

Extending Solid.Http for logging

March 16, 2018 Packages 0

So you’ve decided to use Solid.Http in your project. Thanks! We’re flattered. But now you want to log all outgoing http requests from your application. We’ll be happy to help.

Disclaimer

The following examples are written with the assumption that you’re using Solid.Http 1.1.1-RCĀ or above.

Implementation

First, we create the methods that log request and response events and also the methods that will act as predicates for client error and server error respsones.

private void OnRequest(object sender, RequestEventArgs e)
{
    var logger = e.Services.GetService();
    var stopwatch = new Stopwatch();
    var request = e.Request;
    var scopeMessage = $"Outgoing - {request.Method.Method} - {request.RequestUri}";
    var scope = logger.BeginScope(scopeMessage);
    stopwatch.Start();
    e.Request.Properties.Add("scope", scope);
    e.Request.Properties.Add("stopwatch", stopwatch);
    logger.LogInformation($"Starting outgoing request");
}

private void OnResponse(object sender, ResponseEventArgs e)
{
    var logger = e.Services.GetService();
    var stopwatch = e.Response.RequestMessage.Properties["stopwatch"] as Stopwatch;
    var scope = e.Response.RequestMessage.Properties["scope"] as IDisposable;
    stopwatch.Stop();
    logger.LogInformation($"Outgoing request took {stopwatch.ElapsedMilliseconds}ms.");
    scope.Dispose();
}

private bool ClientError(HttpResponseMessage response)
{
    var code = (int)response.StatusCode;
    return code >= 400 && code < 500; 
} 

private void LogWarning(HttpResponseMessage response, IServiceProvider provider) 
{
    var logger = provider.GetService();
    var message = $"Server responded {response.StatusCode}";
    logger.LogWarning(message); 
} 

private bool ServerError(HttpResponseMessage response) 
{
    var code = (int)response.StatusCode;
    return code >= 500;
}

private void LogError(HttpResponseMessage response, IServiceProvider provider)
{
    var logger = provider.GetService();
    var message = $"Server responded {response.StatusCode}";
    logger.LogError(message);
}

Next, we create an event handler that gets triggered at the creation of SolidHttpRequest. This event handler will use the methods that we just created.

private void AddSolidHttpLoggingEvents(object sender, SolidHttpRequestCreatedEventArgs e)
{
    e.Request.OnRequest += OnRequest;
    e.Request.On(ClientError, (response, services) => LogWarning(response, services));
    e.Request.On(ServerError, (response, services) => LogError(response, services));
    e.Request.OnResponse += OnResponse;
}

Finally, we add Solid.Http and configure it to add events to SolidHttpRequest on creation.

public void ConfigureServices(IServiceCollection services)
{
    services.AddSolidHttp(options =>
    {
        options.Events.OnRequestCreated += AddSolidHttpLoggingEvents;
    });
}

Conclusion

Now, when a request is sent using Solid.Http, the response will be timed and logged. Extending Solid.Http is easy.

Advertisements