Browse Source

Replace log4net with Microsoft.Extensions.Logging.Abstractions

Lucas Trzesniewski 4 years ago
parent
commit
a209a57a99
38 changed files with 420 additions and 302 deletions
  1. 1 0
      src/Abc.Zebus.Directory.Runner/Abc.Zebus.Directory.Runner.csproj
  2. 88 0
      src/Abc.Zebus.Directory.Runner/Log4NetFactory.cs
  3. 8 5
      src/Abc.Zebus.Directory.Runner/Program.cs
  4. 0 19
      src/Abc.Zebus.Directory.Tests/Log4netConfigurator.cs
  5. 7 7
      src/Abc.Zebus.Directory/DeadPeerDetection/DeadPeerDetector.cs
  6. 6 6
      src/Abc.Zebus.Directory/DeadPeerDetection/DeadPeerDetectorEntry.cs
  7. 3 3
      src/Abc.Zebus.Directory/Handlers/DirectoryCommandsHandler.cs
  8. 5 5
      src/Abc.Zebus.Persistence.CQL/Storage/CqlMessageReader.cs
  9. 11 11
      src/Abc.Zebus.Persistence.CQL/Storage/CqlStorage.cs
  10. 8 8
      src/Abc.Zebus.Persistence.CQL/Storage/PeerStateRepository.cs
  11. 2 0
      src/Abc.Zebus.Persistence.Runner/Abc.Zebus.Persistence.Runner.csproj
  12. 13 8
      src/Abc.Zebus.Persistence.Runner/Program.cs
  13. 3 3
      src/Abc.Zebus.Persistence/Handlers/MessageHandledHandler.cs
  14. 5 5
      src/Abc.Zebus.Persistence/Handlers/PersistMessageCommandHandler.cs
  15. 3 3
      src/Abc.Zebus.Persistence/Initialization/MessageReplayerInitializer.cs
  16. 8 8
      src/Abc.Zebus.Persistence/Matching/InMemoryMessageMatcher.cs
  17. 16 16
      src/Abc.Zebus.Persistence/MessageReplayer.cs
  18. 8 8
      src/Abc.Zebus.Persistence/Transport/QueueingTransport.cs
  19. 0 33
      src/Abc.Zebus.Tests/Log4netConfigurator.cs
  20. 0 2
      src/Abc.Zebus.Tests/Program.cs
  21. 1 1
      src/Abc.Zebus/Abc.Zebus.csproj
  22. 13 13
      src/Abc.Zebus/Core/Bus.cs
  23. 19 20
      src/Abc.Zebus/Core/BusMessageLogger.cs
  24. 11 11
      src/Abc.Zebus/Directory/PeerDirectoryClient.cs
  25. 10 10
      src/Abc.Zebus/Dispatch/DispatchQueue.cs
  26. 6 6
      src/Abc.Zebus/Dispatch/MessageDispatcher.cs
  27. 4 4
      src/Abc.Zebus/Dispatch/Pipes/PipeManager.cs
  28. 5 5
      src/Abc.Zebus/Hosting/HostInitializerHelper.cs
  29. 8 8
      src/Abc.Zebus/Hosting/PeriodicActionHostInitializer.cs
  30. 9 6
      src/Abc.Zebus/Persistence/PersistentTransport.Phases.cs
  31. 16 15
      src/Abc.Zebus/Persistence/PersistentTransport.cs
  32. 3 3
      src/Abc.Zebus/Serialization/MessageSerializer.cs
  33. 6 6
      src/Abc.Zebus/Transport/ZmqInboundSocket.cs
  34. 11 11
      src/Abc.Zebus/Transport/ZmqOutboundSocket.cs
  35. 1 1
      src/Abc.Zebus/Transport/ZmqSocketOptions.cs
  36. 27 27
      src/Abc.Zebus/Transport/ZmqTransport.cs
  37. 5 5
      src/Abc.Zebus/Util/BackgroundThread.cs
  38. 70 0
      src/Abc.Zebus/ZebusLogManager.cs

+ 1 - 0
src/Abc.Zebus.Directory.Runner/Abc.Zebus.Directory.Runner.csproj

@@ -16,6 +16,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.12" />
     <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
   </ItemGroup>
 

+ 88 - 0
src/Abc.Zebus.Directory.Runner/Log4NetFactory.cs

@@ -0,0 +1,88 @@
+using System;
+using log4net;
+using Microsoft.Extensions.Logging;
+
+namespace Abc.Zebus.Directory.Runner
+{
+    public sealed class Log4NetFactory : ILoggerFactory
+    {
+        public void Dispose()
+        {
+        }
+
+        public ILogger CreateLogger(string categoryName)
+        {
+            return new Logger(LogManager.GetLogger(categoryName));
+        }
+
+        public void AddProvider(ILoggerProvider provider)
+        {
+        }
+
+        private class Logger : ILogger
+        {
+            private readonly ILog _log;
+
+            public Logger(ILog log)
+            {
+                _log = log;
+            }
+
+            public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
+            {
+                switch (logLevel)
+                {
+                    case LogLevel.Debug:
+                        if (_log.IsDebugEnabled)
+                            _log.Debug(formatter(state, exception), exception);
+                        break;
+
+                    case LogLevel.Information:
+                        if (_log.IsInfoEnabled)
+                            _log.Info(formatter(state, exception), exception);
+                        break;
+
+                    case LogLevel.Warning:
+                        if (_log.IsWarnEnabled)
+                            _log.Warn(formatter(state, exception), exception);
+                        break;
+
+                    case LogLevel.Error:
+                        if (_log.IsErrorEnabled)
+                            _log.Error(formatter(state, exception), exception);
+                        break;
+
+                    case LogLevel.Critical:
+                        if (_log.IsFatalEnabled)
+                            _log.Fatal(formatter(state, exception), exception);
+                        break;
+                }
+            }
+
+            public bool IsEnabled(LogLevel logLevel)
+            {
+                return logLevel switch
+                {
+                    LogLevel.Debug       => _log.IsDebugEnabled,
+                    LogLevel.Information => _log.IsInfoEnabled,
+                    LogLevel.Warning     => _log.IsWarnEnabled,
+                    LogLevel.Error       => _log.IsErrorEnabled,
+                    LogLevel.Critical    => _log.IsFatalEnabled,
+                    _                    => false
+                };
+            }
+
+            public IDisposable BeginScope<TState>(TState state)
+                => EmptyDisposable.Instance;
+        }
+
+        private class EmptyDisposable : IDisposable
+        {
+            public static EmptyDisposable Instance { get; } = new EmptyDisposable();
+
+            public void Dispose()
+            {
+            }
+        }
+    }
+}

+ 8 - 5
src/Abc.Zebus.Directory.Runner/Program.cs

@@ -14,6 +14,7 @@ using Abc.Zebus.Dispatch;
 using Abc.Zebus.Util;
 using log4net;
 using log4net.Config;
+using Microsoft.Extensions.Logging;
 using StructureMap;
 
 namespace Abc.Zebus.Directory.Runner
@@ -29,10 +30,12 @@ namespace Abc.Zebus.Directory.Runner
 
         private static readonly ManualResetEvent _cancelKeySignal = new ManualResetEvent(false);
 
-        private static readonly ILog _log = LogManager.GetLogger(typeof(Program));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(Program));
 
         public static void Main()
         {
+            ZebusLogManager.LoggerFactory = new Log4NetFactory();
+
             Console.CancelKeyPress += (sender, eventArgs) =>
             {
                 eventArgs.Cancel = true;
@@ -41,7 +44,7 @@ namespace Abc.Zebus.Directory.Runner
 
             XmlConfigurator.ConfigureAndWatch(LogManager.GetRepository(typeof(Program).Assembly), new FileInfo(PathUtil.InBaseDirectory("log4net.config")));
             var storageType = ConfigurationManager.AppSettings["Storage"]!;
-            _log.Info($"Starting in directory with storage type '{storageType}'");
+            _log.LogInformation($"Starting in directory with storage type '{storageType}'");
 
             var busFactory = new BusFactory();
             InjectDirectoryServiceSpecificConfiguration(busFactory, Enum.Parse<StorageType>(storageType));
@@ -54,15 +57,15 @@ namespace Abc.Zebus.Directory.Runner
 
             using (busFactory.CreateAndStartBus())
             {
-                _log.Info("Directory started");
+                _log.LogInformation("Directory started");
 
-                _log.Info("Starting dead peer detector");
+                _log.LogInformation("Starting dead peer detector");
                 var deadPeerDetector = busFactory.Container.GetInstance<IDeadPeerDetector>();
                 deadPeerDetector.Start();
 
                 _cancelKeySignal.WaitOne();
 
-                _log.Info("Stopping dead peer detector");
+                _log.LogInformation("Stopping dead peer detector");
                 deadPeerDetector.Stop();
             }
         }

+ 0 - 19
src/Abc.Zebus.Directory.Tests/Log4netConfigurator.cs

@@ -1,19 +0,0 @@
-using System;
-using System.IO;
-using log4net.Config;
-using log4net.Core;
-using NUnit.Framework;
-
-namespace Abc.Zebus.Directory.Tests
-{
-    [SetUpFixture]
-    public class Log4netConfigurator
-    {
-        [OneTimeSetUp]
-        public void SetUp()
-        {
-            var configurationFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config");
-            XmlConfigurator.Configure(LoggerManager.GetRepository(typeof(Log4netConfigurator).Assembly), new FileInfo(configurationFile));
-        }
-    }
-}

+ 7 - 7
src/Abc.Zebus.Directory/DeadPeerDetection/DeadPeerDetector.cs

@@ -8,14 +8,14 @@ using Abc.Zebus.Directory.Configuration;
 using Abc.Zebus.Directory.Storage;
 using Abc.Zebus.Util;
 using Abc.Zebus.Util.Extensions;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Directory.DeadPeerDetection
 {
     public class DeadPeerDetector : IDeadPeerDetector
     {
         private static readonly TimeSpan _commandTimeout = 5.Seconds();
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(DeadPeerDetector));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(DeadPeerDetector));
         private readonly Dictionary<PeerId, DeadPeerDetectorEntry> _peers = new Dictionary<PeerId, DeadPeerDetectorEntry>();
         private readonly IBus _bus;
         private readonly IPeerRepository _peerRepository;
@@ -145,7 +145,7 @@ namespace Abc.Zebus.Directory.DeadPeerDetection
         {
             _isRunning = false;
             if (_detectionThread != null && !_detectionThread.Join(2000))
-                _logger.Warn("Unable to terminate MainLoop");
+                _logger.LogWarning("Unable to terminate MainLoop");
         }
 
         void IDisposable.Dispose()
@@ -156,7 +156,7 @@ namespace Abc.Zebus.Directory.DeadPeerDetection
 
         private void MainLoop()
         {
-            _logger.InfoFormat("MainLoop started");
+            _logger.LogInformation("MainLoop started");
 
             var next = DateTime.UtcNow + _detectionPeriod;
             while (_isRunning)
@@ -180,12 +180,12 @@ namespace Abc.Zebus.Directory.DeadPeerDetection
                 }
             }
 
-            _logger.Info("MainLoop stopped");
+            _logger.LogInformation("MainLoop stopped");
         }
 
         private void OnError(Exception ex)
         {
-            _logger.ErrorFormat("MainLoop error: {0}", ex);
+            _logger.LogError(ex, "MainLoop error");
 
             try
             {
@@ -193,7 +193,7 @@ namespace Abc.Zebus.Directory.DeadPeerDetection
             }
             catch (Exception errorException)
             {
-                _logger.Error(errorException);
+                _logger.LogError(errorException, "Error in event handler");
             }
         }
     }

+ 6 - 6
src/Abc.Zebus.Directory/DeadPeerDetection/DeadPeerDetectorEntry.cs

@@ -2,13 +2,13 @@
 using System.Threading.Tasks;
 using Abc.Zebus.Directory.Configuration;
 using Abc.Zebus.Util;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Directory.DeadPeerDetection
 {
     public class DeadPeerDetectorEntry
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(DeadPeerDetectorEntry));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(DeadPeerDetectorEntry));
         private readonly IDirectoryConfiguration _configuration;
         private readonly IBus _bus;
         private readonly TaskScheduler _taskScheduler;
@@ -86,7 +86,7 @@ namespace Abc.Zebus.Directory.DeadPeerDetection
 
             var descriptor = Descriptor;
 
-            _logger.WarnFormat("Peer timeout, PeerId: {0}", descriptor.PeerId);
+            _logger.LogWarning($"Peer timeout, PeerId: {descriptor.PeerId}");
 
             PeerTimeoutDetected?.Invoke(this, timeoutTimestampUtc);
         }
@@ -105,7 +105,7 @@ namespace Abc.Zebus.Directory.DeadPeerDetection
             }
 
             if (wasDown)
-                _logger.InfoFormat("Peer reset, PeerId: {0}", Descriptor.PeerId);
+                _logger.LogInformation($"Peer reset, PeerId: {Descriptor.PeerId}");
         }
 
         public bool HasReachedTimeout()
