ILogger的自定义实现

时间:2018-11-27 06:51:33

标签: asp.net-core .net-core asp.net-core-2.1

在我的项目中,我经常在日志消息中添加前缀。

目前我正在使用

  logger.LogDebug(prefix + " some message");

我认为这是实现自定义记录器的好方法,在该记录器中,我设置前缀,并且记录器每次记录某些内容时都会附加该前缀。

因此,我创建了自定义记录器类并实现了ILogger接口。但是我不明白如何使用

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)

添加前缀(自定义记录器类的成员)的方法。

我的完整代码是:

  public class CustomLogger : ILogger
  {

    private readonly ILogger _logger;
    private string _logPrefix;

    public CustomLogger(ILogger logger)
    {
      _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    _logPrefix = null;
    }

    public ILogger SetLogPrefix(string logPrefix)
    {
      _logPrefix = logPrefix;
      return this;
    }

    public IDisposable BeginScope<TState>(TState state)
    {
      return _logger.BeginScope(state);
    }

    public bool IsEnabled(LogLevel logLevel)
    {
      return _logger.IsEnabled(logLevel);
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
      _logger.Log(logLevel, eventId, state, exception, formatter);
    }

  }

3 个答案:

答案 0 :(得分:3)

我个人认为这不是一个好方法,“前缀”将被重复很多。为什么不使用Log Scopes呢?

public IActionResult GetById(string id)
{
    TodoItem item;
    using (_logger.BeginScope("Message attached to logs created in the using block"))
    {
        _logger.LogInformation(LoggingEvents.GetItem, "Getting item {ID}", id);
        item = _todoRepository.Find(id);
        if (item == null)
        {
            _logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
            return NotFound();
        }
    }
    return new ObjectResult(item);
}

输出

info: TodoApi.Controllers.TodoController[1002]
      => RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApi.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
      Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
      => RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApi.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
      GetById(0) NOT FOUND

当前,您无法更改日志记录模板,这是Asp.net Core中内置的基本日志记录的限制。要获得更强大的功能,您可以尝试Serilog,继续使用ILogger界面,并在program.cs类中更改某些代码行

您还应该查看此Benefits of Structured Logging vs basic logging

答案 1 :(得分:2)

我认为您不应在自定义记录器中调用_logger。

这将是在运行时的循环调用,结果将是“前缀:前缀:前缀:前缀:前缀:前缀:前缀:前缀:前缀:前缀:...”

简单来说,您可以创建一个简单的记录器并实现日志编写器,例如控制台,数据库编写器,log4net,...

现在,您应该像下面那样更改自定义记录器:

public class CustomLogger : ILogger
{
    private readonly string CategoryName;
    private readonly string _logPrefix;

    public CustomLogger(string categoryName, string logPrefix)
    {
        CategoryName = categoryName;
        _logPrefix = logPrefix;
    }

    public IDisposable BeginScope<TState>(TState state)
    {
        return new NoopDisposable();
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return true;
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        string message = _logPrefix;
        if (formatter != null)
        {
            message += formatter(state, exception);
        }
        // Implement log writter as you want. I am using Console
        Console.WriteLine($"{logLevel.ToString()} - {eventId.Id} - {CategoryName} - {message}");
    }

    private class NoopDisposable : IDisposable
    {
        public void Dispose()
        {
        }
    }
}

第二步,创建记录器提供程序:

 public class LoggerProvider : ILoggerProvider
    {     
        public ILogger CreateLogger(string categoryName)
        {                
            return new CustomLogger(categoryName, "This is prefix: ");
        }

        public void Dispose()
        {
        }
    }

第三步,在“从Startup.cs配置”中:

loggerFactory.AddProvider(new MicroserviceLoggerProvider());

答案 2 :(得分:0)

实施扩展名以将prefix添加到日志记录。

    public static class LogExtensions
    {
        public static void PrefixLogDebug(this ILogger logger, string message, string prefix = "Edward", params object[] args)
        {
            logger.LogDebug($"{prefix} {message}");
        }
    }

用法:

        _log.PrefixLogDebug("Log From Prefix extension");
        _log.PrefixLogDebug("Log From Prefix extension", "New Prefix");
相关问题