【问题标题】:ASP.NET CORE custom logger saving to database once per requestASP.NET CORE 自定义记录器每个请求保存到数据库一次
【发布时间】:2017-12-24 19:50:51
【问题描述】:

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

  1. 为每个请求创建新的记录器
  2. 在内存中收集该请求的日志记录
  3. 在该操作结束或出现异常时将请求的所有记录作为一条记录保存到数据库中。

我对 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,其中包含包含我的记录器的非公共记录器集合(见下图)。这就是为什么我觉得它很复杂

谢谢

菲利普

【问题讨论】:

    标签: logging asp.net-core


    【解决方案1】:

    //为ILogger写一个扩展方法Save,并将任何参数传递给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
                            }
                    }
                }
         }
    }
    

    【讨论】:

      【解决方案2】:

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

          private readonly dynamic _logger;
      

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

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

      【讨论】:

      • 请看我的编辑。我没有在 ILOGger 中输入我的类型,但我得到了更复杂的结构和非公共访问权限。我该如何使用您建议的方法?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      • 1970-01-01
      • 2010-11-02
      • 2019-11-09
      • 2018-01-10
      • 1970-01-01
      相关资源
      最近更新 更多