@@ -136,13 +136,13 @@ namespace Abc.Zebus.Directory.DeadPeerDetection
         {
             if (pingTask.IsFaulted)
             {
-                _logger.DebugFormat("Ping failed, PeerId: {0}, Exception: {1}", Descriptor.PeerId, pingTask.Exception);
+                _logger.LogDebug(pingTask.Exception, $"Ping failed, PeerId: {Descriptor.PeerId}");
                 return;
             }
 
             if (!pingTask.Result.IsSuccess)
             {
-                _logger.DebugFormat("Ping failed, PeerId: {0}", Descriptor.PeerId);
+                _logger.LogDebug($"Ping failed, PeerId: {Descriptor.PeerId}");
                 return;
             }
 

+ 3 - 3
src/Abc.Zebus.Directory/Handlers/DirectoryCommandsHandler.cs

@@ -7,7 +7,7 @@ using Abc.Zebus.Directory.Configuration;
 using Abc.Zebus.Directory.Storage;
 using Abc.Zebus.Util;
 using Abc.Zebus.Util.Extensions;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Directory.Handlers
 {
@@ -20,7 +20,7 @@ namespace Abc.Zebus.Directory.Handlers
                                             IMessageHandler<MarkPeerAsNotRespondingCommand>,
                                             IMessageContextAware
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(DirectoryCommandsHandler));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(DirectoryCommandsHandler));
         private readonly HashSet<string> _blacklistedMachines;
         private readonly IBus _bus;
         private readonly IPeerRepository _peerRepository;
@@ -153,7 +153,7 @@ namespace Abc.Zebus.Directory.Handlers
         {
             if (_peerRepository.Get(message.PeerId) == null)
             {
-                _log.Warn("MarkPeerAsNotRespondingCommand ignored because the peer cannot be found");
+                _log.LogWarning("MarkPeerAsNotRespondingCommand ignored because the peer cannot be found");
                 return;
             }
             _peerRepository.SetPeerResponding(message.PeerId, false);

+ 5 - 5
src/Abc.Zebus.Persistence.CQL/Storage/CqlMessageReader.cs

@@ -6,13 +6,13 @@ using Abc.Zebus.Persistence.Messages;
 using Abc.Zebus.Persistence.Storage;
 using Cassandra;
 using Cassandra.Data.Linq;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.CQL.Storage
 {
     public class CqlMessageReader : IMessageReader
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(CqlMessageReader));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(CqlMessageReader));
 
         private readonly PersistenceCqlDataContext _dataContext;
         private readonly PeerState _peerState;
@@ -33,7 +33,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
         public IEnumerable<byte[]> GetUnackedMessages()
         {
             var oldestNonAckedMessageTimestampInTicks = _peerState.OldestNonAckedMessageTimestampInTicks;
-            _log.Info($"Reading messages for peer {_peerState.PeerId} from {oldestNonAckedMessageTimestampInTicks} ({new DateTime(oldestNonAckedMessageTimestampInTicks).ToLongTimeString()})");
+            _log.LogInformation($"Reading messages for peer {_peerState.PeerId} from {oldestNonAckedMessageTimestampInTicks} ({new DateTime(oldestNonAckedMessageTimestampInTicks).ToLongTimeString()})");
 
             var nonAckedMessagesInBuckets = BucketIdHelper.GetBucketsCollection(oldestNonAckedMessageTimestampInTicks)
                                                           .Select(b => GetNonAckedMessagesInBucket(oldestNonAckedMessageTimestampInTicks, b));
@@ -48,7 +48,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
                 }
             }
 
-            _log.Info($"{nonAckedMessageRead} non acked messages replayed for peer {_peerState.PeerId}");
+            _log.LogInformation($"{nonAckedMessageRead} non acked messages replayed for peer {_peerState.PeerId}");
         }
 
         private IEnumerable<byte[]> GetNonAckedMessagesInBucket(long oldestNonAckedMessageTimestampInTicks, long bucketId)
@@ -61,7 +61,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
 
         public void Dispose()
         {
-            _log.Info($"Reader for peer {_peerState.PeerId} disposed");
+            _log.LogInformation($"Reader for peer {_peerState.PeerId} disposed");
         }
     }
 }

+ 11 - 11
src/Abc.Zebus.Persistence.CQL/Storage/CqlStorage.cs

@@ -13,14 +13,14 @@ using Abc.Zebus.Persistence.Util;
 using Abc.Zebus.Util;
 using Cassandra;
 using Cassandra.Data.Linq;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.CQL.Storage
 {
     public class CqlStorage : ICqlStorage, IDisposable
     {
         private const int _maxParallelInsertTasks = 64;
-        private static readonly ILog _log = LogManager.GetLogger(typeof(CqlStorage));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(CqlStorage));
         private static readonly DateTime _unixOrigin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
 
         private readonly PersistenceCqlDataContext _dataContext;
@@ -70,13 +70,13 @@ namespace Abc.Zebus.Persistence.CQL.Storage
             {
                 var shouldInvestigatePeer = _configuration.PeerIdsToInvestigate != null && _configuration.PeerIdsToInvestigate.Contains(matcherEntry.PeerId.ToString());
                 if (shouldInvestigatePeer)
-                    _log.Info($"Storage requested for peer {matcherEntry.PeerId}, Type: {matcherEntry.Type}, Message Id: {matcherEntry.MessageId}");
+                    _log.LogInformation($"Storage requested for peer {matcherEntry.PeerId}, Type: {matcherEntry.Type}, Message Id: {matcherEntry.MessageId}");
 
                 var countDelta = matcherEntry.IsAck ? -1 : 1;
                 countByPeer[matcherEntry.PeerId] = countDelta + countByPeer.GetValueOrDefault(matcherEntry.PeerId);
 
                 if (shouldInvestigatePeer)
-                    _log.Info($"Count delta computed for peer {matcherEntry.PeerId}, will increment: {countDelta}");
+                    _log.LogInformation($"Count delta computed for peer {matcherEntry.PeerId}, will increment: {countDelta}");
             }
 
             var insertTasks = new List<Task>();
@@ -85,7 +85,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
             {
                 var gotSlot = remaining.Wait(TimeSpan.FromSeconds(10));
                 if (!gotSlot)
-                    _log.Warn("Could not get slot to insert in cassandra after 10 second.");
+                    _log.LogWarning("Could not get slot to insert in cassandra after 10 second.");
 
                 var messageDateTime = matcherEntry.MessageId.GetDateTimeForV2OrV3();
                 var rowTimestamp = matcherEntry.IsAck ? messageDateTime.AddTicks(10) : messageDateTime;
@@ -104,10 +104,10 @@ namespace Abc.Zebus.Persistence.CQL.Storage
                 {
                     var shouldInvestigatePeer = _configuration.PeerIdsToInvestigate != null && _configuration.PeerIdsToInvestigate.Contains(matcherEntry.PeerId.ToString());
                     if (shouldInvestigatePeer)
-                        _log.Info($"Storage done for peer {matcherEntry.PeerId}, Type: {matcherEntry.Type}, Message Id: {matcherEntry.MessageId}, TaskResult: {t.Status}");
+                        _log.LogInformation($"Storage done for peer {matcherEntry.PeerId}, Type: {matcherEntry.Type}, Message Id: {matcherEntry.MessageId}, TaskResult: {t.Status}");
 
                     if (t.IsFaulted)
-                        _log.Error(t.Exception);
+                        _log.LogError(t.Exception, "Error while inserting to Cassandra");
 
                     remaining.Release();
                 }, TaskContinuationOptions.ExecuteSynchronously);
@@ -129,16 +129,16 @@ namespace Abc.Zebus.Persistence.CQL.Storage
 
         public IMessageReader? CreateMessageReader(PeerId peerId)
         {
-            _log.Info($"Creating message reader for peer {peerId}");
+            _log.LogInformation($"Creating message reader for peer {peerId}");
             var peerState = _peerStateRepository.GetPeerStateFor(peerId);
             if (peerState == null)
             {
-                _log.Info($"PeerState for peer {peerId} does not exist, no reader can be created");
+                _log.LogInformation($"PeerState for peer {peerId} does not exist, no reader can be created");
                 return null;
             }
 
             var reader = new CqlMessageReader(_dataContext, peerState);
-            _log.Info("CqlMessageReader created");
+            _log.LogInformation("CqlMessageReader created");
 
             return reader;
         }
@@ -155,7 +155,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
 
             if (newOldestUnackedTimestampMinusSafetyOffset < peer.OldestNonAckedMessageTimestampInTicks)
             {
-                _log.Warn($"OldestNonAckedMessageTimestampInTicks moved backward for {peer.PeerId}, Value: {new DateTime(newOldestUnackedTimestampMinusSafetyOffset)}");
+                _log.LogWarning($"OldestNonAckedMessageTimestampInTicks moved backward for {peer.PeerId}, Value: {new DateTime(newOldestUnackedTimestampMinusSafetyOffset)}");
             }
             else
             {

+ 8 - 8
src/Abc.Zebus.Persistence.CQL/Storage/PeerStateRepository.cs

@@ -8,13 +8,13 @@ using Abc.Zebus.Persistence.Util;
 using Abc.Zebus.Util;
 using Cassandra;
 using Cassandra.Data.Linq;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.CQL.Storage
 {
     public class PeerStateRepository
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(PeerStateRepository));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(PeerStateRepository));
 
         private readonly PersistenceCqlDataContext _dataContext;
         private readonly ConcurrentDictionary<PeerId, PeerState> _statesByPeerId = new ConcurrentDictionary<PeerId, PeerState>();
@@ -26,7 +26,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
 
         public void Initialize()
         {
-            _log.Info("Initializing PeerStateRepository");
+            _log.LogInformation("Initializing PeerStateRepository");
 
             foreach (var cassandraPeerState in _dataContext.PeerStates.Execute())
             {
@@ -34,7 +34,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
                 _statesByPeerId[peerState.PeerId] = peerState;
             }
 
-            _log.Info($"PeerStateRepository initialized with {_statesByPeerId.Count} states.");
+            _log.LogInformation($"PeerStateRepository initialized with {_statesByPeerId.Count} states.");
         }
 
         public PeerState? GetPeerStateFor(PeerId peerId)
@@ -47,7 +47,7 @@ namespace Abc.Zebus.Persistence.CQL.Storage
             var peerState = _statesByPeerId.AddOrUpdate(peerId,
                                                           p =>
                                                           {
-                                                              _log.Info($"Created new state for peer {p}");
+                                                              _log.LogInformation($"Created new state for peer {p}");
                                                               return new PeerState(p, delta);
                                                           },
                                                           (id, state) => state.WithNonAckedMessageCountDelta(delta));
@@ -57,18 +57,18 @@ namespace Abc.Zebus.Persistence.CQL.Storage
 
         public Task RemovePeer(PeerId peerId)
         {
-            _log.Info($"Purge queue for peer {peerId} requested");
+            _log.LogInformation($"Purge queue for peer {peerId} requested");
 
             if (!_statesByPeerId.TryRemove(peerId, out var state))
             {
-                _log.Info($"Peer to purge not found ({peerId})");
+                _log.LogInformation($"Peer to purge not found ({peerId})");
                 return Task.CompletedTask;
             }
 
             state.MarkAsRemoved();
 
             var removeTask = Task.WhenAll(DeletePeerState(peerId), RemovePersistentMessages(peerId));
-            removeTask.ContinueWith(t => _log.Info($"Queue for peer {peerId} purged"));
+            removeTask.ContinueWith(t => _log.LogInformation($"Queue for peer {peerId} purged"));
 
             return removeTask;
         }

+ 2 - 0
src/Abc.Zebus.Persistence.Runner/Abc.Zebus.Persistence.Runner.csproj

@@ -13,6 +13,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.12" />
     <PackageReference Include="FluentDateTime" Version="2.0.0" />
     <PackageReference Include="RocksDbNative" Version="6.2.2" />
     <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
@@ -22,6 +23,7 @@
     <None Update="log4net.config">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
+    <Compile Include="..\Abc.Zebus.Directory.Runner\Log4NetFactory.cs" />
   </ItemGroup>
 
 </Project>

+ 13 - 8
src/Abc.Zebus.Persistence.Runner/Program.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Threading;
 using Abc.Zebus.Core;
 using Abc.Zebus.Directory;
+using Abc.Zebus.Directory.Runner;
 using Abc.Zebus.Dispatch;
 using Abc.Zebus.Monitoring;
 using Abc.Zebus.Persistence.CQL;
@@ -20,7 +21,9 @@ using Abc.Zebus.Transport;
 using log4net;
 using log4net.Config;
 using log4net.Core;
+using Microsoft.Extensions.Logging;
 using StructureMap;
+using ILogger = Microsoft.Extensions.Logging.ILogger;
 
 #nullable enable
 
@@ -29,10 +32,12 @@ namespace Abc.Zebus.Persistence.Runner
     internal class Program
     {
         private static readonly ManualResetEvent _cancelKeySignal = new ManualResetEvent(false);
-        private static readonly ILog _log = LogManager.GetLogger(typeof(Program));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(Program));
 
         public static void Main()
         {
+            ZebusLogManager.LoggerFactory = new Log4NetFactory();
+
             Console.CancelKeyPress += (sender, eventArgs) =>
             {
                 eventArgs.Cancel = true;
@@ -40,7 +45,7 @@ namespace Abc.Zebus.Persistence.Runner
             };
 
             XmlConfigurator.ConfigureAndWatch(LoggerManager.GetRepository(typeof(Program).Assembly), new FileInfo(InBaseDirectory("log4net.config")));
-            _log.Info("Starting persistence");
+            _log.LogInformation("Starting persistence");
 
             var appSettingsConfiguration = new AppSettingsConfiguration();
             var useCassandraStorage = ConfigurationManager.AppSettings["PersistenceStorage"] == "Cassandra";
@@ -53,7 +58,7 @@ namespace Abc.Zebus.Persistence.Runner
 
             using (busFactory.CreateAndStartBus())
             {
-                _log.Info("Starting initialisers");
+                _log.LogInformation("Starting initialisers");
                 var inMemoryMessageMatcherInitializer = busFactory.Container.GetInstance<InMemoryMessageMatcherInitializer>();
                 inMemoryMessageMatcherInitializer.BeforeStart();
 
@@ -64,11 +69,11 @@ namespace Abc.Zebus.Persistence.Runner
                     oldestNonAckedMessageUpdaterPeriodicAction.AfterStart();
                 }
 
-                _log.Info("Persistence started");
+                _log.LogInformation("Persistence started");
 
                 _cancelKeySignal.WaitOne();
 
-                _log.Info("Stopping initialisers");
+                _log.LogInformation("Stopping initialisers");
                 oldestNonAckedMessageUpdaterPeriodicAction?.BeforeStop();
 
                 var messageReplayerInitializer = busFactory.Container.GetInstance<MessageReplayerInitializer>();
@@ -76,7 +81,7 @@ namespace Abc.Zebus.Persistence.Runner
 
                 inMemoryMessageMatcherInitializer.AfterStop();
 
-                _log.Info("Persistence stopped");
+                _log.LogInformation("Persistence stopped");
             }
         }
 
