ASP.NET CORE自定义记录器按请求保存到数据库

时间:2017-07-19 13:36:43

标签: logging asp.net-core

我需要为ASP.NET Core WEB API开发自定义记录器。 我想使用标准的日志记录基础结构,但是,我需要的是有点不同,因为日志记录不应该立即写入目标介质,但我需要

  1. 按请求创建新记录器
  2. 在内存中收集此请求的日志记录
  3. 在该操作结束时或出现异常时将请求的所有记录保存为数据库。
  4. 我是ASP.NET Core的新手,所以我遵循了几个教程,创建了DBLogger(实现ILogger并将记录保存到内部StringBuilder +另外一个方法Save),配置,提供者,扩展,我在Startup中注册了它它的工作原理,但没有最后一步,这是对数据库的保存。 在控制器中,我使用DI来获取记录器,所以它看起来像这样

        public class ValuesController : Controller
    
    {
        private readonly ILogger<ValuesController> _logger;
    
        public ValuesController(ILogger<ValuesController> logger)
        {
            _logger = logger;
        }
    
        [HttpGet]
        public IEnumerable<string> Get()
        {
            _logger.LogWarning("TestWarning");
            _logger.LogInformation("TestInfo");
    
            return new string[] { "value1", "value2" };
        }
    

    所以我现在可以编写日志记录了,但是如何调用特定Logger的附加(自定义)功能(在本例中我的DBLogger的Save()方法)?我的控制器中的_logger属性保存对应用程序内部使用的所有记录器的引用,但无法从代码访问该集合。

    一般来说,问题甚至可能是:如何在代码中使用自定义ILogger的自定义功能。或许 - 我怎样才能获得对自定义记录器的引用?

    [编辑] 这不是我的类型(DBlogger),我通过DI收到的,但我得到了Microsoft.Extensions.Logging.Logger,包含Microsoft.Extensions.Logging.Logger类型的非公共属性_logger,包含包含我的记录器的非公开记录器集合(见下图)。所以这就是为什么我觉得它很复杂

    1]

    由于

    菲利普

2 个答案:

答案 0 :(得分:1)

//编写一个扩展方法Save for ILogger并将任何参数传递给StateInfo

public static void Save(this ILogger logger, string param) {

var state = new List<KeyValuePair<string, dynamic>>
{
    new KeyValuePair<string, dynamic>("Myparam", param),

};

logger.Log(level,999, state, null, null);
}

public class DBLogger:ILogger{
public void Log<TState>(LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
      if (eventId.Id == 999) //Save Event
      {
            if (state is IReadOnlyList<KeyValuePair<string, object>> stateInfo )
            {
                foreach (var property in stateInfo)
                {
                  if (property.Key == "Myparam")
                        {
                            var value = (string)property.Value;//do something with value
                        }
                }
            }
     }
}

答案 1 :(得分:0)

您可以将记录器声明为动态:

    private readonly dynamic _logger;

但是,在这种情况下,您需要确保在执行该调用时ILogger的特定实现具有一个名为Save的方法。

OR

使用反射来调用save方法。当您的特定ILogger实现不包含名为Save的方法时,您可以使用try catch来处理这种情况。