拦截或装饰对ILogger的调用

拦截或装饰对ILogger的调用

本文介绍了拦截或装饰对ILogger的调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用温莎城堡,并在我的应用程序中使用它的测井设施.

I'm currently using castle windsor, along with it's logging facility in my application.

但是,在我的日志记录中,我想包含一些上下文信息,这些信息不在记录的消息中,而是存储在 CallContext .

However, in my logging I would like to include some contextual information that is not within the logged message, but stored within the CallContext.

我尝试通过使用以下命令拦截对ILogger的调用来做到这一点:

I have tried to do this by intercepting the calls to ILogger using the following:

internal class Program
{
    private static void Main(string[] args)
    {
        var container = new WindsorContainer();
        container.AddFacility<LoggingFacility>(f => f.UseNLog());
        container.Kernel.Resolver.AddSubResolver(new LoggerResolver(container.Kernel));

        var logger = container.Resolve<ILogger>();
    }
}

public class LoggerResolver: ISubDependencyResolver
{
    private readonly IKernel _kernel;
    private static ProxyGenerator _proxyGenerator;

    static LoggerResolver()
    {
        _proxyGenerator = new ProxyGenerator();
    }

    public LoggerResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
    {
        return dependency.TargetType == typeof(ILogger);
    }

    public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
    {
        return _proxyGenerator.CreateInterfaceProxyWithTarget(_kernel.Resolve<ILogger>(), new LoggingInterceptor());
    }
}

public class LoggingInterceptor: IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        //Some modification to message here
        invocation.Proceed();
    }
}

但是变量logger的类型为NLog.Loggger,而不是我期望的动态代理.

But the variable logger is of type NLog.Loggger rather than the dynamic proxy I was expecting.

推荐答案

使用ILSpy进行的某些挖掘似乎表明您将无法拦截对ILogger实例化的调用. ILogger实例是直接由NLogFactory创建的(对于我研究过的所有日志记录工厂,log4net,控制台等都相同)

Some digging with ILSpy seems to show that you won't be able to intercept calls to the ILogger instantiation. The ILogger intance is created directly by the NLogFactory (same thing for all logging factories I looked into, log4net, console, etc)

// Castle.Services.Logging.NLogIntegration.NLogFactory
public override ILogger Create(string name)
{
    Logger logger = LogManager.GetLogger(name);
    return new NLogLogger(logger, this);
}

如果确实有必要,您应该能够继承您感兴趣的工厂(基本上是NLogFactoryExtendedNLogFactory),以便覆盖ILogger的创建.然后创建ILogger的基于实例的代理,并插入自定义拦截器.最后,通知LoggingFacility您要使用自定义工厂.

If this is really necessary you should be able to inherit the factories you're interested into (basically, NLogFactory and ExtendedNLogFactory) in order to override the ILogger creation. Then create a instance-based proxy of the ILogger and plug in your custom interceptors. Finally inform the LoggingFacility that you want to use a custom factory.

我开始对您的问题感到悲观,但是我发现该解决方案实施起来非常简单,因此您应该不会遇到太多问题来实现您想要的目标.代码?当然:)

I started being pessimist about your problem but I found the solution to be quite simple to implement, so you shouldn't have too many problems to achieve what you want.Code? Of course :)

public class MyFactory : NLogFactory
{
    public override ILogger Create(string name)
    {
        var il = base.Create(name);
        var pg =  new ProxyGenerator();
        return pg.CreateInterfaceProxyWithTarget<ILogger>(il, new LoggingInterceptor());
    }
}

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        //Some modification to message here
        invocation.Proceed();
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var container = new WindsorContainer();
        container.AddFacility<LoggingFacility>(f => f.UseNLog().LogUsing<MyFactory>());

        var logger = container.Resolve<ILogger>();
        logger.Debug("data"); // we intercept this call, success
        Console.ReadLine();
    }
}

这篇关于拦截或装饰对ILogger的调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 07:32