@@ -93,12 +98,12 @@ namespace Abc.Zebus.Persistence.Runner
 
                 if (useCassandraStorage)
                 {
-                    _log.Info("Using Cassandra storage implementation");
+                    _log.LogInformation("Using Cassandra storage implementation");
                     c.ForSingletonOf<IStorage>().Use<CqlStorage>();
                 }
                 else
                 {
-                    _log.Info("Using RocksDB storage implementation");
+                    _log.LogInformation("Using RocksDB storage implementation");
                     c.ForSingletonOf<IStorage>().Use<RocksDbStorage>();
                 }
 

+ 3 - 3
src/Abc.Zebus.Persistence/Handlers/MessageHandledHandler.cs

@@ -1,12 +1,12 @@
 using System.Linq;
 using Abc.Zebus.Persistence.Matching;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.Handlers
 {
     public class MessageHandledHandler : IMessageHandler<MessageHandled>, IMessageContextAware
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(MessageHandledHandler));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(MessageHandledHandler));
 
         private readonly IMessageReplayerRepository _messageReplayerRepository;
         private readonly IInMemoryMessageMatcher _inMemoryMessageMatcher;
@@ -24,7 +24,7 @@ namespace Abc.Zebus.Persistence.Handlers
         public void Handle(MessageHandled message)
         {
             if (_configuration.PeerIdsToInvestigate != null && _configuration.PeerIdsToInvestigate.Contains(Context!.SenderId.ToString()))
-                _log.Info($"Ack received from peer {Context.SenderId}. MessageId: {message.MessageId}");
+                _log.LogInformation($"Ack received from peer {Context.SenderId}. MessageId: {message.MessageId}");
 
             _inMemoryMessageMatcher.EnqueueAck(Context!.SenderId, message.MessageId);
 

+ 5 - 5
src/Abc.Zebus.Persistence/Handlers/PersistMessageCommandHandler.cs

@@ -1,13 +1,13 @@
 using System.Linq;
 using Abc.Zebus.Persistence.Matching;
 using Abc.Zebus.Persistence.Storage;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.Handlers
 {
     public class PersistMessageCommandHandler : IMessageHandler<PersistMessageCommand>
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(PersistMessageCommandHandler));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(PersistMessageCommandHandler));
 
         private readonly TransportMessageSerializer _serializer = new TransportMessageSerializer();
         private readonly IMessageReplayerRepository _messageReplayerRepository;
@@ -29,7 +29,7 @@ namespace Abc.Zebus.Persistence.Handlers
             var transportMessage = message.TransportMessage;
             if (string.IsNullOrEmpty(transportMessage.MessageTypeId.FullName))
             {
-                _log.Error($"Message received with empty TypeId, MessageId: {transportMessage.Id}, SenderId: {transportMessage.Originator.SenderId}");
+                _log.LogError($"Message received with empty TypeId, MessageId: {transportMessage.Id}, SenderId: {transportMessage.Originator.SenderId}");
                 return;
             }
 
@@ -38,12 +38,12 @@ namespace Abc.Zebus.Persistence.Handlers
             {
                 if (string.IsNullOrEmpty(target.ToString()))
                 {
-                    _log.Error($"Message received with empty target, MessageId: {transportMessage.Id}, SenderId: {transportMessage.Originator.SenderId}");
+                    _log.LogError($"Message received with empty target, MessageId: {transportMessage.Id}, SenderId: {transportMessage.Originator.SenderId}");
                     continue;
                 }
 
                 if (_configuration.PeerIdsToInvestigate != null && _configuration.PeerIdsToInvestigate.Contains(target.ToString()))
-                    _log.Info($"Message received for peer {target}, MessageId: {transportMessage.Id}, MessageType: {transportMessage.MessageTypeId}");
+                    _log.LogInformation($"Message received for peer {target}, MessageId: {transportMessage.Id}, MessageType: {transportMessage.MessageTypeId}");
 
                 _messageReplayerRepository.GetActiveMessageReplayer(target)?.AddLiveMessage(transportMessage);
                 _inMemoryMessageMatcher.EnqueueMessage(target, transportMessage.Id, transportMessage.MessageTypeId, transportMessageBytes);

+ 3 - 3
src/Abc.Zebus.Persistence/Initialization/MessageReplayerInitializer.cs

@@ -3,13 +3,13 @@ using System.Diagnostics;
 using System.Threading;
 using Abc.Zebus.Hosting;
 using Abc.Zebus.Util;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.Initialization
 {
     public class MessageReplayerInitializer : HostInitializer
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(MessageReplayerInitializer));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(MessageReplayerInitializer));
         private readonly IMessageReplayerRepository _messageReplayerRepository;
         private readonly TimeSpan _waitTimeout;
 
@@ -30,7 +30,7 @@ namespace Abc.Zebus.Persistence.Initialization
                 Thread.Sleep(200);
 
             if (_messageReplayerRepository.HasActiveMessageReplayers())
-                _logger.WarnFormat("Stopping with active message replayers");
+                _logger.LogWarning("Stopping with active message replayers");
         }
     }
 }

+ 8 - 8
src/Abc.Zebus.Persistence/Matching/InMemoryMessageMatcher.cs

@@ -8,13 +8,13 @@ using Abc.Zebus.Monitoring;
 using Abc.Zebus.Persistence.Storage;
 using Abc.Zebus.Persistence.Util;
 using Abc.Zebus.Util;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.Matching
 {
     public class InMemoryMessageMatcher : IInMemoryMessageMatcher, IProvideQueueLength
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(InMemoryMessageMatcher));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(InMemoryMessageMatcher));
         private readonly BlockingCollection<MatcherEntry> _persistenceQueue = new BlockingCollection<MatcherEntry>();
         private readonly ConcurrentSet<MessageKey> _ackMessageKeys = new ConcurrentSet<MessageKey>();
         private readonly IPersistenceConfiguration _persistenceConfiguration;
@@ -40,7 +40,7 @@ namespace Abc.Zebus.Persistence.Matching
                 _workerThread.Start(signal);
                 signal.Wait();
             }
-            _logger.Info("InMemoryMessageMatcher started");
+            _logger.LogInformation("InMemoryMessageMatcher started");
         }
 
         private void ThreadProc(object? state)
@@ -108,7 +108,7 @@ namespace Abc.Zebus.Persistence.Matching
             }
             catch (Exception ex)
             {
-                _logger.Error("Unexpected error happened", ex);
+                _logger.LogError(ex, "Unexpected error happened");
                 _bus.Publish(new CustomProcessingFailed(GetType().FullName!, ex.ToString(), SystemDateTime.UtcNow));
             }
             finally
@@ -144,7 +144,7 @@ namespace Abc.Zebus.Persistence.Matching
             if (entriesToInsert.Any())
             {
                 if (!_storage.Write(entriesToInsert).Wait(30.Seconds()))
-                    _logger.WarnFormat("Unable to Write {0} entries in 30s", entriesToInsert.Count);
+                    _logger.LogWarning($"Unable to Write {entriesToInsert.Count} entries in 30s");
             }
 
             foreach (var entry in batch.Where(x => x.IsEventWaitHandle))
@@ -159,14 +159,14 @@ namespace Abc.Zebus.Persistence.Matching
         {
             if (_persistenceQueue.IsAddingCompleted)
             {
-                _logger.InfoFormat("InMemoryMessageMatcher already stopped");
+                _logger.LogInformation("InMemoryMessageMatcher already stopped");
                 return;
             }
 
-            _logger.InfoFormat("Stopping InMemoryMessageMatcher, {0} messages on queue to persist", _persistenceQueue.Count);
+            _logger.LogInformation($"Stopping InMemoryMessageMatcher, {_persistenceQueue.Count} messages on queue to persist");
             _persistenceQueue.CompleteAdding();
             _workerThread.Join();
-            _logger.Info("InMemoryMessageMatcher stopped");
+            _logger.LogInformation("InMemoryMessageMatcher stopped");
         }
 
         public void EnqueueMessage(PeerId peerId, MessageId messageId, MessageTypeId messageTypeId, byte[] bytes)

+ 16 - 16
src/Abc.Zebus.Persistence/MessageReplayer.cs

@@ -11,13 +11,13 @@ using Abc.Zebus.Persistence.Util;
 using Abc.Zebus.Serialization;
 using Abc.Zebus.Transport;
 using Abc.Zebus.Util;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence
 {
     public class MessageReplayer : IMessageReplayer
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(MessageReplayer));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(MessageReplayer));
         private readonly BlockingCollection<TransportMessage> _liveMessages = new BlockingCollection<TransportMessage>();
         private readonly ConcurrentSet<MessageId> _unackedIds = new ConcurrentSet<MessageId>();
         private readonly IPersistenceConfiguration _persistenceConfiguration;
@@ -86,7 +86,7 @@ namespace Abc.Zebus.Persistence
             if (WaitForCompletion(5.Seconds()))
                 return true;
 
-            _logger.WarnFormat("Unable to cancel replayer, PeerId: {0}", _peer.Id);
+            _logger.LogWarning($"Unable to cancel replayer, PeerId: {_peer.Id}");
             return false;
         }
 
@@ -97,28 +97,28 @@ namespace Abc.Zebus.Persistence
 
         private void RunProc(ManualResetEvent signal)
         {
-            _logger.InfoFormat("Replay started, PeerId: {0}", _peer.Id);
+            _logger.LogInformation($"Replay started, PeerId: {_peer.Id}");
 
             signal.WaitOne();
             signal.Dispose();
 
-            _logger.InfoFormat("BatchPersister flushed, PeerId: {0}", _peer.Id);
+            _logger.LogInformation($"BatchPersister flushed, PeerId: {_peer.Id}");
 
             _stopwatch.Start();
             try
             {
                 Run(_cancellationTokenSource!.Token);
                 if (_cancellationTokenSource!.IsCancellationRequested)
-                    _logger.WarnFormat("Replay cancelled, PeerId: {0}", _peer.Id);
+                    _logger.LogWarning("Replay cancelled, PeerId: {_peer.Id}");
             }
             catch (Exception ex)
             {
-                _logger.ErrorFormat("Replay failed, PeerId: {0}, Exception: {1}", _peer.Id, ex);
+                _logger.LogError(ex, $"Replay failed, PeerId: {_peer.Id}");
             }
 
             _stopwatch.Stop();
 
-            _logger.InfoFormat("Replay stopped, PeerId: {0}. It ran for {1}", _peer.Id, _stopwatch.Elapsed);
+            _logger.LogInformation($"Replay stopped, PeerId: {_peer.Id}. It ran for {_stopwatch.Elapsed}");
 
             Stopped?.Invoke();
         }
@@ -129,7 +129,7 @@ namespace Abc.Zebus.Persistence
 
             var replayDuration = MeasureDuration();
             var totalReplayedCount = ReplayUnackedMessages(cancellationToken);
