Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging using AOP in .NET Core 2.1

I want to implement AOP for the logging in my .NET Core 2.1 solution. I've never used it before and I've been looking online and cant seem to see any examples of people using it with Core 2. Does anyone know how i would go about this?

For example what packages to use for AOP and have any example code to get me started? Im using the built in DI with .net core so i dont need to worry about that part.

like image 537
user2661305 Avatar asked Aug 10 '18 09:08

user2661305


2 Answers

Microsoft DI does not offer advances scenarios such as interceptor or decorators(there is a workaround for decorators using Microsoft DI: https://medium.com/@willie.tetlow/net-core-dependency-injection-decorator-workaround-664cd3ec1246).

You can implement AOP by using Autofac (https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html) or Simple injector with dynamic proxy. Both have a really good documentation. Simple injector doesn't have an out of the box solution for interception because of their design rules but you can add an extension for it (http://simpleinjector.readthedocs.io/en/latest/aop.html).

Here is a basic AOP scenario from the official SI documentation:(http://simpleinjector.readthedocs.io/en/latest/InterceptionExtensions.html) :

//Add registration to the composition root
container.InterceptWith<MonitoringInterceptor>(serviceType => serviceType.Name.EndsWith("Repository"));`

// Here is an example of an interceptor implementation.
// NOTE: Interceptors must implement the IInterceptor interface:
private class MonitoringInterceptor : IInterceptor {
    private readonly ILogger logger;

  public MonitoringInterceptor(ILogger logger) {
        this.logger = logger;
    }

    public void Intercept(IInvocation invocation) {
        var watch = Stopwatch.StartNew();

        // Calls the decorated instance.
        invocation.Proceed();

        var decoratedType = invocation.InvocationTarget.GetType();

        this.logger.Log(string.Format("{0} executed in {1} ms.",
            decoratedType.Name, watch.ElapsedMilliseconds));
    }
}
like image 198
aseaSharp Avatar answered Nov 08 '22 23:11

aseaSharp


Disclaimer: I am the producer of this solution

Microsoft does not provide an AOP solution out the box for Net Core. However, I have produced a 3rd party project which may help. It works directly with Net Core and plugs in via the ServiceCollection registration in your application.

What Microsoft does provide is a library called System.Runtime.DispatchProxy which can be used to create proxy objects for your classes. However, this proxy isnt particularly useful or feature rich on its own and would require a lot of extra code to get something that is on a level with Castle Proxy (the well known Dynamic Proxy library)

With that in mind, I have created a library which wraps the DispatchProxy into code that can be easily injected during the ServiceCollection configuration in the application startup. The trick is to have a way to create attributes AND a paired interceptor that can be applied to your methods. The attribute is then read during the Proxy wrapping and the relevant Interceptor is called.

This is an example Interceptor Attribute

public class ConsoleLogAttribute : MethodInterceptorAttribute
{
}

This is an example Interceptor class

public class ConsoleLogInterceptor : MethodInterceptor
{
    public override void BeforeInvoke(IInterceptionContext interceptionContext)
    {
        Console.WriteLine($"Method executing: {interceptionContext.CurrentMethod.Name}");
    }

    public override void AfterInvoke(IInterceptionContext interceptionContext, object methodResult)
    {
        Console.WriteLine($"Method executed: {interceptionContext.CurrentMethod.Name}");
    }
}

This is how it would be applied to your method

[ConsoleLog]
public void TestMethod()
{
}

And then finally, this is how it would be added to your ServiceCollection configuration (assuming that the class you wanted to Proxy was called [TestClass]:

public void ConfigureServices(IServiceCollection services)
{
    // Configure Simple Proxy
    services.EnableSimpleProxy(p => p.AddInterceptor<ConsoleLogAttribute, ConsoleLogInterceptor>());

    // Configure your services using the Extension Methods
    services.AddTransientWithProxy<ITestClass, TestClass>();
}

Take a look at this GitHub project: https://github.com/f135ta/SimpleProxy

like image 29
Robert Perry Avatar answered Nov 09 '22 00:11

Robert Perry