ILogger 的自定义实现
Custom implementation of ILogger
在我的项目中,我经常为我的日志消息添加前缀。
目前我正在使用
logger.LogDebug(prefix + " some message");
我认为这是实现自定义记录器的好方法,我在其中设置前缀,记录器本身在每次记录内容时附加它。
所以我创建了自定义记录器 class 并实现了 ILogger 接口。但是我不明白如何使用
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
添加前缀的方法(这是自定义记录器的成员class)。
我的完整代码是:
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);
}
}
我认为您不应该在自定义记录器中调用 _logger。
这将是运行时的循环调用,结果将是 "prefix: prefix: prefix: prefix: prefix: prefix: prefix: prefix: ..."
简单地说,您可以创建一个简单的记录器并实现一个日志编写器,例如 Console、数据库编写器、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()
{
}
}
}
第二步,创建logger provider:
public class LoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
return new CustomLogger(categoryName, "This is prefix: ");
}
public void Dispose()
{
}
}
第三步,在Configure from Startup.cs:
loggerFactory.AddProvider(new MicroserviceLoggerProvider());
实施扩展以将 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");
我个人认为这不是一个好方法,"prefix" 会重复很多。为什么不使用 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
class
中的一些代码行
在我的项目中,我经常为我的日志消息添加前缀。
目前我正在使用
logger.LogDebug(prefix + " some message");
我认为这是实现自定义记录器的好方法,我在其中设置前缀,记录器本身在每次记录内容时附加它。
所以我创建了自定义记录器 class 并实现了 ILogger 接口。但是我不明白如何使用
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
添加前缀的方法(这是自定义记录器的成员class)。
我的完整代码是:
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);
}
}
我认为您不应该在自定义记录器中调用 _logger。
这将是运行时的循环调用,结果将是 "prefix: prefix: prefix: prefix: prefix: prefix: prefix: prefix: ..."
简单地说,您可以创建一个简单的记录器并实现一个日志编写器,例如 Console、数据库编写器、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()
{
}
}
}
第二步,创建logger provider:
public class LoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
return new CustomLogger(categoryName, "This is prefix: ");
}
public void Dispose()
{
}
}
第三步,在Configure from Startup.cs:
loggerFactory.AddProvider(new MicroserviceLoggerProvider());
实施扩展以将 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");
我个人认为这不是一个好方法,"prefix" 会重复很多。为什么不使用 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
class