-            _logger.Info($"Replay phase ended for {_peer.Id}. {totalReplayedCount} messages replayed in {replayDuration.Value} ({totalReplayedCount / replayDuration.Value.TotalSeconds} msg/s)");
+            _logger.LogInformation($"Replay phase ended for {_peer.Id}. {totalReplayedCount} messages replayed in {replayDuration.Value} ({totalReplayedCount / replayDuration.Value.TotalSeconds} msg/s)");
 
             if (cancellationToken.IsCancellationRequested)
                 return;
@@ -138,7 +138,7 @@ namespace Abc.Zebus.Persistence
 
             var safetyDuration = MeasureDuration();
             ForwardLiveMessages(cancellationToken);
-            _logger.Info($"Safety phase ended for {_peer.Id} ({safetyDuration.Value})");
+            _logger.LogInformation($"Safety phase ended for {_peer.Id} ({safetyDuration.Value})");
             if (cancellationToken.IsCancellationRequested)
                 return;
 
@@ -168,13 +168,13 @@ namespace Abc.Zebus.Persistence
 
                     totalMessageCount += messageSentCount;
 
-                    _logger.Info($"Read and send for last batch of {messageSentCount} msgs for {_peer.Id} took {readAndSendDuration.Value}. ({messageSentCount / readAndSendDuration.Value.TotalSeconds} msg/s)");
+                    _logger.LogInformation($"Read and send for last batch of {messageSentCount} msgs for {_peer.Id} took {readAndSendDuration.Value}. ({messageSentCount / readAndSendDuration.Value.TotalSeconds} msg/s)");
                     WaitForAcks(cancellationToken);
-                    _logger.Info($"Last batch for {_peer.Id} took {batchDuration.Value} to be totally replayed ({messageSentCount / batchDuration.Value.TotalSeconds} msg/s)");
+                    _logger.LogInformation($"Last batch for {_peer.Id} took {batchDuration.Value} to be totally replayed ({messageSentCount / batchDuration.Value.TotalSeconds} msg/s)");
                     _reporter.AddReplaySpeedReport(messageSentCount, readAndSendDuration.Value.TotalSeconds, batchDuration.Value.TotalSeconds);
                 }
 
-                _logger.Info($"Replay finished for peer {_peer.Id}. Disposing the reader");
+                _logger.LogInformation($"Replay finished for peer {_peer.Id}. Disposing the reader");
                 return totalMessageCount;
             }
         }
@@ -187,7 +187,7 @@ namespace Abc.Zebus.Persistence
                 return;
 
             var expectedAckCount = Math.Max(0, _unackedIds.Count - UnackedMessageCountThatReleasesNextBatch);
-            _logger.Info($"Waiting for {expectedAckCount} ack(s) before proceeding to next batch for {_peer.Id}");
+            _logger.LogInformation($"Waiting for {expectedAckCount} ack(s) before proceeding to next batch for {_peer.Id}");
 
             var waitDuration = MeasureDuration();
             while (_unackedIds.Count > UnackedMessageCountThatReleasesNextBatch)
@@ -198,8 +198,8 @@ namespace Abc.Zebus.Persistence
                 Thread.Sleep(100);
             }
 
-            _logger.Info($"Batch acked in {waitDuration.Value} for peer {_peer.Id} ({expectedAckCount / waitDuration.Value.TotalSeconds} msg/s)");
-            _logger.Info($"Proceeding with next batch for {_peer.Id}");
+            _logger.LogInformation($"Batch acked in {waitDuration.Value} for peer {_peer.Id} ({expectedAckCount / waitDuration.Value.TotalSeconds} msg/s)");
+            _logger.LogInformation($"Proceeding with next batch for {_peer.Id}");
         }
 
         private void ReplayMessage(TransportMessage unackedMessage)

+ 8 - 8
src/Abc.Zebus.Persistence/Transport/QueueingTransport.cs

@@ -7,13 +7,13 @@ using System.Threading;
 using Abc.Zebus.Directory;
 using Abc.Zebus.Transport;
 using Abc.Zebus.Util;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence.Transport
 {
     public class QueueingTransport : ITransport
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(QueueingTransport));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(QueueingTransport));
         private readonly BlockingCollection<TransportMessage> _pendingReceives = new BlockingCollection<TransportMessage>();
         private readonly ITransport _transport;
         private readonly IPeerDirectory _peerDirectory;
@@ -65,7 +65,7 @@ namespace Abc.Zebus.Persistence.Transport
         {
             if (transportMessage.MessageTypeId == MessageTypeId.PersistenceStoppingAck)
             {
-                _logger.InfoFormat("Received PersistenceStoppingAck from {0}", transportMessage.Originator.SenderId);
+                _logger.LogInformation($"Received PersistenceStoppingAck from {transportMessage.Originator.SenderId}");
                 _ackCountdown?.Signal();
                 return;
             }
@@ -93,21 +93,21 @@ namespace Abc.Zebus.Persistence.Transport
 
             _transport.Send(new TransportMessage(MessageTypeId.PersistenceStopping, new MemoryStream(), PeerId, InboundEndPoint), targets, new SendContext());
 
-            _logger.InfoFormat("Waiting for {0} persistence stopping acknowledgments within the next {1} seconds", targets.Count, _configuration.QueuingTransportStopTimeout.TotalSeconds);
+            _logger.LogInformation($"Waiting for {targets.Count} persistence stopping acknowledgments within the next {_configuration.QueuingTransportStopTimeout.TotalSeconds} seconds");
             var success = _ackCountdown.Wait(_configuration.QueuingTransportStopTimeout);
             if (!success)
-                _logger.WarnFormat("{0} acknowledgments not received", _ackCountdown.CurrentCount);
+                _logger.LogWarning($"{_ackCountdown.CurrentCount} acknowledgments not received");
 
             var newTargetsCount = _peerDirectory.GetPeerDescriptors().Count(desc => desc.PeerId != _transport.PeerId);
             if (newTargetsCount > targets.Count)
-                _logger.WarnFormat("The peer count on the bus raised from {0} to {1} during the graceful shutdown of the persistence, some messages might have been lost.", targets.Count, newTargetsCount);
+                _logger.LogWarning($"The peer count on the bus raised from {targets.Count} to {newTargetsCount} during the graceful shutdown of the persistence, some messages might have been lost.");
 
-            _logger.InfoFormat("Stopping ZmqTransport");
+            _logger.LogInformation("Stopping ZmqTransport");
             _transport.Stop();
 
             _pendingReceives.CompleteAdding();
             if (_receptionThread != null && !_receptionThread.Join(30.Seconds()))
-                _logger.WarnFormat("Unable to stop reception thread");
+                _logger.LogWarning("Unable to stop reception thread");
         }
 
         public void Send(TransportMessage message, IEnumerable<Peer> peerIds, SendContext sendContext)

+ 0 - 33
src/Abc.Zebus.Tests/Log4netConfigurator.cs

@@ -1,33 +0,0 @@
-using System;
-using System.IO;
-using JetBrains.Annotations;
-using log4net.Appender;
-using log4net.Config;
-using log4net.Core;
-using NUnit.Framework;
-
-namespace Abc.Zebus.Tests
-{
-    [SetUpFixture]
-    public class Log4netConfigurator
-    {
-        [OneTimeSetUp]
-        public void Setup()
-        {
-            var configurationFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config");
-            XmlConfigurator.Configure(LoggerManager.GetRepository(typeof(Log4netConfigurator).Assembly), new FileInfo(configurationFile));
-        }
-
-        [UsedImplicitly]
-        public class Appender : ConsoleAppender
-        {
-            protected override void Append(LoggingEvent loggingEvent)
-            {
-                lock (this)
-                {
-                    base.Append(loggingEvent);
-                }
-            }
-        }
-    }
-}

+ 0 - 2
src/Abc.Zebus.Tests/Program.cs

@@ -16,8 +16,6 @@ namespace Abc.Zebus.Tests
     {
         public static void MainLol(string[] args)
         {
-            new Log4netConfigurator().Setup();
-
             if (args.FirstOrDefault() == "/receive")
             {
                 RunReceiver();

+ 1 - 1
src/Abc.Zebus/Abc.Zebus.csproj

@@ -10,7 +10,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="log4net" Version="2.0.12" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
     <PackageReference Include="protobuf-net" Version="3.0.73" />
     <PackageReference Include="structuremap" Version="4.7.1" />

+ 13 - 13
src/Abc.Zebus/Core/Bus.cs

@@ -14,7 +14,7 @@ using Abc.Zebus.Subscriptions;
 using Abc.Zebus.Transport;
 using Abc.Zebus.Util;
 using Abc.Zebus.Util.Extensions;
-using log4net;
+using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 
 namespace Abc.Zebus.Core
@@ -22,7 +22,7 @@ namespace Abc.Zebus.Core
     public class Bus : IInternalBus, IMessageDispatchFactory
     {
         private static readonly BusMessageLogger _messageLogger = new(typeof(Bus));
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(Bus));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(Bus));
 
         private readonly ConcurrentDictionary<MessageId, TaskCompletionSource<CommandResult>> _messageIdToTaskCompletionSources = new();
         private readonly UniqueTimestampProvider _deserializationFailureTimestampProvider = new();
@@ -105,25 +105,25 @@ namespace Abc.Zebus.Core
             var registered = false;
             try
             {
-                _logger.DebugFormat("Loading invokers...");
+                _logger.LogDebug("Loading invokers...");
                 _messageDispatcher.LoadMessageHandlerInvokers();
 
-                _logger.DebugFormat("Performing startup subscribe...");
+                _logger.LogDebug("Performing startup subscribe...");
                 PerformStartupSubscribe();
 
-                _logger.DebugFormat("Starting transport...");
+                _logger.LogDebug("Starting transport...");
                 _transport.Start();
 
                 Status = BusStatus.Started;
 
-                _logger.DebugFormat("Registering on directory...");
+                _logger.LogDebug("Registering on directory...");
                 var self = new Peer(PeerId, EndPoint);
                 _directory.RegisterAsync(this, self, GetSubscriptions()).Wait();
                 registered = true;
 
                 _transport.OnRegistered();
 
-                _logger.DebugFormat("Starting message dispatcher...");
+                _logger.LogDebug("Starting message dispatcher...");
                 _messageDispatcher.Start();
             }
             catch
@@ -215,7 +215,7 @@ namespace Abc.Zebus.Core
                 }
                 catch (Exception ex)
                 {
-                    _logger.Error(ex);
+                    _logger.LogError(ex, "Error during stop");
                 }
             }
 
@@ -510,7 +510,7 @@ namespace Abc.Zebus.Core
             }
             catch (Exception ex)
             {
-                _logger.Error(ex);
+                _logger.LogError(ex, "Error waiting for pending unsubscription");
             }
         }
 
