asp.net core 集成 log4net 日志框架


asp.net core 集成 log4net 日志框架

Intro

在 asp.net core 中有些日志我們可能想輸出到數據庫或文件或elasticsearch等,如果不自己去實現一個 LoggerProvider 的話就需要借助第三方日志框架實現了,而一些第三方框架的實現大多比較完善和成熟,不失為一個好辦法。

自己寫了一個 log4net 的擴展 WeihanLi.Common.Logging.Log4Net,提供了在 .net core 中使用 log4net 的擴展

安裝 nuget 包

通過 nuget 安裝 WeihanLi.Common.Logging.Log4Net

使用

基本使用

ILoggerFactory loggerFactory = new LoggerFactory();
loggerFactory.AddLog4Net(); // loggerFactory.AddLog4Net(log4netConfigFilePath);

你可以在 asp.net core 應用里你的 Startup 文件中使用下面代碼進行配置

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddLog4Net(); // loggerFactory.AddLog4Net(log4netConfigFilePath);

            // ...
        }

默認使用當前目錄下的 log4net.config 文件作為 log4net 的配置文件,如果不是需要自己設置 log4net 配置文件的路徑。

log4net 配置參考 示例配置

源碼解析

項目源碼

Log4NetLoggerProvider

  • 實現記錄日志的 ILogger
    internal class Log4NetLogger : ILogger
    {
        private readonly ILog _logger;

        public Log4NetLogger(string name) => _logger = LogManager.GetLogger(ApplicationHelper.ApplicationName, name);

        public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;

        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;

                case LogLevel.None:
                    return false;

                default:
                    throw new ArgumentOutOfRangeException(nameof(logLevel));
            }
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state,
            Exception exception, Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }

            var message = formatter(state, exception);

            if (!(string.IsNullOrEmpty(message) && exception == null))
            {
                switch (logLevel)
                {
                    case LogLevel.Critical:
                        _logger.Fatal(message, exception);
                        break;

                    case LogLevel.Debug:
                    case LogLevel.Trace:
                        _logger.Debug(message, exception);
                        break;

                    case LogLevel.Error:
                        _logger.Error(message, exception);
                        break;

                    case LogLevel.Information:
                        _logger.Info(message, exception);
                        break;

                    case LogLevel.Warning:
                        _logger.Warn(message, exception);
                        break;

                    default:
                        _logger.Warn($"Encountered unknown log level {logLevel}, writing out as Info.");
                        _logger.Info(message, exception);
                        break;
                }
            }
        }
    }
  • 實現提供 logger 的 ILoggerProvider
    [ProviderAlias("log4net")]
    internal class Log4NetLoggerProvider : ILoggerProvider
    {
        private readonly ConcurrentDictionary<string, Log4NetLogger> _loggers =
            new ConcurrentDictionary<string, Log4NetLogger>(StringComparer.Ordinal);

        public Log4NetLoggerProvider(string confFilePath)
        {
            if (null == LogManager.GetAllRepositories()?.FirstOrDefault(_ => _.Name == ApplicationHelper.ApplicationName))
            {
                XmlConfigurator.ConfigureAndWatch(LogManager.CreateRepository(ApplicationHelper.ApplicationName), new FileInfo(confFilePath));
            }
        }

        public void Dispose() => _loggers.Clear();

        public ILogger CreateLogger(string categoryName) => _loggers.GetOrAdd(categoryName, loggerName => new Log4NetLogger(loggerName));
    }
  • 添加 ILoggerFactory 擴展
    public static class Log4NetLoggerFactoryExtensions
    {
        public static ILoggerFactory AddLog4Net(this ILoggerFactory factory)
        {
            factory.AddProvider(new Log4NetLoggerProvider(ApplicationHelper.MapPath("log4net.config")));

            return factory;
        }

        public static ILoggerFactory AddLog4Net(this ILoggerFactory factory, string configFile)
        {
            factory.AddProvider(new Log4NetLoggerProvider(configFile));

            return factory;
        }
    }

Memo

如果有什么問題或建議,歡迎指出


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM