代码之家  ›  专栏  ›  技术社区  ›  monty

ILogger的定制实现

  •  0
  • monty  · 技术社区  · 7 年前

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

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

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

        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 回复  |  直到 7 年前
        1
  •  7
  •   Hung Quach    7 年前

    就我个人而言,我认为这不是一个好办法,“前缀”会被大量重复。你为什么不使用 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内核中内置基本日志的限制。对于更强大的一个,你可以尝试 Serilog ,继续使用 ILogger program.cs 班

    你也应该看看这个 Benefits of Structured Logging vs basic logging

        2
  •  10
  •   Håkon K. Olafsen    7 年前

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

    这将是运行时的循环调用,结果将是“prefix:prefix:prefix:prefix:prefix:prefix:prefix:…”

    简单地说,您可以创建一个简单的日志记录器并实现一个日志写入程序,如控制台、数据库写入程序、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()
                {
                }
            }
    

        loggerFactory.AddProvider(new MicroserviceLoggerProvider());
    
        3
  •  3
  •   Edward    7 年前

    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");
    
    推荐文章