@@ -591,7 +591,7 @@ namespace Abc.Zebus.Core
             }
             catch (Exception ex)
             {
-                _logger.Error(ex);
+                _logger.LogError(ex, "Error processing pending unsubscription");
 
                 lock (_subscriptions)
                 {
@@ -669,7 +669,7 @@ namespace Abc.Zebus.Core
             var dispatch = CreateMessageDispatch(transportMessage, synchronous);
             if (dispatch == null)
             {
-                _logger.WarnFormat("Received a remote message that could not be deserialized: {0} from {1}", transportMessage.MessageTypeId.FullName, transportMessage.Originator.SenderId);
+                _logger.LogWarning($"Received a remote message that could not be deserialized: {transportMessage.MessageTypeId.FullName} from {transportMessage.Originator.SenderId}");
                 _transport.AckMessage(transportMessage);
                 return;
             }
@@ -733,7 +733,7 @@ namespace Abc.Zebus.Core
         private void HandleDispatchErrorsForUnserializableMessage(IMessage message, Exception serializationException, string dispatchErrorMessage)
         {
             var messageTypeName = message.GetType().FullName;
-            _logger.Error($"Unable to serialize message {messageTypeName}. Error: {serializationException}");
+            _logger.LogError(serializationException, $"Unable to serialize message {messageTypeName}");
 
             if (!_configuration.IsErrorPublicationEnabled || !IsRunning)
                 return;
@@ -844,7 +844,7 @@ namespace Abc.Zebus.Core
         {
             var dumpLocation = DumpMessageOnDisk(messageTypeId, messageStream);
             var errorMessage = $"Unable to deserialize message {messageTypeId.FullName}. Originator: {originator.SenderId}. Message dumped at: {dumpLocation}\r\n{exception}";
-            _logger.Error(errorMessage);
+            _logger.LogError(errorMessage);
 
             if (!_configuration.IsErrorPublicationEnabled || !IsRunning)
                 return;

+ 19 - 20
src/Abc.Zebus/Core/BusMessageLogger.cs

@@ -6,14 +6,14 @@ using System.Reflection;
 using Abc.Zebus.Scan;
 using Abc.Zebus.Transport;
 using Abc.Zebus.Util.Extensions;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Core
 {
     public class BusMessageLogger
     {
         private static readonly ConcurrentDictionary<Type, MessageTypeLogHelper> _logHelpers = new ConcurrentDictionary<Type, MessageTypeLogHelper>();
-        private readonly ILog _logger;
+        private readonly ILogger _logger;
         private bool _logDebugEnabled;
         private bool _logInfoEnabled;
 
@@ -24,23 +24,22 @@ namespace Abc.Zebus.Core
 
         public BusMessageLogger(string loggerFullName)
         {
-            _logger = LogManager.GetLogger(typeof(BusMessageLogger).Assembly, loggerFullName);
+            _logger = ZebusLogManager.GetLogger(loggerFullName);
 
-            // Instances of BusMessageLogger are static, no need to unsubscribe from these events
-            _logger.Logger.Repository.ConfigurationChanged += (sender, args) => UpdateLogConfig();
-            _logger.Logger.Repository.ConfigurationReset += (sender, args) => UpdateLogConfig();
+            // Instances of BusMessageLogger are static, no need to unsubscribe from this event
+            ZebusLogManager.LoggerFactoryChanged += UpdateLogConfig;
 
             UpdateLogConfig();
 
             void UpdateLogConfig()
             {
-                _logDebugEnabled = _logger.IsDebugEnabled;
-                _logInfoEnabled = _logger.IsInfoEnabled;
+                _logDebugEnabled = _logger.IsEnabled(LogLevel.Debug);
+                _logInfoEnabled = _logger.IsEnabled(LogLevel.Information);
             }
         }
 
         public bool IsInfoEnabled(IMessage message)
-            => _logInfoEnabled && GetLogHelper(message).Logger.IsInfoEnabled;
+            => _logInfoEnabled && GetLogHelper(message).Logger.IsEnabled(LogLevel.Information);
 
         public void LogHandleMessage(IList<IMessage> messages, string? dispatchQueueName, MessageId? messageId)
         {
@@ -53,7 +52,7 @@ namespace Abc.Zebus.Core
             var dispatchQueueNameText = HasCustomDispatchQueue() ? $" [{dispatchQueueName}]" : "";
             var batchText = messages.Count > 1 ? $" Count: {messages.Count}" : "";
 
-            _logger.Info($"HANDLE{dispatchQueueNameText}: {messageText}{batchText} [{messageId}]");
+            _logger.LogInformation($"HANDLE{dispatchQueueNameText}: {messageText}{batchText} [{messageId}]");
 
             bool HasCustomDispatchQueue() => !string.IsNullOrEmpty(dispatchQueueName) && dispatchQueueName != DispatchQueueNameScanner.DefaultQueueName;
         }
@@ -63,7 +62,7 @@ namespace Abc.Zebus.Core
             if (!TryGetLogHelperForDebug(messageAck, out _))
                 return;
 
-            _logger.Debug($"RECV ACK {{{messageAck}}}");
+            _logger.LogDebug($"RECV ACK {{{messageAck}}}");
         }
 
         public void LogReceiveMessageLocal(IMessage message)
@@ -72,7 +71,7 @@ namespace Abc.Zebus.Core
                 return;
 
             var messageText = logHelper.GetMessageText(message);
-            _logger.Debug($"RECV local: {messageText}");
+            _logger.LogDebug($"RECV local: {messageText}");
         }
 
         public void LogReceiveMessageRemote(IMessage message, TransportMessage transportMessage)
@@ -81,7 +80,7 @@ namespace Abc.Zebus.Core
                 return;
 
             var messageText = logHelper.GetMessageText(message);
-            _logger.Debug($"RECV remote: {messageText} from {transportMessage.SenderId} ({transportMessage.Content?.Length} bytes). [{transportMessage.Id}]");
+            _logger.LogDebug($"RECV remote: {messageText} from {transportMessage.SenderId} ({transportMessage.Content?.Length} bytes). [{transportMessage.Id}]");
         }
 
         public void LogSendMessage(IMessage message, IList<Peer> peers)
@@ -92,7 +91,7 @@ namespace Abc.Zebus.Core
             var messageText = logHelper.GetMessageText(message);
             var targetPeersText = GetTargetPeersText(peers);
 
-            _logger.Info($"SEND: {messageText} to {targetPeersText}");
+            _logger.LogInformation($"SEND: {messageText} to {targetPeersText}");
         }
 
         public void LogSendMessage(IMessage message, IList<Peer> peers, TransportMessage transportMessage)
@@ -103,7 +102,7 @@ namespace Abc.Zebus.Core
             var messageText = logHelper.GetMessageText(message);
             var targetPeersText = GetTargetPeersText(peers);
 
-            _logger.Info($"SEND: {messageText} to {targetPeersText} ({transportMessage.Content?.Length} bytes) [{transportMessage.Id}]");
+            _logger.LogInformation($"SEND: {messageText} to {targetPeersText} ({transportMessage.Content?.Length} bytes) [{transportMessage.Id}]");
         }
 
         private static string GetTargetPeersText(IList<Peer> peers)
@@ -133,7 +132,7 @@ namespace Abc.Zebus.Core
 
         private static MessageTypeLogHelper CreateLogger(Type messageType)
         {
-            var logger = LogManager.GetLogger(messageType);
+            var logger = ZebusLogManager.GetLogger(messageType);
             var hasToStringOverride = HasToStringOverride(messageType);
 
             return new MessageTypeLogHelper(logger, hasToStringOverride, messageType.GetPrettyName());
@@ -148,7 +147,7 @@ namespace Abc.Zebus.Core
             }
 
             logHelper = GetLogHelper(message);
-            return logHelper.Logger.IsInfoEnabled;
+            return logHelper.Logger.IsEnabled(LogLevel.Information);
         }
 
         private bool TryGetLogHelperForDebug(IMessage message, [NotNullWhen(true)] out MessageTypeLogHelper? logHelper)
@@ -160,7 +159,7 @@ namespace Abc.Zebus.Core
             }
 
             logHelper = GetLogHelper(message);
-            return logHelper.Logger.IsDebugEnabled;
+            return logHelper.Logger.IsEnabled(LogLevel.Debug);
         }
 
         private static bool HasToStringOverride(Type messageType)
@@ -171,11 +170,11 @@ namespace Abc.Zebus.Core
 
         private class MessageTypeLogHelper
         {
-            public readonly ILog Logger;
+            public readonly ILogger Logger;
             private readonly bool _hasToStringOverride;
             private readonly string _messageTypeName;
 
-            public MessageTypeLogHelper(ILog logger, bool hasToStringOverride, string messageTypeName)
+            public MessageTypeLogHelper(ILogger logger, bool hasToStringOverride, string messageTypeName)
             {
                 Logger = logger;
                 _hasToStringOverride = hasToStringOverride;

+ 11 - 11
src/Abc.Zebus/Directory/PeerDirectoryClient.cs

@@ -8,7 +8,7 @@ using System.Threading.Tasks;
 using Abc.Zebus.Routing;
 using Abc.Zebus.Util;
 using Abc.Zebus.Util.Extensions;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Directory
 {
@@ -22,7 +22,7 @@ namespace Abc.Zebus.Directory
                                                IMessageHandler<PeerNotResponding>,
                                                IMessageHandler<PeerResponding>
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(PeerDirectoryClient));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(PeerDirectoryClient));
 
         private readonly ConcurrentDictionary<MessageTypeId, PeerSubscriptionTree> _globalSubscriptionsIndex = new ConcurrentDictionary<MessageTypeId, PeerSubscriptionTree>();
         private readonly ConcurrentDictionary<PeerId, PeerEntry> _peers = new ConcurrentDictionary<PeerId, PeerEntry>();
@@ -111,7 +111,7 @@ namespace Abc.Zebus.Directory
                 }
                 catch (Exception ex)
                 {
-                    _logger.WarnFormat("Unable to process message {0} {{{1}}}, Exception: {2}", message.GetType(), message, ex);
+                    _logger.LogWarning(ex, $"Unable to process message {message.GetType()} {{{message}}}");
                 }
             }
         }
@@ -137,13 +137,13 @@ namespace Abc.Zebus.Directory
                 }
                 catch (TimeoutException ex)
                 {
-                    _logger.Error(ex);
+                    _logger.LogError(ex, "Timeout while registering on directory");
                 }
             }
 
             var directoryPeersText = string.Join(", ", directoryPeers.Select(peer => "{" + peer + "}"));
             var message = $"Unable to register peer on directory (tried: {directoryPeersText}) after {_configuration.RegistrationTimeout}";
-            _logger.Error(message);
+            _logger.LogError(message);
             throw new TimeoutException(message);
         }
 
@@ -159,7 +159,7 @@ namespace Abc.Zebus.Directory
 
                 if (registration.ErrorCode == DirectoryErrorCodes.PeerAlreadyExists)
                 {
-                    _logger.InfoFormat("Register rejected for {0}, the peer already exists in the directory", new RegisterPeerCommand(self).Peer.PeerId);
+                    _logger.LogInformation($"Register rejected for {self.PeerId}, the peer already exists in the directory");
                     return false;
                 }
 
@@ -169,7 +169,7 @@ namespace Abc.Zebus.Directory
             }
             catch (TimeoutException ex)
             {
-                _logger.Error(ex);
+                _logger.LogError(ex, "Timeout while registering on directory");
                 return false;
             }
         }
@@ -191,7 +191,7 @@ namespace Abc.Zebus.Directory
                 }
                 catch (TimeoutException ex)
                 {
-                    _logger.Error(ex);
+                    _logger.LogError(ex, "Timeout while updating subscriptions on directory");
                 }
             }
 
@@ -213,7 +213,7 @@ namespace Abc.Zebus.Directory
                 }
                 catch (TimeoutException ex)
                 {
-                    _logger.Error(ex);
+                    _logger.LogError(ex, "Timeout while unregistering on directory");
                 }
             }
 
@@ -440,7 +440,7 @@ namespace Abc.Zebus.Directory
         private static void WarnWhenPeerDoesNotExist(PeerEntryResult peer, PeerId peerId)
         {
             if (peer.FailureReason == PeerEntryResult.FailureReasonType.PeerNotPresent)
-                _logger.WarnFormat("Received message but no peer existed: {0}", peerId);
+                _logger.LogWarning($"Received message but no peer existed: {peerId}");
         }
 
         public void Handle(PeerNotResponding message)
@@ -472,7 +472,7 @@ namespace Abc.Zebus.Directory
 
             if (peer.TimestampUtc > timestampUtc)
             {
-                _logger.InfoFormat("Outdated message ignored");
+                _logger.LogInformation("Outdated message ignored");
                 return new PeerEntryResult(PeerEntryResult.FailureReasonType.OutdatedMessage);
             }
 

+ 10 - 10
src/Abc.Zebus/Dispatch/DispatchQueue.cs

@@ -5,7 +5,7 @@ using System.Threading.Tasks;
 using Abc.Zebus.Dispatch.Pipes;
 using Abc.Zebus.Util;
 using Abc.Zebus.Util.Collections;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Dispatch
 {
@@ -14,7 +14,7 @@ namespace Abc.Zebus.Dispatch
         [ThreadStatic]
         private static string? _currentDispatchQueueName;
 
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(DispatchQueue));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(DispatchQueue));
 
         private readonly IPipeManager _pipeManager;
         private readonly int _batchSize;
@@ -71,7 +71,7 @@ namespace Abc.Zebus.Dispatch
             };
 
             _thread.Start();
-            _logger.InfoFormat("{0} started", Name);
+            _logger.LogInformation($"{Name} started");
         }
 
         public void Stop()
@@ -90,7 +90,7 @@ namespace Abc.Zebus.Dispatch
             _thread = null;
 
             _queue = new FlushableBlockingCollection<Entry>();
-            _logger.InfoFormat("{0} stopped", Name);
+            _logger.LogInformation($"{Name} stopped");
         }
 
         private void ThreadProc()
@@ -98,7 +98,7 @@ namespace Abc.Zebus.Dispatch
             _currentDispatchQueueName = Name;
             try
             {
-                _logger.InfoFormat("{0} processing started", Name);
+                _logger.LogInformation($"{Name} processing started");
                 var batch = new Batch(_batchSize);
 
                 foreach (var entries in _queue.GetConsumingEnumerable(_batchSize))
@@ -106,7 +106,7 @@ namespace Abc.Zebus.Dispatch
                     ProcessEntries(entries, batch);
                 }
 
-                _logger.InfoFormat("{0} processing stopped", Name);
+                _logger.LogInformation($"{Name} processing stopped");
             }
             finally
             {
@@ -139,7 +139,7 @@ namespace Abc.Zebus.Dispatch
             }
             catch (Exception ex)
             {
-                _logger.Error(ex);
+                _logger.LogError(ex, "Error running action");
             }
             finally
             {
@@ -195,7 +195,7 @@ namespace Abc.Zebus.Dispatch
             }
             catch (Exception ex)
             {
-                _logger.Error(ex);
+                _logger.LogError(ex, "Error running batch");
                 batch.SetHandled(ex);
             }
             finally
@@ -216,7 +216,7 @@ namespace Abc.Zebus.Dispatch
                     : null;
 
                 if (exception != null)
-                    _logger.Error(exception);
+                    _logger.LogError(exception, "Error running async batch");
 
                 asyncBatch.SetHandled(exception);
             }
