using log4net; using log4net.Config; using Microsoft.Extensions.Logging; using System.Collections.Concurrent; namespace Esim.SendMail.Logging; public class Log4NetProvider : ILoggerProvider { private readonly ConcurrentDictionary _loggers = new(); public Log4NetProvider() { } public ILogger CreateLogger(string categoryName) { return _loggers.GetOrAdd(categoryName, name => new Log4NetLogger(name)); } public void Dispose() { _loggers.Clear(); } } public class Log4NetLogger : ILogger { private readonly ILog _log; public Log4NetLogger(string categoryName) { _log = LogManager.GetLogger(typeof(Log4NetProvider).Assembly, categoryName); } public IDisposable? BeginScope(TState state) where TState : notnull => null; public bool IsEnabled(LogLevel logLevel) { return logLevel switch { LogLevel.Critical => _log.IsFatalEnabled, LogLevel.Error => _log.IsErrorEnabled, LogLevel.Warning => _log.IsWarnEnabled, LogLevel.Information => _log.IsInfoEnabled, LogLevel.Debug => _log.IsDebugEnabled, LogLevel.Trace => _log.IsDebugEnabled, _ => false }; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { if (!IsEnabled(logLevel)) return; var message = formatter(state, exception); if (string.IsNullOrEmpty(message) && exception == null) return; switch (logLevel) { case LogLevel.Critical: _log.Fatal(message, exception); break; case LogLevel.Error: _log.Error(message, exception); break; case LogLevel.Warning: _log.Warn(message, exception); break; case LogLevel.Information: _log.Info(message, exception); break; case LogLevel.Debug: _log.Debug(message, exception); break; case LogLevel.Trace: _log.Debug(message, exception); break; } } } public static class Log4NetExtensions { public static ILoggingBuilder AddLog4Net(this ILoggingBuilder builder, string configPath) { XmlConfigurator.Configure(new FileInfo(configPath)); builder.AddProvider(new Log4NetProvider()); return builder; } }