Simple Logging Middleware (Katana Part 4)

Tuesday, November 12, 2013

Perhaps all you want to do with middleware is perform some simple logging for an HTTP request and response.

Here’s a class that can hold the options for which keys the application needs to log, and and an Action to encapsulate the logging logic.

public class SimpleLoggerOptions
{
    public IList<string> RequestKeys { get; set; }
    public IList<string> ResponseKeys { get; set; }
    public Action<string, object> Log { get; set; }
}

The logging middleware itself just needs to invoke the Action delegate at the appropriate time, and with the appropriate values, all the while letting each request pass through into the rest of the pipeline by calling into the next AppFunc.

using AppFunc = Func<IDictionary<string, object>, Task>;

public class SimpleLogger
{
    private readonly AppFunc _next;
    private readonly SimpleLoggerOptions _options;

    public SimpleLogger(AppFunc next, SimpleLoggerOptions options)
    {
        _next = next;
        _options = options;
    }

    public async Task Invoke(IDictionary<string, object> environment)
    {
        foreach (var key in _options.RequestKeys)
          {
            _options.Log(key, environment[key]);            
        }   

        await _next(environment);

        foreach (var key in _options.ResponseKeys)
        {
            _options.Log(key, environment[key]);
        }   
    }
    
}

Of course there could be some additional code inside the middleware to validate parameters and make sure a key exists before indexing into the environment dictionary, but given a simple extension method to help with registration …...

public static class AppBuilderExtensions
{
    public static IAppBuilder UseSimpleLogger(
        this IAppBuilder app, 
        SimpleLoggerOptions options)
    {
        return app.Use<SimpleLogger>(options);
    }
}

… it is now easy to add logging to any application by registering the simple logger as the first piece of middleware. The keys specified below are all keys required by the OWIN specification

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var options = new SimpleLoggerOptions
        {
            Log = (key, value) => Debug.WriteLine("{0}:{1}", key, value),
            RequestKeys = new[] {"owin.RequestPath", "owin.RequestMethod"},
            ResponseKeys = new[] {"owin.ResponseStatusCode"}
        };
        app.UseSimpleLogger(options);


        // ... and more ...
    }
}

Next up: how to shim and log every other piece of middleware.

Previous posts in this series.


Comments
Comments are closed.

My Pluralsight Courses

K.Scott Allen OdeToCode by K. Scott Allen
What JavaScript Developers Should Know About ECMAScript 2015
The Podcast!