@@ -347,7 +347,7 @@ namespace Abc.Zebus.Dispatch
                     }
                     catch (Exception ex)
                     {
-                        _logger.Error($"Unable to run dispatch continuation, MessageType: {entry.Invoker!.MessageType.Name}, HandlerType: {entry.Invoker!.MessageHandlerType.Name}, HandlerError: {error}, ContinuationError: {ex}");
+                        _logger.LogError(ex, $"Unable to run dispatch continuation, MessageType: {entry.Invoker!.MessageType.Name}, HandlerType: {entry.Invoker!.MessageHandlerType.Name}, HandlerError: {error}");
                     }
                 }
             }

+ 6 - 6
src/Abc.Zebus/Dispatch/MessageDispatcher.cs

@@ -7,14 +7,14 @@ using System.Threading.Tasks;
 using Abc.Zebus.Monitoring;
 using Abc.Zebus.Scan;
 using Abc.Zebus.Util.Extensions;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Dispatch
 {
     public class MessageDispatcher : IMessageDispatcher, IProvideQueueLength
     {
         private static readonly List<IMessageHandlerInvoker> _emptyInvokers = new List<IMessageHandlerInvoker>();
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(MessageDispatcher));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(MessageDispatcher));
 
         private readonly ConcurrentDictionary<string, DispatchQueue> _dispatchQueues = new ConcurrentDictionary<string, DispatchQueue>(StringComparer.OrdinalIgnoreCase);
         private readonly object _lock = new object();
@@ -170,9 +170,9 @@ namespace Abc.Zebus.Dispatch
             {
                 Stopping?.Invoke();
             }
-            catch (Exception e)
+            catch (Exception ex)
             {
-                _logger.Error("Stopping event handler error", e);
+                _logger.LogError(ex, "Stopping event handler error");
             }
         }
 
@@ -203,9 +203,9 @@ namespace Abc.Zebus.Dispatch
             {
                 Starting?.Invoke();
             }
-            catch (Exception e)
+            catch (Exception ex)
             {
-                _logger.Error("Starting event handler error", e);
+                _logger.LogError(ex, "Starting event handler error");
             }
         }
 

+ 4 - 4
src/Abc.Zebus/Dispatch/Pipes/PipeManager.cs

@@ -3,13 +3,13 @@ using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
 using Abc.Zebus.Util.Collections;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Dispatch.Pipes
 {
     internal class PipeManager : IPipeManager
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(PipeManager));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(PipeManager));
 
         private readonly ConcurrentDictionary<Type, PipeList> _pipesByMessageType = new ConcurrentDictionary<Type, PipeList>();
         private readonly ConcurrentSet<string> _enabledPipeNames = new ConcurrentSet<string>();
@@ -25,7 +25,7 @@ namespace Abc.Zebus.Dispatch.Pipes
 
         public void EnablePipe(string pipeName)
         {
-            _logger.InfoFormat("Enabling pipe [{0}]", pipeName);
+            _logger.LogInformation($"Enabling pipe [{pipeName}]");
 
             _enabledPipeNames.Add(pipeName);
             _disabledPipeNames.Remove(pipeName);
@@ -36,7 +36,7 @@ namespace Abc.Zebus.Dispatch.Pipes
 
         public void DisablePipe(string pipeName)
         {
-            _logger.InfoFormat("Disabling pipe [{0}]", pipeName);
+            _logger.LogInformation($"Disabling pipe [{pipeName}]");
 
             _enabledPipeNames.Remove(pipeName);
             _disabledPipeNames.Add(pipeName);

+ 5 - 5
src/Abc.Zebus/Hosting/HostInitializerHelper.cs

@@ -2,14 +2,14 @@
 using System.Linq;
 using System.Linq.Expressions;
 using System.Reflection;
-using log4net;
+using Microsoft.Extensions.Logging;
 using StructureMap;
 
 namespace Abc.Zebus.Hosting
 {
     public static class HostInitializerHelper
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(HostInitializerHelper));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(HostInitializerHelper));
 
         public static void CallActionOnInitializers(this Container container, Expression<Action<HostInitializer>> actionToCall, bool invertPriority = false)
         {
@@ -25,11 +25,11 @@ namespace Abc.Zebus.Hosting
                 if (hostMethodInfo == null || hostMethodInfo.DeclaringType == typeof(HostInitializer))
                     continue;
 
-                _log.Info("Calling " + methodInfo.Name + " on initializer: " + hostInitializer.GetType().Name);
+                _log.LogInformation("Calling " + methodInfo.Name + " on initializer: " + hostInitializer.GetType().Name);
                 actionToCall.Compile()(hostInitializer);
             }
 
-            _log.Info(methodInfo.Name + " on initializers executed");
+            _log.LogInformation(methodInfo.Name + " on initializers executed");
         }
 
         private static MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression)
@@ -38,4 +38,4 @@ namespace Abc.Zebus.Hosting
             return methodCall.Method;
         }
     }
-}
+}

+ 8 - 8
src/Abc.Zebus/Hosting/PeriodicActionHostInitializer.cs

@@ -3,14 +3,14 @@ using System.Threading;
 using Abc.Zebus.Lotus;
 using Abc.Zebus.Util;
 using JetBrains.Annotations;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Hosting
 {
     [UsedImplicitly]
     public abstract class PeriodicActionHostInitializer : HostInitializer
     {
-        protected readonly ILog _logger;
+        protected readonly ILogger _logger;
         private readonly IBus _bus;
         private readonly Func<DateTime>? _dueTimeUtcFunc;
         private Timer? _timer;
@@ -20,7 +20,7 @@ namespace Abc.Zebus.Hosting
 
         protected PeriodicActionHostInitializer(IBus bus, TimeSpan period, Func<DateTime>? dueTimeUtcFunc = null)
         {
-            _logger = LogManager.GetLogger(GetType());
+            _logger = ZebusLogManager.GetLogger(GetType());
             _bus = bus;
             _dueTimeUtcFunc = dueTimeUtcFunc;
 
@@ -45,7 +45,7 @@ namespace Abc.Zebus.Hosting
 
             if (Period <= TimeSpan.Zero || Period == TimeSpan.MaxValue)
             {
-                _logger.InfoFormat("Periodic action disabled");
+                _logger.LogInformation("Periodic action disabled");
                 return;
             }
 
@@ -89,7 +89,7 @@ namespace Abc.Zebus.Hosting
 
             var timerStopWaitHandle = new ManualResetEvent(false);
             if (!timer.Dispose(timerStopWaitHandle) || !timerStopWaitHandle.WaitOne(2.Seconds()))
-                _logger.Warn("Unable to terminate periodic action");
+                _logger.LogWarning("Unable to terminate periodic action");
         }
 
         private void OnTimer()
@@ -123,7 +123,7 @@ namespace Abc.Zebus.Hosting
             }
             catch (Exception ex)
             {
-                _logger.Error(ex);
+                _logger.LogError(ex, "Error in periodic action");
 
                 if (ShouldPublishError(ex))
                     PublishError(ex);
@@ -131,7 +131,7 @@ namespace Abc.Zebus.Hosting
                 _exceptionCount++;
                 if (_exceptionCount >= ErrorCountBeforePause)
                 {
-                    _logger.WarnFormat("Too many exceptions, periodic action paused ({0})", ErrorPauseDuration);
+                    _logger.LogWarning($"Too many exceptions, periodic action paused ({ErrorPauseDuration})");
                     _pauseEndTimeUtc = DateTime.UtcNow.Add(ErrorPauseDuration);
                 }
             }
@@ -145,7 +145,7 @@ namespace Abc.Zebus.Hosting
             }
             catch (Exception ex)
             {
-                _logger.ErrorFormat("Unable to send CustomProcessingFailed, Exception: {0}", ex);
+                _logger.LogError(ex, "Unable to send CustomProcessingFailed");
             }
         }
 

+ 9 - 6
src/Abc.Zebus/Persistence/PersistentTransport.Phases.cs

@@ -2,6 +2,7 @@
 using System.Threading;
 using System.Threading.Tasks;
 using Abc.Zebus.Transport;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence
 {
@@ -62,7 +63,7 @@ namespace Abc.Zebus.Persistence
 
             public virtual void ProcessPendingReceive(TransportMessage transportMessage)
             {
-                _logger.ErrorFormat("DISCARDING MESSAGE {0} {1}", transportMessage.MessageTypeId, transportMessage.Id);
+                _logger.LogError($"DISCARDING MESSAGE {transportMessage.MessageTypeId} {transportMessage.Id}");
             }
 
             protected virtual void OnMessageReplayed(MessageReplayed messageReplayed)
@@ -93,7 +94,7 @@ namespace Abc.Zebus.Persistence
                     _replayEventReceivedSignal.Set();
 
                 if (replayEvent is ReplayPhaseEnded)
-                    _logger.InfoFormat("Replayed {0} messages", _replayCount);
+                    _logger.LogInformation($"Replayed {_replayCount} messages");
 
                 base.OnReplayEvent(replayEvent);
             }
@@ -121,14 +122,15 @@ namespace Abc.Zebus.Persistence
 
             protected override void OnMessageReplayed(MessageReplayed messageReplayed)
             {
-                _logger.DebugFormat("REPLAY: {0} {1}", messageReplayed.Message.MessageTypeId, messageReplayed.Message.Id);
+                if (_logger.IsEnabled(LogLevel.Debug))
+                    _logger.LogDebug($"REPLAY: {messageReplayed.Message.MessageTypeId} {messageReplayed.Message.Id}");
 
                 Transport.TriggerMessageReceived(messageReplayed.Message);
                 Transport._receivedMessagesIds.TryAdd(messageReplayed.Message.Id, true);
 
                 _replayCount++;
                 if (_replayCount % 100 == 0)
-                    _logger.InfoFormat("Replayed {0} messages...", _replayCount);
+                    _logger.LogInformation($"Replayed {_replayCount} messages...");
             }
 
             public override void OnRealTimeMessage(TransportMessage transportMessage)
@@ -156,7 +158,7 @@ namespace Abc.Zebus.Persistence
                 catch (Exception exception)
                 {
                     var errorMessage = $"Unable to handle message {transportMessage.MessageTypeId.FullName} during SafetyPhase.";
-                    _logger.Error(errorMessage, exception);
+                    _logger.LogError(exception, errorMessage);
                 }
 
                 Transport._receivedMessagesIds.TryAdd(transportMessage.Id, true);
@@ -164,7 +166,8 @@ namespace Abc.Zebus.Persistence
 
             protected override void OnMessageReplayed(MessageReplayed messageReplayed)
             {
-                _logger.DebugFormat("FORWARD: {0} {1}", messageReplayed.Message.MessageTypeId, messageReplayed.Message.Id);
+                if (_logger.IsEnabled(LogLevel.Debug))
+                    _logger.LogDebug($"FORWARD: {messageReplayed.Message.MessageTypeId} {messageReplayed.Message.Id}");
 
                 Transport._pendingReceives.Add(messageReplayed.Message);
             }

+ 16 - 15
src/Abc.Zebus/Persistence/PersistentTransport.cs

@@ -9,13 +9,13 @@ using Abc.Zebus.Directory;
 using Abc.Zebus.Serialization;
 using Abc.Zebus.Transport;
 using Abc.Zebus.Util;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Persistence
 {
     public partial class PersistentTransport : IPersistentTransport
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(PersistentTransport));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(PersistentTransport));
         private static readonly List<MessageTypeId> _replayMessageTypeIds = new List<MessageTypeId> { MessageReplayed.TypeId, ReplayPhaseEnded.TypeId, SafetyPhaseEnded.TypeId };
         private static readonly MessageBinding _bindingForPersistence = MessageBinding.Default<PersistMessageCommand>();
         private static readonly List<Peer> _emptyPeerList = new List<Peer>();
