如何为各种控制器和 asp net mvc 过滤器创建 nlog 记录器?

How to create nlog loggers for various controllers and asp net mvc filters?

我需要以编程方式为每个控制器(比方说:文档、客户和仓库,以记录其中的一些操作)和控制器上方的过滤器(以记录发送到每个操作的参数)创建记录器。每个控制器逻辑都应记录到另一个文件中。 Documents.csv、Customers.csv 和 Warehouses.csv。

目前我有一个 nlog 记录器的包装器。包装器通过构造函数注入控制器实例,然后通过 LogManager 初始化内部的 nlog 记录器。初始化创建新的目标和日志级别并将其分配给 LogManager.Configuration.

问题是在几个请求之后,每个记录器都会记录到每个文件,例如。来自客户的逻辑被记录到 Customers.csv,反之亦然,与来自过滤器的记录器相同。

然后我应该如何为每个控制器配置不同目标的单独博客记录器并为过滤器单独配置?

与通过 xms 等相比,我更喜欢编程配置

请求的适配器:

public class Logger : ILogger
{
    private NLog.Logger _logger;
    string _deployVersion;

    public Logger(string deploymentVersion)
    {
        _deployVersion = deploymentVersion;
    }

    public void Init(string loggerName)
    {
        _logger = NLog.LogManager.GetLogger(loggerName);
    }

    public void Init(string loggerName, string header, string layout, Level level)
    {
        LoggingConfiguration config;
        if (NLog.LogManager.Configuration == null)
        {
            config = new LoggingConfiguration();
        }
        else
        {
            config = LogManager.Configuration;
        }

        if (config.FindTargetByName(loggerName) == null)
        {
            var target = CreateTarget(loggerName, header, layout, level); //configures target: path, archives and layout
            config.AddTarget(loggerName, target);

            var logLevel = GetLogLevel(level); //translates Level enum to NLog level
            var rule1 = new LoggingRule("*", logLevel, target);
            config.LoggingRules.Add(rule1);

            LogManager.Configuration = config;
        }
        _logger = LogManager.GetLogger(loggerName);
    }
    ...
    //Info, Debug etc. methods

太好了,您已经在此处使用了一个界面,它可以更轻松地生成此模式。

这里的主要问题是责任,因为您的控制器代码将(我假设)调用 Init(string loggerName, string header, string layout, Level level)。这可能不是最佳实践,因为您可能不得不多次重复此代码,并且控制器可能不应该关心日志的去向或格式......只是使用日志这一事实。

不要直接注入这些,而是​​使用工厂来获取正确的记录器类型。例如,CustomerLogger : ILogger:

public class LogFactory
{
    public ILogger Get<T>() where T : ILogger
    {
        ILogger instance = null;
        if (typeof(T) == typeof(CustomerLogger))
        {
            instance = (T)Activator.CreateInstance(typeof(T), "CustomerLogger", "Header", "Layout", Level.Verbose);
        } 
        else if (...)
        {
            ...etc
        }
        return instance;
    }
} 

这意味着您可以将 ILogger 混凝土的管理和创建交给工厂。

请注意,我传入了 string loggerName, string header, string layout, Level level,因此您可以在 CustomerLogger 构造函数中调用 Init。然后你有不同的 ILogger 实现来满足你的需要。

然后您可以让 LogFactory 使用一个接口并将其注入您的控制器,或者简单地在控制器中新建工厂,您可以调用 LogFactory.Get<T>()。选项 A 更适合单元测试目的。

希望对您有所帮助!