Встроенное ведение журналов ASP.Net Core было попыткой Microsoft вести журналы Microsoft, используя инъекцию зависимостей. Он следует основным принципам и принципам подхода Log4Net (который был стандартизирован среди .Net, Java и Javascript, среди прочих). Таким образом, эти два подхода не полностью противоречат друг другу.
Однако в данном конкретном случае реализация, по-видимому, фактически вступает в противоречие с намерением обоих подходов к ведению журнала.
Log4Net разделяет два акта запись и запись журнала . Первый выполняется через интерфейс ILog . Вторая выполняется через один из Appenders .
Аналогично, в ASP.net Core API используется ILogger и один или несколько провайдеров отправлять сообщения журнала.
Поскольку мне удобнее работать с log4net, а также я не вижу особого смысла в добавлении регистраторов посредством внедрения зависимостей в КАЖДЫЙ КЛАСС, я использовал вместо log4net подход LogManager.GetLogger(typeof(MyClass))
, а неделать это через Microsoft DI. Мои appenders также работают через log4net. Таким образом, моя реализация была сосредоточена на переводе результатов регистрации Microsoft в формат log4net, который, по-видимому, является тем, чего хочет ваша команда, но противоположным тому, что вы здесь делаете. Мой подход был основан на этой статье . Код, который я использовал ниже:
Замечания по реализации:
Я настроил пользовательский appender через log4net, который записывает мои журналы в базу данных журналов (часто используемые базы данных). для этого есть локи и / или эластичный поиск).
В методе Configure()
на startup.cs
вам понадобится следующая строка (обратите внимание, что я создаю экземпляр customAppender в ConfigureServices
, а затем добавляю его в DI, но вы несделать это нужно следующим образом):
loggerFactory.AddLog4Net(_serverConfig.LoggingSettings, customAppender);
Также необходимо иметь следующее в ConfigureServices()
(не уверен почему, но, похоже, он гарантирует, что включится обычное ведение журнала ядра .net).
services.AddLogging(config => {
config.AddDebug();
config.AddConsole();
});
Log4NetLogger.cs
/// <summary>
/// Writes ASP.net core logs out to the log4net system.
/// </summary>
public class Log4NetLogger : ILogger
{
private readonly ILog _logger;
public Log4NetLogger(string name)
{
_logger = LogManager.GetLogger(typeof(Log4NetProvider).Assembly, name);
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
switch (logLevel) {
case LogLevel.Critical:
return _logger.IsFatalEnabled;
case LogLevel.Debug:
case LogLevel.Trace:
return _logger.IsDebugEnabled;
case LogLevel.Error:
return _logger.IsErrorEnabled;
case LogLevel.Information:
return _logger.IsInfoEnabled;
case LogLevel.Warning:
return _logger.IsWarnEnabled;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel));
}
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state,
Exception exception, Func<TState, Exception, string> formatter)
{
if (!this.IsEnabled(logLevel)) {
return;
}
if (formatter == null) {
throw new ArgumentNullException(nameof(formatter));
}
string message = null;
if (null != formatter) {
message = formatter(state, exception);
}
if (!string.IsNullOrEmpty(message) || exception != null) {
switch (logLevel) {
case LogLevel.Critical:
_logger.Fatal(message);
break;
case LogLevel.Debug:
case LogLevel.Trace:
_logger.Debug(message);
break;
case LogLevel.Error:
_logger.Error(message);
break;
case LogLevel.Information:
_logger.Info(message);
break;
case LogLevel.Warning:
_logger.Warn(message);
break;
default:
_logger.Warn($"Encountered unknown log level {logLevel}, writing out as Info.");
_logger.Info(message, exception);
break;
}
}
}
Log4NetProvider.cs
/// <summary>
/// Returns new log4net loggers when called by the ASP.net core logging framework
/// </summary>
public class Log4NetProvider : ILoggerProvider
{
private readonly LoggingConfig _config;
private readonly ConcurrentDictionary<string, Log4NetLogger> _loggers =
new ConcurrentDictionary<string, Log4NetLogger>();
private readonly ILoggerRepository _repository =
log4net.LogManager.CreateRepository(typeof(Log4NetProvider).Assembly, typeof(log4net.Repository.Hierarchy.Hierarchy));
public Log4NetProvider(LoggingConfig config, MyCustomAppender otherAppender)
{
_config = config;
BasicConfigurator.Configure(_repository, new ConsoleAppender(), otherAppender);
LogManager.GetLogger(this.GetType()).Info("Logging initialized.");
}
public ILogger CreateLogger(string categoryName)
{
return _loggers.GetOrAdd(categoryName, this.CreateLoggerImplementation(categoryName));
}
public void Dispose()
{
_loggers.Clear();
}
private Log4NetLogger CreateLoggerImplementation(string name)
{
return new Log4NetLogger(name);
}
}
Log4NetExtensions.cs
/// <summary>
/// A helper class for initializing Log4Net in the .NET core project.
/// </summary>
public static class Log4netExtensions
{
public static ILoggerFactory AddLog4Net(this ILoggerFactory factory, LoggingConfig config, MyCustomAppender appender)
{
factory.AddProvider(new Log4NetProvider(config, appender));
return factory;
}
}