@@ -90,7 +90,7 @@ namespace Abc.Zebus.Persistence
         {
             var persistencePeers = GetPersistencePeers();
 
-            _logger.InfoFormat("Sending {0} enqueued messages to the persistence", _messagesWaitingForPersistence.Count);
+            _logger.LogInformation($"Sending {_messagesWaitingForPersistence.Count} enqueued messages to the persistence");
 
             while (_messagesWaitingForPersistence.TryTake(out var messageToSend))
             {
@@ -117,7 +117,7 @@ namespace Abc.Zebus.Persistence
 
         private void Enqueue(TransportMessage transportMessage)
         {
-            _logger.InfoFormat("Enqueing in temp persistence buffer: {0}", transportMessage.Id);
+            _logger.LogInformation($"Enqueueing in temp persistence buffer: {transportMessage.Id}");
             _messagesWaitingForPersistence.Add(transportMessage);
 
             if (!_persistenceIsDown)
@@ -148,14 +148,14 @@ namespace Abc.Zebus.Persistence
 
             if (_messagesWaitingForPersistence.Any())
             {
-                _logger.WarnFormat("Stopping PersistenceTransport with messages waiting for persistence to come back online!");
+                _logger.LogWarning("Stopping PersistenceTransport with messages waiting for persistence to come back online!");
             }
 
             _innerTransport.Stop();
 
             _pendingReceives.CompleteAdding();
             if (_receptionThread != null && !_receptionThread.Join(30.Second()))
-                _logger.WarnFormat("Unable to stop reception thread");
+                _logger.LogWarning("Unable to stop reception thread");
 
             SetInitialPhase();
         }
@@ -219,15 +219,15 @@ namespace Abc.Zebus.Persistence
         private void SetPhase(Phase phase)
         {
             var phaseType = phase.GetType();
-            if (_phase == null)
+            if (_phase == null!)
             {
-                _logger.InfoFormat("Initial phase: {0}", phaseType.Name);
+                _logger.LogInformation($"Initial phase: {phaseType.Name}");
             }
             else
             {
-                var curentPhaseType = _phase.GetType();
-                if (curentPhaseType != phaseType)
-                    _logger.InfoFormat("Switching phase: {0} -> {1}", curentPhaseType.Name, phaseType.Name);
+                var currentPhaseType = _phase.GetType();
+                if (currentPhaseType != phaseType)
+                    _logger.LogInformation($"Switching phase: {currentPhaseType.Name} -> {phaseType.Name}");
             }
 
             _phase = phase;
@@ -255,7 +255,7 @@ namespace Abc.Zebus.Persistence
 
                 var ackMessage = new TransportMessage(MessageTypeId.PersistenceStoppingAck, new MemoryStream(), _innerTransport.PeerId, _innerTransport.InboundEndPoint);
 
-                _logger.InfoFormat("Sending PersistenceStoppingAck to {0}", transportMessage.Originator.SenderId);
+                _logger.LogInformation($"Sending PersistenceStoppingAck to {transportMessage.Originator.SenderId}");
                 _innerTransport.Send(ackMessage, new[] { new Peer(transportMessage.Originator.SenderId, transportMessage.Originator.SenderEndPoint) }, new SendContext());
 
                 return;
@@ -271,7 +271,7 @@ namespace Abc.Zebus.Persistence
         {
             Thread.CurrentThread.Name = "PersistentTransport.PendingReceivesDispatcher";
 
-            _logger.InfoFormat("Starting reception pump");
+            _logger.LogInformation("Starting reception pump");
 
             foreach (var transportMessage in _pendingReceives.GetConsumingEnumerable())
             {
@@ -282,7 +282,7 @@ namespace Abc.Zebus.Persistence
                 catch (Exception exception)
                 {
                     var errorMessage = $"Unable to process message {transportMessage.MessageTypeId.FullName}. Originator: {transportMessage.Originator.SenderId}";
-                    _logger.Error(errorMessage, exception);
+                    _logger.LogError(exception, errorMessage);
                 }
             }
 
@@ -298,7 +298,8 @@ namespace Abc.Zebus.Persistence
         {
             if (transportMessage.WasPersisted == true || transportMessage.WasPersisted == null && _isPersistent && _messageSendingStrategy.IsMessagePersistent(transportMessage))
             {
-                _logger.DebugFormat("PERSIST ACK: {0} {1}", transportMessage.MessageTypeId, transportMessage.Id);
+                if (_logger.IsEnabled(LogLevel.Debug))
+                    _logger.LogDebug($"PERSIST ACK: {transportMessage.MessageTypeId} {transportMessage.Id}");
 
                 EnqueueOrSendToPersistenceService(new MessageHandled(transportMessage.Id));
             }

+ 3 - 3
src/Abc.Zebus/Serialization/MessageSerializer.cs

@@ -1,11 +1,11 @@
 using System.IO;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Serialization
 {
     public class MessageSerializer : IMessageSerializer
     {
-        private static readonly ILog _log = LogManager.GetLogger(typeof(MessageSerializer));
+        private static readonly ILogger _log = ZebusLogManager.GetLogger(typeof(MessageSerializer));
 
         public IMessage? Deserialize(MessageTypeId messageTypeId, Stream stream)
         {
@@ -13,7 +13,7 @@ namespace Abc.Zebus.Serialization
             if (messageType != null)
                 return (IMessage)Serializer.Deserialize(messageType, stream);
 
-            _log.WarnFormat("Could not find message type: {0}", messageTypeId.FullName);
+            _log.LogWarning($"Could not find message type: {messageTypeId.FullName}");
             return null;
         }
 

+ 6 - 6
src/Abc.Zebus/Transport/ZmqInboundSocket.cs

@@ -2,19 +2,19 @@
 using System.Text;
 using Abc.Zebus.Serialization.Protobuf;
 using Abc.Zebus.Transport.Zmq;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Transport
 {
     internal class ZmqInboundSocket : IDisposable
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(ZmqInboundSocket));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(ZmqInboundSocket));
 
         private readonly ZmqContext _context;
         private readonly PeerId _peerId;
         private readonly ZmqEndPoint _configuredEndPoint;
         private readonly ZmqSocketOptions _options;
-        private byte[] _readBuffer = new byte[0];
+        private byte[] _readBuffer = Array.Empty<byte>();
         private ZmqSocket? _socket;
         private TimeSpan _lastReceiveTimeout;
 
@@ -33,7 +33,7 @@ namespace Abc.Zebus.Transport
             _socket.Bind(_configuredEndPoint.ToString());
 
             var socketEndPoint = new ZmqEndPoint(_socket.GetOptionString(ZmqSocketOption.LAST_ENDPOINT));
-            _logger.InfoFormat("Socket bound, Inbound EndPoint: {0}", socketEndPoint);
+            _logger.LogInformation($"Socket bound, Inbound EndPoint: {socketEndPoint}");
 
             return socketEndPoint;
         }
@@ -81,9 +81,9 @@ namespace Abc.Zebus.Transport
             if (endpoint == null)
                 return;
 
-            _logger.InfoFormat("Unbinding socket, Inbound Endpoint: {0}", endpoint);
+            _logger.LogInformation($"Unbinding socket, Inbound Endpoint: {endpoint}");
             if (!_socket!.TryUnbind(endpoint))
-                _logger.WarnFormat("Socket error, Inbound Endpoint: {0}, Error: {1}", endpoint, ZmqUtil.GetLastErrorMessage());
+                _logger.LogWarning($"Socket error, Inbound Endpoint: {endpoint}, Error: {ZmqUtil.GetLastErrorMessage()}");
         }
     }
 }

+ 11 - 11
src/Abc.Zebus/Transport/ZmqOutboundSocket.cs

@@ -2,13 +2,13 @@
 using System.Diagnostics;
 using System.Text;
 using Abc.Zebus.Transport.Zmq;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Transport
 {
     internal class ZmqOutboundSocket
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(ZmqOutboundSocket));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(ZmqOutboundSocket));
 
         private readonly Stopwatch _closedStateStopwatch = new Stopwatch();
         private readonly ZmqContext _context;
@@ -44,7 +44,7 @@ namespace Abc.Zebus.Transport
 
                 IsConnected = true;
 
-                _logger.InfoFormat("Socket connected, Peer: {0}, EndPoint: {1}", PeerId, EndPoint);
+                _logger.LogInformation($"Socket connected, Peer: {PeerId}, EndPoint: {EndPoint}");
             }
             catch (Exception ex)
             {
@@ -52,7 +52,7 @@ namespace Abc.Zebus.Transport
                 _socket = null;
                 IsConnected = false;
 
-                _logger.ErrorFormat("Unable to connect socket, Peer: {0}, EndPoint: {1}, Exception: {2}", PeerId, EndPoint, ex);
+                _logger.LogError(ex, $"Unable to connect socket, Peer: {PeerId}, EndPoint: {EndPoint}");
                 _errorHandler.OnConnectException(PeerId, EndPoint, ex);
 
                 SwitchToClosedState(_options.ClosedStateDurationAfterConnectFailure);
@@ -99,11 +99,11 @@ namespace Abc.Zebus.Transport
                 _socket!.SetOption(ZmqSocketOption.LINGER, 0);
                 _socket!.Dispose();
 
-                _logger.InfoFormat("Socket disconnected, Peer: {0}", PeerId);
+                _logger.LogInformation($"Socket disconnected, Peer: {PeerId}");
             }
             catch (Exception ex)
             {
-                _logger.ErrorFormat("Unable to disconnect socket, Peer: {0}, Exception: {1}", PeerId, ex);
+                _logger.LogError(ex, $"Unable to disconnect socket, Peer: {PeerId}");
                 _errorHandler.OnDisconnectException(PeerId, EndPoint, ex);
             }
 
@@ -122,9 +122,9 @@ namespace Abc.Zebus.Transport
             }
 
             var hasReachedHighWaterMark = error == ZmqErrorCode.EAGAIN;
-            var errorMesage = hasReachedHighWaterMark ? "High water mark reached" : error.ToErrorMessage();
+            var errorMessage = hasReachedHighWaterMark ? "High water mark reached" : error.ToErrorMessage();
 
-            _logger.ErrorFormat("Unable to send message, destination peer: {0}, MessageTypeId: {1}, MessageId: {2}, Error: {3}", PeerId, message.MessageTypeId, message.Id, errorMesage);
+            _logger.LogError($"Unable to send message, destination peer: {PeerId}, MessageTypeId: {message.MessageTypeId}, MessageId: {message.Id}, Error: {errorMessage}");
             _errorHandler.OnSendFailed(PeerId, EndPoint, message.MessageTypeId, message.Id);
 
             if (_failedSendCount >= _options.SendRetriesBeforeSwitchingToClosedState)
@@ -139,7 +139,7 @@ namespace Abc.Zebus.Transport
             {
                 if (_closedStateStopwatch.Elapsed < _closedStateDuration)
                 {
-                    _logger.WarnFormat("Send or connect ignored in closed state, Peer: {0}, MessageTypeId: {1}, MessageId: {2}", PeerId, message.MessageTypeId, message.Id);
+                    _logger.LogWarning($"Send or connect ignored in closed state, Peer: {PeerId}, MessageTypeId: {message.MessageTypeId}, MessageId: {message.Id}");
                     return false;
                 }
 
@@ -151,7 +151,7 @@ namespace Abc.Zebus.Transport
 
         private void SwitchToClosedState(TimeSpan duration)
         {
-            _logger.ErrorFormat("Switching to closed state, Peer: {0}, Duration: {1}", PeerId, duration);
+            _logger.LogError($"Switching to closed state, Peer: {PeerId}, Duration: {duration}");
 
             _closedStateStopwatch.Start();
             _closedStateDuration = duration;
@@ -160,7 +160,7 @@ namespace Abc.Zebus.Transport
 
         private void SwitchToOpenState()
         {
-            _logger.InfoFormat("Switching back to open state, Peer: {0}", PeerId);
+            _logger.LogInformation($"Switching back to open state, Peer: {PeerId}");
 
             _isInClosedState = false;
             _closedStateStopwatch.Reset();

+ 1 - 1
src/Abc.Zebus/Transport/ZmqSocketOptions.cs

@@ -75,7 +75,7 @@ namespace Abc.Zebus.Transport
         /// <summary>
         /// Configures ZMQ keepalive options (ZMQ_TCP_KEEPALIVE, ZMQ_TCP_KEEPALIVE_IDLE and ZMQ_TCP_KEEPALIVE_INTVL).
         /// </summary>
-        public KeepAliveOptions KeepAlive { get; set; }
+        public KeepAliveOptions? KeepAlive { get; set; }
 
         public class KeepAliveOptions
         {

+ 27 - 27
src/Abc.Zebus/Transport/ZmqTransport.cs

@@ -8,7 +8,7 @@ using Abc.Zebus.Directory;
 using Abc.Zebus.Serialization.Protobuf;
 using Abc.Zebus.Transport.Zmq;
 using Abc.Zebus.Util;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Transport
 {
@@ -18,7 +18,7 @@ namespace Abc.Zebus.Transport
         private readonly ZmqSocketOptions _socketOptions;
         private readonly IZmqOutboundSocketErrorHandler _errorHandler;
         private readonly ZmqEndPoint _configuredInboundEndPoint;
-        private ILog _logger = LogManager.GetLogger(typeof(ZmqTransport));
+        private ILogger _logger = ZebusLogManager.GetLogger(typeof(ZmqTransport));
         private ConcurrentDictionary<PeerId, ZmqOutboundSocket> _outboundSockets = new ConcurrentDictionary<PeerId, ZmqOutboundSocket>();
         private BlockingCollection<OutboundSocketAction>? _outboundSocketActions;
         private BlockingCollection<PendingDisconnect> _pendingDisconnects = new BlockingCollection<PendingDisconnect>();
@@ -58,7 +58,7 @@ namespace Abc.Zebus.Transport
 
         internal void SetLogId(int logId)
         {
-            _logger = LogManager.GetLogger(typeof(ZmqTransport).Assembly, typeof(ZmqTransport).FullName + "#" + logId);
+            _logger = ZebusLogManager.GetLogger(typeof(ZmqTransport).FullName + "#" + logId);
         }
 
         public void Configure(PeerId peerId, string environment)
@@ -87,7 +87,7 @@ namespace Abc.Zebus.Transport
         public void Start()
         {
             var zmqVersion = ZmqUtil.GetVersion();
-            _logger.InfoFormat("Loaded ZMQ v{0}", zmqVersion.ToString(3));
+            _logger.LogInformation($"Loaded ZMQ v{zmqVersion.ToString(3)}");
 
             if (zmqVersion.Major != 4)
                 throw new InvalidOperationException($"Expected ZMQ v4.*, loaded ZMQ v{zmqVersion.ToString(3)}");
@@ -128,7 +128,7 @@ namespace Abc.Zebus.Transport
                 DiscardItems(_pendingDisconnects);
 
             if (!_disconnectThread!.Join(30.Seconds()))
-                _logger.Error("Unable to terminate disconnect thread");
+                _logger.LogError("Unable to terminate disconnect thread");
 
             _outboundSocketActions!.CompleteAdding();
 
@@ -136,17 +136,17 @@ namespace Abc.Zebus.Transport
                 DiscardItems(_outboundSocketActions!);
 
             if (!_outboundThread!.Join(30.Seconds()))
-                _logger.Error("Unable to terminate outbound thread");
+                _logger.LogError("Unable to terminate outbound thread");
 
             _isListening = false;
             if (!_inboundThread!.Join(30.Seconds()))
-                _logger.Error("Unable to terminate inbound thread");
+                _logger.LogError("Unable to terminate inbound thread");
 
             _outboundSocketActions!.Dispose();
             _outboundSocketActions = null;
 
             _context!.Dispose();
-            _logger.InfoFormat("{0} Stopped", PeerId);
+            _logger.LogInformation($"{PeerId} Stopped");
         }
 
         private static void DiscardItems<T>(BlockingCollection<T> collection)
@@ -169,7 +169,7 @@ namespace Abc.Zebus.Transport
         private void Disconnect(PeerId peerId, bool delayed = true)
         {
             if (_outboundSockets.ContainsKey(peerId))
-                _logger.InfoFormat("Queueing disconnect, PeerId: {0}, Delayed: {1}", peerId, delayed);
+                _logger.LogInformation($"Queueing disconnect, PeerId: {peerId}, Delayed: {delayed}");
 
             if (delayed)
             {
@@ -188,7 +188,7 @@ namespace Abc.Zebus.Transport
         private void InboundProc(InboundProcStartSequenceState state)
         {
             Thread.CurrentThread.Name = "ZmqTransport.InboundProc";
-            _logger.DebugFormat("Starting inbound proc...");
+            _logger.LogDebug("Starting inbound proc...");
 
             var inboundSocket = CreateInboundSocket(state);
             if (inboundSocket == null)
@@ -208,7 +208,7 @@ namespace Abc.Zebus.Transport
                 GracefullyDisconnectInboundSocket(inboundSocket);
             }
 
-            _logger.InfoFormat("InboundProc terminated");
+            _logger.LogInformation("InboundProc terminated");
         }
 
         private ZmqInboundSocket? CreateInboundSocket(InboundProcStartSequenceState state)
@@ -269,7 +269,7 @@ namespace Abc.Zebus.Transport
             }
             catch (Exception ex)
             {
-                _logger.ErrorFormat("Failed to process inbound transport message, PeerId: {0}: {0}", ex);
+                _logger.LogError(ex, "Failed to process inbound transport message");
             }
         }
 
@@ -278,7 +278,7 @@ namespace Abc.Zebus.Transport
             if (bufferReader.TryReadTransportMessage(out transportMessage))
                 return true;
 
-            _logger.Debug($"Unable to read transport message, Length: {bufferReader.Length}, Bytes: {bufferReader.ToDebugString(50)}");
+            _logger.LogDebug($"Unable to read transport message, Length: {bufferReader.Length}, Bytes: {bufferReader.ToDebugString(50)}");
 
             return false;
         }
@@ -291,17 +291,17 @@ namespace Abc.Zebus.Transport
 
             if (!isValid)
             {
-                _logger.Debug($"Invalid transport message received, Id: {transportMessage.Id}, MessageTypeId: {transportMessage.MessageTypeId}, Originator: {transportMessage.Originator.SenderId}");
+                _logger.LogDebug($"Invalid transport message received, Id: {transportMessage.Id}, MessageTypeId: {transportMessage.MessageTypeId}, Originator: {transportMessage.Originator.SenderId}");
                 return false;
             }
 
             if (transportMessage.Environment == null) // TODO: treat as invalid message
             {
-                _logger.Info($"Receiving message with null environment from  {transportMessage.Originator.SenderId}");
+                _logger.LogInformation($"Receiving message with null environment from  {transportMessage.Originator.SenderId}");
             }
             else if (transportMessage.Environment != _environment)
             {
-                _logger.Error($"Receiving messages from wrong environment: {transportMessage.Environment} from {transportMessage.Originator.SenderEndPoint}, discarding message type {transportMessage.MessageTypeId}");
+                _logger.LogError($"Receiving messages from wrong environment: {transportMessage.Environment} from {transportMessage.Originator.SenderEndPoint}, discarding message type {transportMessage.MessageTypeId}");
                 return false;
             }
 
@@ -316,18 +316,18 @@ namespace Abc.Zebus.Transport
 
             if (!_outboundSockets.ContainsKey(senderId))
             {
-                _logger.ErrorFormat("Received EndOfStreamAck for an unknown socket ({0}) PeerId: {1} (Known peers: {2})", senderEndPoint, senderId, string.Join(", ", _outboundSockets.Keys));
+                _logger.LogError("Received EndOfStreamAck for an unknown socket ({0}) PeerId: {1} (Known peers: {2})", senderEndPoint, senderId, string.Join(", ", _outboundSockets.Keys));
                 return;
             }
 
-            _logger.InfoFormat("Received EndOfStreamAck for {0}, {1}", senderId, senderEndPoint);
+            _logger.LogInformation("Received EndOfStreamAck for {0}, {1}", senderId, senderEndPoint);
 
             _outboundSocketsToStop!.Signal();
         }
 
         private void SendEndOfStreamAck(TransportMessage transportMessage)
         {
-            _logger.InfoFormat("Sending EndOfStreamAck to {0}", transportMessage.Originator.SenderEndPoint);
+            _logger.LogInformation("Sending EndOfStreamAck to {0}", transportMessage.Originator.SenderEndPoint);
 
             var endOfStreamAck = new TransportMessage(MessageTypeId.EndOfStreamAck, new MemoryStream(), PeerId, InboundEndPoint);
             var closingPeer = new Peer(transportMessage.Originator.SenderId, transportMessage.Originator.SenderEndPoint);
@@ -339,7 +339,7 @@ namespace Abc.Zebus.Transport
         private void OutboundProc()
         {
             Thread.CurrentThread.Name = "ZmqTransport.OutboundProc";
-            _logger.DebugFormat("Starting outbound proc...");
+            _logger.LogDebug("Starting outbound proc...");
 
             var bufferWriter = new ProtoBufferWriter();
 
@@ -357,7 +357,7 @@ namespace Abc.Zebus.Transport
 
             GracefullyDisconnectOutboundSockets(bufferWriter);
 
-            _logger.InfoFormat("OutboundProc terminated");
+            _logger.LogInformation("OutboundProc terminated");
         }
 
         private void WriteTransportMessageAndSendToPeers(TransportMessage transportMessage, List<Peer> peers, SendContext context, ProtoBufferWriter bufferWriter)
@@ -391,7 +391,7 @@ namespace Abc.Zebus.Transport
             var outboundSocket = GetConnectedOutboundSocket(target, transportMessage);
             if (!outboundSocket.IsConnected)
             {
-                _logger.Error($"Could not send message of type {transportMessage.MessageTypeId.FullName} to peer {target.Id} because outbound socket was not connected");
+                _logger.LogError($"Could not send message of type {transportMessage.MessageTypeId.FullName} to peer {target.Id} because outbound socket was not connected");
                 return;
             }
 
@@ -401,7 +401,7 @@ namespace Abc.Zebus.Transport
             }
             catch (Exception ex)
             {
-                _logger.Error($"Failed to send message, PeerId: {target.Id}, EndPoint: {target.EndPoint}, Exception: {ex}");
+                _logger.LogError(ex, $"Failed to send message, PeerId: {target.Id}, EndPoint: {target.EndPoint}");
             }
         }
 
@@ -441,9 +441,9 @@ namespace Abc.Zebus.Transport
 
             SendEndOfStreamMessages(connectedOutboundSockets, bufferWriter);
 
-            _logger.InfoFormat("Waiting for {0} outbound socket end of stream acks", _outboundSocketsToStop.InitialCount);
+            _logger.LogInformation($"Waiting for {_outboundSocketsToStop.InitialCount} outbound socket end of stream acks");
             if (!_outboundSocketsToStop.Wait(_configuration.WaitForEndOfStreamAckTimeout))
-                _logger.WarnFormat("{0} peers did not respond to end of stream", _outboundSocketsToStop.CurrentCount);
+                _logger.LogWarning($"{_outboundSocketsToStop.CurrentCount} peers did not respond to end of stream");
 
             DisconnectPeers(connectedOutboundSockets.Select(x => x.PeerId).ToList());
         }
@@ -452,7 +452,7 @@ namespace Abc.Zebus.Transport
         {
             foreach (var outboundSocket in connectedOutboundSockets)
             {
-                _logger.InfoFormat("Sending EndOfStream to {0}", outboundSocket.EndPoint);
+                _logger.LogInformation($"Sending EndOfStream to {outboundSocket.EndPoint}");
 
                 var endOfStreamMessage = new TransportMessage(MessageTypeId.EndOfStream, new MemoryStream(), PeerId, InboundEndPoint) { WasPersisted = false };
                 bufferWriter.Reset();
@@ -487,7 +487,7 @@ namespace Abc.Zebus.Transport
             }
             catch (Exception ex)
             {
-                _logger.WarnFormat("Unable to enqueue item, Type: {0}, Exception: {1}", typeof(T).Name, ex);
+                _logger.LogWarning(ex, $"Unable to enqueue item, Type: {typeof(T).Name}");
             }
         }
 

+ 5 - 5
src/Abc.Zebus/Util/BackgroundThread.cs

@@ -1,12 +1,12 @@
 using System;
 using System.Threading;
-using log4net;
+using Microsoft.Extensions.Logging;
 
 namespace Abc.Zebus.Util
 {
     internal static class BackgroundThread
     {
-        private static readonly ILog _logger = LogManager.GetLogger(typeof(BackgroundThread));
+        private static readonly ILogger _logger = ZebusLogManager.GetLogger(typeof(BackgroundThread));
 
         public static Thread Start(ThreadStart startAction, Action? abortAction = null)
         {
@@ -38,7 +38,7 @@ namespace Abc.Zebus.Util
             }
             catch (Exception ex)
             {
-                _logger.Error(ex);
+                _logger.LogError(ex, "Error running action");
             }
         }
 
@@ -59,7 +59,7 @@ namespace Abc.Zebus.Util
                 }
                 catch (Exception ex)
                 {
-                    _logger.Error(ex);
+                    _logger.LogError(ex, "Error running action");
                 }
             };
         }
@@ -81,7 +81,7 @@ namespace Abc.Zebus.Util
                 }
                 catch (Exception ex)
                 {
-                    _logger.Error(ex);
+                    _logger.LogError(ex, "Error running action");
                 }
             };
         }

+ 70 - 0
src/Abc.Zebus/ZebusLogManager.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Runtime.CompilerServices;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+
+namespace Abc.Zebus
+{
+    public static class ZebusLogManager
+    {
+        private static ILoggerFactory _loggerFactory = NullLoggerFactory.Instance;
+
+        public static ILoggerFactory LoggerFactory
+        {
+            get => _loggerFactory;
+            set
+            {
+                value ??= NullLoggerFactory.Instance;
+
+                if (ReferenceEquals(value, _loggerFactory))
+                    return;
+
+                _loggerFactory = value;
+                LoggerFactoryChanged?.Invoke();
+            }
+        }
+
+        public static event Action? LoggerFactoryChanged;
+
+        public static ILogger GetLogger(string name)
+            => new Logger(name);
+
+        public static ILogger GetLogger(Type type)
+            => GetLogger(type.FullName!);
+
+        private class Logger : ILogger
+        {
+            private readonly string _name;
+            private ILogger _logger = NullLogger.Instance;
+            private ILoggerFactory _currentLoggerFactory = NullLoggerFactory.Instance;
+
+            public Logger(string name)
+                => _name = name;
+
+            public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
+                => GetLogger().Log(logLevel, eventId, state, exception, formatter);
+
+            public bool IsEnabled(LogLevel logLevel)
+                => GetLogger().IsEnabled(logLevel);
+
+            public IDisposable BeginScope<TState>(TState state)
+                => GetLogger().BeginScope(state);
+
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            private ILogger GetLogger()
+            {
+                return ReferenceEquals(_currentLoggerFactory, _loggerFactory)
+                    ? _logger
+                    : GetLoggerSlow();
+
+                [MethodImpl(MethodImplOptions.NoInlining)]
+                ILogger GetLoggerSlow()
+                {
+                    _logger = _loggerFactory.CreateLogger(_name);
+                    _currentLoggerFactory = _loggerFactory;
+                    return _logger;
+                }
+            }
+        }
+    }
+}