This is an automated email from the ASF dual-hosted git repository.

lizhanhui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-clients.git


The following commit(s) were added to refs/heads/master by this push:
     new 17bd443b replace nlog with Microsoft.Extensions.Logging (#596)
17bd443b is described below

commit 17bd443b438df9aa0e1d9d92d38973d8466e6f7c
Author: EventHorizon <772552...@qq.com>
AuthorDate: Sun Oct 8 14:07:34 2023 +0800

    replace nlog with Microsoft.Extensions.Logging (#596)
    
    * replace nlog with Microsoft.Extensions.Logging
    
    * fix md format
    
    * use nlog as default LoggerFactory and remove useless nlog configuration 
file
    
    ---------
    
    Co-authored-by: Event Horizon <772552754@qq.com>
---
 csharp/README-CN.md                                | 16 +++++-
 csharp/README.md                                   | 15 ++++--
 csharp/examples/ProducerBenchmark.cs               |  6 +--
 csharp/examples/ProducerDelayMessageExample.cs     |  6 +--
 csharp/examples/ProducerFifoMessageExample.cs      |  7 ++-
 csharp/examples/ProducerNormalMessageExample.cs    |  6 +--
 .../examples/ProducerTransactionMessageExample.cs  |  8 +--
 csharp/examples/QuickStart.cs                      |  9 ++++
 csharp/examples/SimpleConsumerExample.cs           | 10 ++--
 csharp/examples/examples.csproj                    |  3 ++
 csharp/rocketmq-client-csharp/Client.cs            | 60 +++++++++++-----------
 .../ClientLoggerInterceptor.cs                     |  8 +--
 csharp/rocketmq-client-csharp/ClientMeter.cs       |  8 +--
 .../rocketmq-client-csharp/ClientMeterManager.cs   | 10 ++--
 csharp/rocketmq-client-csharp/MessageView.cs       |  9 ++--
 csharp/rocketmq-client-csharp/MqLogManager.cs      | 58 ++++++++++++---------
 csharp/rocketmq-client-csharp/Producer.cs          | 42 +++++++--------
 .../rocketmq-client-csharp/PublishingSettings.cs   |  6 +--
 csharp/rocketmq-client-csharp/RpcClient.cs         | 10 ++--
 csharp/rocketmq-client-csharp/Session.cs           | 14 ++---
 csharp/rocketmq-client-csharp/SimpleConsumer.cs    | 12 ++---
 .../SimpleSubscriptionSettings.cs                  |  8 +--
 csharp/rocketmq-client-csharp/StatusChecker.cs     |  6 +--
 .../rocketmq-client-csharp.csproj                  |  3 +-
 .../rocketmq-client-csharp.nlog                    | 45 ----------------
 csharp/tests/MqLogManagerTest.cs                   | 45 ++++++++++++----
 csharp/tests/tests.csproj                          |  1 +
 27 files changed, 227 insertions(+), 204 deletions(-)

diff --git a/csharp/README-CN.md b/csharp/README-CN.md
index 69d9f198..dacf7a2a 100644
--- a/csharp/README-CN.md
+++ b/csharp/README-CN.md
@@ -51,14 +51,26 @@ dotnet test -l "console;verbosity=detailed"
 
 ## 日志系统
 
-我们使用 [NLog](https://nlog-project.org/) 作为日志实现,与 Java 
客户端类似,我们允许使用环境变量来自定义日志相关的配置。
+我们使用 
[Microsoft.Extensions.Logging](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line#non-host-console-app)
 作为日志实现。
+
+默认的 `LoggerFactory` 是 [NLog](https://nlog-project.org/)。与 Java 
客户端类似,我们允许使用环境变量来自定义日志相关的配置:
 
 * `rocketmq_log_level`:日志输出级别,默认为 INFO。
 * `rocketmq_log_root`
   :日志输出的根目录。默认路径为 `$HOME/logs/rocketmq`,因此完整路径为 
`$HOME/logs/rocketmq/rocketmq-client.log`。
 * `rocketmq_log_file_maxIndex`:要保留的日志文件的最大数量。默认值为 10,单个日志文件的大小限制为 64 MB。暂不支持调整。
 
-除此之外,通过将 `mq_consoleAppender_enabled` 设置为 true,您可以同时将客户端日志输出到控制台进行调试。
+如果你想使用自定义的 `LoggerFactory`,可以使用 `MqLogManager.UseLoggerFactory` 方法来配置。
+
+```csharp
+var loggerFactory = LoggerFactory.Create(builder =>
+{
+    builder
+        .AddFilter("Org.Apache.Rocketmq", LogLevel.Warning)
+        .AddConsole();
+});
+MqLogManager.UseLoggerFactory(loggerFactory);
+```
 
 ## NuGet 包发布步骤
 
diff --git a/csharp/README.md b/csharp/README.md
index 1e648085..3b804a6d 100644
--- a/csharp/README.md
+++ b/csharp/README.md
@@ -54,7 +54,9 @@ dotnet test -l "console;verbosity=detailed"
 
 ## Logging System
 
-We use [NLog](https://nlog-project.org/) as our logging implementation. 
Similar to the Java binding, we allow the use of
+We use 
[Microsoft.Extensions.Logging](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line#non-host-console-app)
 as our logging implementation.
+
+The default `LoggerFactory` is [NLog](https://nlog-project.org/). Similar to 
the Java binding, we allow the use of
 environment variables to customize the related configuration:
 
 * `rocketmq_log_level`: Log output level, default is INFO.
@@ -63,8 +65,15 @@ environment variables to customize the related configuration:
 * `rocketmq_log_file_maxIndex`: The maximum number of log files to keep. The 
default is 10, and the size of a single log
   file is limited to 64 MB. Adjustment is not supported yet.
 
-Specifically, by setting `mq_consoleAppender_enabled` to true, you can output 
client logs to the console simultaneously
-if you need debugging.
+If you want to use a custom `LoggerFactory`, you can use the 
`MqLogManager.UseLoggerFactory` method to configure.
+
+```csharp
+var loggerFactory = LoggerFactory.Create(
+      builder => builder
+         .AddFilter("Org.Apache.Rocketmq", LogLevel.Warning)
+         .AddConsole());
+MqLogManager.UseLoggerFactory(loggerFactory);
+```
 
 ## Publishing Steps
 
diff --git a/csharp/examples/ProducerBenchmark.cs 
b/csharp/examples/ProducerBenchmark.cs
index 2b2ff427..6e57d7e3 100644
--- a/csharp/examples/ProducerBenchmark.cs
+++ b/csharp/examples/ProducerBenchmark.cs
@@ -20,14 +20,14 @@ using System.Collections.Concurrent;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Org.Apache.Rocketmq;
 
 namespace examples
 {
     public static class ProducerBenchmark
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger(typeof(ProducerBenchmark).FullName);
 
         private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(0);
         private const int TpsLimit = 1024;
@@ -52,7 +52,7 @@ namespace examples
             {
                 while (true)
                 {
-                    Logger.Info($"{Interlocked.Exchange(ref _successCounter, 
0)} success, " +
+                    Logger.LogInformation($"{Interlocked.Exchange(ref 
_successCounter, 0)} success, " +
                                 $"{Interlocked.Exchange(ref _failureCounter, 
0)} failure.");
                     await Task.Delay(TimeSpan.FromSeconds(1));
                 }
diff --git a/csharp/examples/ProducerDelayMessageExample.cs 
b/csharp/examples/ProducerDelayMessageExample.cs
index fa3d4bae..1da89186 100644
--- a/csharp/examples/ProducerDelayMessageExample.cs
+++ b/csharp/examples/ProducerDelayMessageExample.cs
@@ -18,14 +18,14 @@
 using System;
 using System.Text;
 using System.Threading.Tasks;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Org.Apache.Rocketmq;
 
 namespace examples
 {
     internal static class ProducerDelayMessageExample
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger(typeof(ProducerDelayMessageExample).FullName);
 
         internal static async Task QuickStart()
         {
@@ -65,7 +65,7 @@ namespace examples
                 .Build();
 
             var sendReceipt = await producer.Send(message);
-            Logger.Info($"Send message successfully, 
sendReceipt={sendReceipt}");
+            Logger.LogInformation($"Send message successfully, 
sendReceipt={sendReceipt}");
 
             // Close the producer if you don't need it anymore.
             await producer.DisposeAsync();
diff --git a/csharp/examples/ProducerFifoMessageExample.cs 
b/csharp/examples/ProducerFifoMessageExample.cs
index bba5fc60..138cd02e 100644
--- a/csharp/examples/ProducerFifoMessageExample.cs
+++ b/csharp/examples/ProducerFifoMessageExample.cs
@@ -16,16 +16,15 @@
  */
 
 using System.Text;
-using System.Threading;
 using System.Threading.Tasks;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Org.Apache.Rocketmq;
 
 namespace examples
 {
     internal static class ProducerFifoMessageExample
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger(typeof(ProducerFifoMessageExample).FullName);
 
         internal static async Task QuickStart()
         {
@@ -67,7 +66,7 @@ namespace examples
                 .Build();
 
             var sendReceipt = await producer.Send(message);
-            Logger.Info($"Send message successfully, 
sendReceipt={sendReceipt}");
+            Logger.LogInformation($"Send message successfully, 
sendReceipt={sendReceipt}");
 
             // Close the producer if you don't need it anymore.
             await producer.DisposeAsync();
diff --git a/csharp/examples/ProducerNormalMessageExample.cs 
b/csharp/examples/ProducerNormalMessageExample.cs
index c94662d0..6038eb6c 100644
--- a/csharp/examples/ProducerNormalMessageExample.cs
+++ b/csharp/examples/ProducerNormalMessageExample.cs
@@ -17,14 +17,14 @@
 
 using System.Text;
 using System.Threading.Tasks;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Org.Apache.Rocketmq;
 
 namespace examples
 {
     internal static class ProducerNormalMessageExample
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger(typeof(ProducerNormalMessageExample).FullName);
 
         internal static async Task QuickStart()
         {
@@ -63,7 +63,7 @@ namespace examples
                 .Build();
 
             var sendReceipt = await producer.Send(message);
-            Logger.Info($"Send message successfully, 
messageId={sendReceipt.MessageId}");
+            Logger.LogInformation($"Send message successfully, 
messageId={sendReceipt.MessageId}");
 
             // Close the producer if you don't need it anymore.
             await producer.DisposeAsync();
diff --git a/csharp/examples/ProducerTransactionMessageExample.cs 
b/csharp/examples/ProducerTransactionMessageExample.cs
index ebaec134..d353f743 100644
--- a/csharp/examples/ProducerTransactionMessageExample.cs
+++ b/csharp/examples/ProducerTransactionMessageExample.cs
@@ -17,20 +17,20 @@
 
 using System.Text;
 using System.Threading.Tasks;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Org.Apache.Rocketmq;
 
 namespace examples
 {
     internal static class ProducerTransactionMessageExample
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger(typeof(ProducerTransactionMessageExample).FullName);
 
         private class TransactionChecker : ITransactionChecker
         {
             public TransactionResolution Check(MessageView messageView)
             {
-                Logger.Info("Receive transaction check, messageId={}", 
messageView.MessageId);
+                Logger.LogInformation("Receive transaction check, 
messageId={}", messageView.MessageId);
                 return TransactionResolution.Commit;
             }
         }
@@ -74,7 +74,7 @@ namespace examples
                 .Build();
 
             var sendReceipt = await producer.Send(message, transaction);
-            Logger.Info("Send transaction message successfully, messageId={}", 
sendReceipt.MessageId);
+            Logger.LogInformation("Send transaction message successfully, 
messageId={}", sendReceipt.MessageId);
             // Commit the transaction.
             transaction.Commit();
             // Or rollback the transaction.
diff --git a/csharp/examples/QuickStart.cs b/csharp/examples/QuickStart.cs
index 2d4a674d..63d57e85 100644
--- a/csharp/examples/QuickStart.cs
+++ b/csharp/examples/QuickStart.cs
@@ -15,12 +15,21 @@
  * limitations under the License.
  */
 
+using Microsoft.Extensions.Logging;
+using Org.Apache.Rocketmq;
+
 namespace examples
 {
     internal static class QuickStart
     {
         public static void Main()
         {
+            var loggerFactory = LoggerFactory.Create(
+                builder => builder
+                    .AddFilter("Org.Apache.Rocketmq", LogLevel.Warning)
+                    .AddFilter("examples", LogLevel.Information)
+                    .AddConsole());
+            MqLogManager.UseLoggerFactory(loggerFactory);
             // ProducerNormalMessageExample.QuickStart().Wait();
             // ProducerFifoMessageExample.QuickStart().Wait();
             // ProducerDelayMessageExample.QuickStart().Wait();
diff --git a/csharp/examples/SimpleConsumerExample.cs 
b/csharp/examples/SimpleConsumerExample.cs
index 221ce05a..3b2a4b7d 100644
--- a/csharp/examples/SimpleConsumerExample.cs
+++ b/csharp/examples/SimpleConsumerExample.cs
@@ -18,14 +18,14 @@
 using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Org.Apache.Rocketmq;
 
 namespace examples
 {
     internal static class SimpleConsumerExample
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger(typeof(SimpleConsumerExample).FullName);
 
         internal static async Task QuickStart()
         {
@@ -60,12 +60,12 @@ namespace examples
                 var messageViews = await simpleConsumer.Receive(16, 
TimeSpan.FromSeconds(15));
                 foreach (var message in messageViews)
                 {
-                    Logger.Info(
+                    Logger.LogInformation(
                         $"Received a message, topic={message.Topic}, 
message-id={message.MessageId}, body-size={message.Body.Length}");
                     await simpleConsumer.Ack(message);
-                    Logger.Info($"Message is acknowledged successfully, 
message-id={message.MessageId}");
+                    Logger.LogInformation($"Message is acknowledged 
successfully, message-id={message.MessageId}");
                     // await simpleConsumer.ChangeInvisibleDuration(message, 
TimeSpan.FromSeconds(15));
-                    // Logger.Info($"Changing message invisible duration 
successfully, message=id={message.MessageId}");
+                    // Logger.LogInformation($"Changing message invisible 
duration successfully, message=id={message.MessageId}");
                 }
             }
             // Close the simple consumer if you don't need it anymore.
diff --git a/csharp/examples/examples.csproj b/csharp/examples/examples.csproj
index c4836826..34e14655 100644
--- a/csharp/examples/examples.csproj
+++ b/csharp/examples/examples.csproj
@@ -2,6 +2,9 @@
     <ItemGroup>
         <ProjectReference 
Include="..\rocketmq-client-csharp\rocketmq-client-csharp.csproj" />
     </ItemGroup>
+    <ItemGroup>
+      <PackageReference Include="Microsoft.Extensions.Logging.Console" 
Version="3.1.32" />
+    </ItemGroup>
 
     <PropertyGroup>
         <OutputType>Exe</OutputType>
diff --git a/csharp/rocketmq-client-csharp/Client.cs 
b/csharp/rocketmq-client-csharp/Client.cs
index 2a2c9716..f3ea4a87 100644
--- a/csharp/rocketmq-client-csharp/Client.cs
+++ b/csharp/rocketmq-client-csharp/Client.cs
@@ -21,15 +21,15 @@ using System.Threading.Tasks;
 using System.Threading;
 using System;
 using System.Linq;
+using Microsoft.Extensions.Logging;
 using Proto = Apache.Rocketmq.V2;
 using grpc = Grpc.Core;
-using NLog;
 
 namespace Org.Apache.Rocketmq
 {
     public abstract class Client
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<Client>();
 
         private static readonly TimeSpan HeartbeatScheduleDelay = 
TimeSpan.FromSeconds(1);
         private static readonly TimeSpan HeartbeatSchedulePeriod = 
TimeSpan.FromSeconds(10);
@@ -85,7 +85,7 @@ namespace Org.Apache.Rocketmq
 
         protected virtual async Task Start()
         {
-            Logger.Debug($"Begin to start the rocketmq client, 
clientId={ClientId}");
+            Logger.LogDebug($"Begin to start the rocketmq client, 
clientId={ClientId}");
             foreach (var topic in GetTopics())
             {
                 await FetchTopicRoute(topic);
@@ -97,12 +97,12 @@ namespace Org.Apache.Rocketmq
             ScheduleWithFixedDelay(SyncSettings, SettingsSyncScheduleDelay, 
SettingsSyncSchedulePeriod,
                 _settingsSyncCts.Token);
             ScheduleWithFixedDelay(Stats, StatsScheduleDelay, 
StatsSchedulePeriod, _statsCts.Token);
-            Logger.Debug($"Start the rocketmq client successfully, 
clientId={ClientId}");
+            Logger.LogDebug($"Start the rocketmq client successfully, 
clientId={ClientId}");
         }
 
         protected virtual async Task Shutdown()
         {
-            Logger.Debug($"Begin to shutdown rocketmq client, 
clientId={ClientId}");
+            Logger.LogDebug($"Begin to shutdown rocketmq client, 
clientId={ClientId}");
             _heartbeatCts.Cancel();
             _topicRouteUpdateCts.Cancel();
             _settingsSyncCts.Cancel();
@@ -110,7 +110,7 @@ namespace Org.Apache.Rocketmq
             NotifyClientTermination();
             await ClientManager.Shutdown();
             ClientMeterManager.Shutdown();
-            Logger.Debug($"Shutdown the rocketmq client successfully, 
clientId={ClientId}");
+            Logger.LogDebug($"Shutdown the rocketmq client successfully, 
clientId={ClientId}");
         }
 
         private (bool, Session) GetSession(Endpoints endpoints)
@@ -174,9 +174,9 @@ namespace Org.Apache.Rocketmq
                     continue;
                 }
 
-                Logger.Info($"Begin to establish session for 
endpoints={endpoints}, clientId={ClientId}");
+                Logger.LogInformation($"Begin to establish session for 
endpoints={endpoints}, clientId={ClientId}");
                 await session.SyncSettings(true);
-                Logger.Info($"Establish session for endpoints={endpoints} 
successfully, clientId={ClientId}");
+                Logger.LogInformation($"Establish session for 
endpoints={endpoints} successfully, clientId={ClientId}");
             }
 
             _topicRouteCache[topic] = topicRouteData;
@@ -204,7 +204,7 @@ namespace Org.Apache.Rocketmq
         {
             try
             {
-                Logger.Info($"Start to update topic route cache for a new 
round, clientId={ClientId}");
+                Logger.LogInformation($"Start to update topic route cache for 
a new round, clientId={ClientId}");
                 Dictionary<string, Task<TopicRouteData>> responses = new 
Dictionary<string, Task<TopicRouteData>>();
 
                 foreach (var topic in GetTopics())
@@ -221,13 +221,13 @@ namespace Org.Apache.Rocketmq
                     }
                     catch (Exception e)
                     {
-                        Logger.Error(e, $"Failed to update topic route cache, 
topic={item}");
+                        Logger.LogError(e, $"Failed to update topic route 
cache, topic={item}");
                     }
                 }
             }
             catch (Exception e)
             {
-                Logger.Error(e, $"[Bug] unexpected exception raised during 
topic route cache update, " +
+                Logger.LogError(e, $"[Bug] unexpected exception raised during 
topic route cache update, " +
                                 $"clientId={ClientId}");
             }
         }
@@ -241,19 +241,19 @@ namespace Org.Apache.Rocketmq
                 {
                     var (_, session) = GetSession(endpoints);
                     await session.SyncSettings(false);
-                    Logger.Info($"Sync settings to remote, 
endpoints={endpoints}");
+                    Logger.LogInformation($"Sync settings to remote, 
endpoints={endpoints}");
                 }
             }
             catch (Exception e)
             {
-                Logger.Error(e, $"[Bug] unexpected exception raised during 
setting sync, clientId={ClientId}");
+                Logger.LogError(e, $"[Bug] unexpected exception raised during 
setting sync, clientId={ClientId}");
             }
         }
 
         private void Stats()
         {
             ThreadPool.GetAvailableThreads(out var availableWorker, out var 
availableIo);
-            Logger.Info(
+            Logger.LogInformation(
                 $"ClientId={ClientId}, 
ClientVersion={MetadataConstants.Instance.ClientVersion}, " +
                 $".NET Version={Environment.Version}, 
ThreadCount={ThreadPool.ThreadCount}, " +
                 $"CompletedWorkItemCount={ThreadPool.CompletedWorkItemCount}, 
" +
@@ -274,7 +274,7 @@ namespace Org.Apache.Rocketmq
                     }
                     catch (Exception e)
                     {
-                        Logger.Error(e, $"Failed to execute scheduled task, 
ClientId={ClientId}");
+                        Logger.LogError(e, $"Failed to execute scheduled task, 
ClientId={ClientId}");
                     }
                     finally
                     {
@@ -299,7 +299,7 @@ namespace Org.Apache.Rocketmq
         {
             var topicRouteData = await FetchTopicRoute0(topic);
             await OnTopicRouteDataFetched(topic, topicRouteData);
-            Logger.Info(
+            Logger.LogInformation(
                 $"Fetch topic route successfully, clientId={ClientId}, 
topic={topic}, topicRouteData={topicRouteData}");
             return topicRouteData;
         }
@@ -323,7 +323,7 @@ namespace Org.Apache.Rocketmq
                 var code = invocation.Response.Status.Code;
                 if (!Proto.Code.Ok.Equals(code))
                 {
-                    Logger.Error($"Failed to fetch topic route, 
clientId={ClientId}, topic={topic}, code={code}, " +
+                    Logger.LogError($"Failed to fetch topic route, 
clientId={ClientId}, topic={topic}, code={code}, " +
                                  
$"statusMessage={invocation.Response.Status.Message}");
                 }
 
@@ -334,7 +334,7 @@ namespace Org.Apache.Rocketmq
             }
             catch (Exception e)
             {
-                Logger.Error(e, $"Failed to fetch topic route, 
clientId={ClientId}, topic={topic}");
+                Logger.LogError(e, $"Failed to fetch topic route, 
clientId={ClientId}, topic={topic}");
                 throw;
             }
         }
@@ -364,10 +364,10 @@ namespace Org.Apache.Rocketmq
 
                         if (code.Equals(Proto.Code.Ok))
                         {
-                            Logger.Info($"Send heartbeat successfully, 
endpoints={item}, clientId={ClientId}");
+                            Logger.LogInformation($"Send heartbeat 
successfully, endpoints={item}, clientId={ClientId}");
                             if (Isolated.TryRemove(item, out _))
                             {
-                                Logger.Info($"Rejoin endpoints which was 
isolated before, endpoints={item}, " +
+                                Logger.LogInformation($"Rejoin endpoints which 
was isolated before, endpoints={item}, " +
                                             $"clientId={ClientId}");
                             }
 
@@ -375,18 +375,18 @@ namespace Org.Apache.Rocketmq
                         }
 
                         var statusMessage = invocation.Response.Status.Message;
-                        Logger.Info($"Failed to send heartbeat, 
endpoints={item}, code={code}, " +
+                        Logger.LogInformation($"Failed to send heartbeat, 
endpoints={item}, code={code}, " +
                                     $"statusMessage={statusMessage}, 
clientId={ClientId}");
                     }
                     catch (Exception e)
                     {
-                        Logger.Error(e, $"Failed to send heartbeat, 
endpoints={item}");
+                        Logger.LogError(e, $"Failed to send heartbeat, 
endpoints={item}");
                     }
                 }
             }
             catch (Exception e)
             {
-                Logger.Error(e, $"[Bug] unexpected exception raised during 
heartbeat, clientId={ClientId}");
+                Logger.LogError(e, $"[Bug] unexpected exception raised during 
heartbeat, clientId={ClientId}");
             }
         }
 
@@ -401,7 +401,7 @@ namespace Org.Apache.Rocketmq
 
         private async void NotifyClientTermination()
         {
-            Logger.Info($"Notify remote endpoints that current client is 
terminated, clientId={ClientId}");
+            Logger.LogInformation($"Notify remote endpoints that current 
client is terminated, clientId={ClientId}");
             var endpoints = GetTotalRouteEndpoints();
             var request = WrapNotifyClientTerminationRequest();
             foreach (var item in endpoints)
@@ -414,7 +414,7 @@ namespace Org.Apache.Rocketmq
                 }
                 catch (Exception e)
                 {
-                    Logger.Error(e, $"Failed to notify client's termination, 
clientId=${ClientId}, " +
+                    Logger.LogError(e, $"Failed to notify client's 
termination, clientId=${ClientId}, " +
                                     $"endpoints=${item}");
                 }
             }
@@ -435,14 +435,14 @@ namespace Org.Apache.Rocketmq
         internal virtual void OnRecoverOrphanedTransactionCommand(Endpoints 
endpoints,
             Proto.RecoverOrphanedTransactionCommand command)
         {
-            Logger.Warn($"Ignore orphaned transaction recovery command from 
remote, which is not expected, " +
-                        $"clientId={ClientId}, endpoints={endpoints}");
+            Logger.LogWarning($"Ignore orphaned transaction recovery command 
from remote, which is not expected, " +
+                              $"clientId={ClientId}, endpoints={endpoints}");
         }
 
         internal async void OnVerifyMessageCommand(Endpoints endpoints, 
Proto.VerifyMessageCommand command)
         {
             // Only push consumer support message consumption verification.
-            Logger.Warn($"Ignore verify message command from remote, which is 
not expected, clientId={ClientId}, " +
+            Logger.LogWarning($"Ignore verify message command from remote, 
which is not expected, clientId={ClientId}, " +
                         $"endpoints={endpoints}, command={command}");
             var status = new Proto.Status
             {
@@ -466,8 +466,8 @@ namespace Org.Apache.Rocketmq
         internal async void OnPrintThreadStackTraceCommand(Endpoints endpoints,
             Proto.PrintThreadStackTraceCommand command)
         {
-            Logger.Warn("Ignore thread stack trace printing command from 
remote because it is still not supported, " +
-                        $"clientId={ClientId}, endpoints={endpoints}");
+            Logger.LogWarning("Ignore thread stack trace printing command from 
remote because it is still not supported, " +
+                              $"clientId={ClientId}, endpoints={endpoints}");
             var status = new Proto.Status
             {
                 Code = Proto.Code.Unsupported,
diff --git a/csharp/rocketmq-client-csharp/ClientLoggerInterceptor.cs 
b/csharp/rocketmq-client-csharp/ClientLoggerInterceptor.cs
index 6f990de7..7631bdfe 100644
--- a/csharp/rocketmq-client-csharp/ClientLoggerInterceptor.cs
+++ b/csharp/rocketmq-client-csharp/ClientLoggerInterceptor.cs
@@ -19,14 +19,14 @@ using System;
 using System.Threading.Tasks;
 using Grpc.Core;
 using Grpc.Core.Interceptors;
-using NLog;
+using Microsoft.Extensions.Logging;
 
 namespace Org.Apache.Rocketmq
 {
     public class ClientLoggerInterceptor : Interceptor
     {
 
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<ClientLoggerInterceptor>();
 
         public override TResponse BlockingUnaryCall<TRequest, TResponse>(
             TRequest request,
@@ -55,7 +55,7 @@ namespace Org.Apache.Rocketmq
         private async Task<TResponse> 
HandleResponse<TResponse>(Task<TResponse> t)
         {
             var response = await t;
-            Logger.Trace($"Response received: {response}");
+            Logger.LogTrace($"Response received: {response}");
             return response;
         }
 
@@ -94,7 +94,7 @@ namespace Org.Apache.Rocketmq
             where TRequest : class
             where TResponse : class
         {
-            Logger.Trace($"Starting call. Type: {method.Type}. Request: 
{typeof(TRequest)}. Response: {typeof(TResponse)}");
+            Logger.LogTrace($"Starting call. Type: {method.Type}. Request: 
{typeof(TRequest)}. Response: {typeof(TResponse)}");
         }
 
         private void AddCallerMetadata<TRequest, TResponse>(ref 
ClientInterceptorContext<TRequest, TResponse> context)
diff --git a/csharp/rocketmq-client-csharp/ClientMeter.cs 
b/csharp/rocketmq-client-csharp/ClientMeter.cs
index e4360cd1..2e215556 100644
--- a/csharp/rocketmq-client-csharp/ClientMeter.cs
+++ b/csharp/rocketmq-client-csharp/ClientMeter.cs
@@ -15,14 +15,14 @@
  * limitations under the License.
  */
 
-using NLog;
+using Microsoft.Extensions.Logging;
 using OpenTelemetry.Metrics;
 
 namespace Org.Apache.Rocketmq
 {
     public class ClientMeter
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<ClientMeter>();
 
         public ClientMeter(Endpoints endpoints, MeterProvider meterProvider, 
string clientId)
         {
@@ -58,9 +58,9 @@ namespace Org.Apache.Rocketmq
                 return;
             }
 
-            Logger.Info($"Begin to shutdown the client meter, 
clientId={ClientId}, endpoints={Endpoints}");
+            Logger.LogInformation($"Begin to shutdown the client meter, 
clientId={ClientId}, endpoints={Endpoints}");
             MeterProvider.Shutdown();
-            Logger.Info($"Shutdown the client meter successfully, 
clientId={ClientId}, endpoints={Endpoints}");
+            Logger.LogInformation($"Shutdown the client meter successfully, 
clientId={ClientId}, endpoints={Endpoints}");
         }
 
         public bool Satisfy(Metric metric)
diff --git a/csharp/rocketmq-client-csharp/ClientMeterManager.cs 
b/csharp/rocketmq-client-csharp/ClientMeterManager.cs
index dc856edd..5da0151b 100644
--- a/csharp/rocketmq-client-csharp/ClientMeterManager.cs
+++ b/csharp/rocketmq-client-csharp/ClientMeterManager.cs
@@ -18,7 +18,7 @@
 using System;
 using System.Diagnostics.Metrics;
 using System.Net.Http;
-using NLog;
+using Microsoft.Extensions.Logging;
 using OpenTelemetry;
 using OpenTelemetry.Exporter;
 using OpenTelemetry.Metrics;
@@ -28,7 +28,7 @@ namespace Org.Apache.Rocketmq
 {
     public class ClientMeterManager
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<ClientMeterManager>();
         private const string MeterName = "Apache.RocketMQ.Client";
         private const string Version = "1.0";
         private const int MetricExportPeriodInMillis = 60 * 1000;
@@ -59,14 +59,14 @@ namespace Org.Apache.Rocketmq
                 var clientId = _client.GetClientId();
                 if (_clientMeter.Satisfy(metric))
                 {
-                    Logger.Info(
+                    Logger.LogInformation(
                         $"Metric settings is satisfied by the current message 
meter, metric={metric}, clientId={clientId}");
                     return;
                 }
 
                 if (!metric.On)
                 {
-                    Logger.Info($"Metric is off, clientId={clientId}");
+                    Logger.LogInformation($"Metric is off, 
clientId={clientId}");
                     _clientMeter.Shutdown();
                     _clientMeter = ClientMeter.DisabledInstance(clientId);
                     return;
@@ -105,7 +105,7 @@ namespace Org.Apache.Rocketmq
                 var exist = _clientMeter;
                 _clientMeter = new ClientMeter(metric.Endpoints, 
meterProvider, clientId);
                 exist.Shutdown();
-                Logger.Info($"Metric is on, endpoints={metric.Endpoints}, 
clientId={clientId}");
+                Logger.LogInformation($"Metric is on, 
endpoints={metric.Endpoints}, clientId={clientId}");
             }
         }
 
diff --git a/csharp/rocketmq-client-csharp/MessageView.cs 
b/csharp/rocketmq-client-csharp/MessageView.cs
index 63906344..4d8824d4 100644
--- a/csharp/rocketmq-client-csharp/MessageView.cs
+++ b/csharp/rocketmq-client-csharp/MessageView.cs
@@ -19,8 +19,7 @@ using Proto = Apache.Rocketmq.V2;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Security.Cryptography;
-using NLog;
+using Microsoft.Extensions.Logging;
 
 namespace Org.Apache.Rocketmq
 {
@@ -29,7 +28,7 @@ namespace Org.Apache.Rocketmq
     /// </summary>
     public class MessageView
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<MessageView>();
 
         internal readonly MessageQueue MessageQueue;
         internal readonly string ReceiptHandle;
@@ -125,7 +124,7 @@ namespace Org.Apache.Rocketmq
                 case Proto.DigestType.Unspecified:
                 default:
                     {
-                        Logger.Error(
+                        Logger.LogError(
                             $"Unsupported message body digest algorithm," +
                             $"digestType={type}, topic={topic}, 
messageId={messageId}");
                         break;
@@ -148,7 +147,7 @@ namespace Org.Apache.Rocketmq
                 case Proto.Encoding.Unspecified:
                 default:
                     {
-                        Logger.Error($"Unsupported message encoding 
algorithm," +
+                        Logger.LogError($"Unsupported message encoding 
algorithm," +
                                      $" topic={topic}, messageId={messageId}, 
bodyEncoding={bodyEncoding}");
                         break;
                     }
diff --git a/csharp/rocketmq-client-csharp/MqLogManager.cs 
b/csharp/rocketmq-client-csharp/MqLogManager.cs
index 1e68ea43..a6bde949 100644
--- a/csharp/rocketmq-client-csharp/MqLogManager.cs
+++ b/csharp/rocketmq-client-csharp/MqLogManager.cs
@@ -16,50 +16,63 @@
  */
 
 using System;
-using NLog;
+using Microsoft.Extensions.Logging;
 using NLog.Config;
+using NLog.Extensions.Logging;
 using NLog.Layouts;
 using NLog.Targets;
 using NLog.Targets.Wrappers;
+using LogLevel = NLog.LogLevel;
 
 namespace Org.Apache.Rocketmq
 {
-    /**
-     * RocketMQ Log Manager.
-     *
-     * Configure component logging, please refer to 
https://github.com/NLog/NLog/wiki/Configure-component-logging
-     */
+    /// <summary>
+    /// RocketMQ Log Manager.
+    /// Use NLog as the default logger and support custom logger factory by 
using <see cref="UseLoggerFactory"/>.
+    /// To configure the logger factory, please refer to 
https://learn.microsoft.com/en-us/dotnet/core/extensions/logging.
+    /// </summary>
     public static class MqLogManager
     {
-        public static LogFactory Instance => LazyInstance.Value;
-
-        private static readonly Lazy<LogFactory> LazyInstance = new 
Lazy<LogFactory>(BuildLogFactory);
+        private static ILoggerFactory _loggerFactory;
 
         private const string FileLogLevelKey = "rocketmq_log_level";
         private const string FileLogLevel = "Info";
 
-        private const string ConsoleAppenderEnabledKey = 
"mq_consoleAppender_enabled";
-        private const string ConsoleAppenderEnabled = "false";
-        private const string ConsoleAppenderLogLevel = "Off";
-
-
         private const string FileLogRootKey = "rocketmq_log_root";
 
         private const string FileMaxIndexKey = "rocketmq_log_file_maxIndex";
         private const string FileMaxIndex = "10";
 
-        private static LogFactory BuildLogFactory()
+        static MqLogManager()
+        {
+            _loggerFactory = BuildDefaultLoggerFactory();
+        }
+
+        public static ILogger<T> CreateLogger<T>()
+        {
+            return _loggerFactory.CreateLogger<T>();
+        }
+
+        public static ILogger CreateLogger(string categoryName)
+        {
+            return _loggerFactory.CreateLogger(categoryName);
+        }
+
+        public static void UseLoggerFactory(ILoggerFactory loggerFactory)
+        {
+            _loggerFactory = loggerFactory ?? throw new 
ArgumentNullException(nameof(loggerFactory));
+        }
+
+        // Build default logger factory with NLog.
+        // Configure component logging, please refer to 
https://github.com/NLog/NLog/wiki/Configure-component-logging
+        private static ILoggerFactory BuildDefaultLoggerFactory()
         {
             var fileLogLevel = 
Environment.GetEnvironmentVariable(FileLogLevelKey) ?? FileLogLevel;
-            var consoleAppenderEnabled =
-                Environment.GetEnvironmentVariable(ConsoleAppenderEnabledKey) 
?? ConsoleAppenderEnabled;
-            var consoleLogLevel = bool.Parse(consoleAppenderEnabled) ? 
fileLogLevel : ConsoleAppenderLogLevel;
             var fileLogRoot = 
Environment.GetEnvironmentVariable(FileLogRootKey) ??
                               
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
             var fileMaxIndexStr = 
Environment.GetEnvironmentVariable(FileMaxIndexKey) ?? FileMaxIndex;
             var fileMaxIndex = int.Parse(fileMaxIndexStr);
 
-
             var config = new LoggingConfiguration();
             var fileTarget = new FileTarget();
             fileTarget.Name = "log_file";
@@ -92,12 +105,9 @@ namespace Org.Apache.Rocketmq
             var asyncFileRule = new LoggingRule("*", 
LogLevel.FromString(fileLogLevel), asyncTargetWrapper);
             config.LoggingRules.Add(asyncFileRule);
 
-            var consoleRule = new LoggingRule("*", 
LogLevel.FromString(consoleLogLevel), consoleTarget);
-            config.LoggingRules.Add(consoleRule);
+            var loggerFactory = LoggerFactory.Create(builder => 
builder.AddNLog(config));
 
-            var logFactory = new LogFactory();
-            logFactory.Configuration = config;
-            return logFactory;
+            return loggerFactory;
         }
     }
 }
\ No newline at end of file
diff --git a/csharp/rocketmq-client-csharp/Producer.cs 
b/csharp/rocketmq-client-csharp/Producer.cs
index 78ee4e34..136bdada 100644
--- a/csharp/rocketmq-client-csharp/Producer.cs
+++ b/csharp/rocketmq-client-csharp/Producer.cs
@@ -22,15 +22,15 @@ using System.Diagnostics;
 using System.Diagnostics.Metrics;
 using System.Linq;
 using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
 using Proto = Apache.Rocketmq.V2;
-using NLog;
 using Org.Apache.Rocketmq.Error;
 
 namespace Org.Apache.Rocketmq
 {
     public class Producer : Client, IAsyncDisposable, IDisposable
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<Producer>();
         private readonly ConcurrentDictionary<string /* topic */, 
PublishingLoadBalancer> _publishingRouteDataCache;
         internal readonly PublishingSettings PublishingSettings;
         private readonly ConcurrentDictionary<string, bool> _publishingTopics;
@@ -61,9 +61,9 @@ namespace Org.Apache.Rocketmq
             try
             {
                 State = State.Starting;
-                Logger.Info($"Begin to start the rocketmq producer, 
clientId={ClientId}");
+                Logger.LogInformation($"Begin to start the rocketmq producer, 
clientId={ClientId}");
                 await base.Start();
-                Logger.Info($"The rocketmq producer starts successfully, 
clientId={ClientId}");
+                Logger.LogInformation($"The rocketmq producer starts 
successfully, clientId={ClientId}");
                 State = State.Running;
             }
             catch (Exception)
@@ -90,9 +90,9 @@ namespace Org.Apache.Rocketmq
             try
             {
                 State = State.Stopping;
-                Logger.Info($"Begin to shutdown the rocketmq producer, 
clientId={ClientId}");
+                Logger.LogInformation($"Begin to shutdown the rocketmq 
producer, clientId={ClientId}");
                 await base.Shutdown();
-                Logger.Info($"Shutdown the rocketmq producer successfully, 
clientId={ClientId}");
+                Logger.LogInformation($"Shutdown the rocketmq producer 
successfully, clientId={ClientId}");
                 State = State.Terminated;
             }
             catch (Exception)
@@ -230,7 +230,7 @@ namespace Org.Apache.Rocketmq
                     var sendReceipt = sendReceipts.First();
                     if (attempt > 1)
                     {
-                        Logger.Info(
+                        Logger.LogInformation(
                             $"Re-send message successfully, 
topic={message.Topic}, messageId={sendReceipt.MessageId}," +
                             $" maxAttempts={maxAttempts}, 
endpoints={endpoints}, clientId={ClientId}");
                     }
@@ -245,35 +245,35 @@ namespace Org.Apache.Rocketmq
                     Isolated[endpoints] = true;
                     if (attempt >= maxAttempts)
                     {
-                        Logger.Error(e, "Failed to send message finally, run 
out of attempt times, " +
-                                        $"topic={message.Topic}, 
maxAttempt={maxAttempts}, attempt={attempt}, " +
-                                        $"endpoints={endpoints}, 
messageId={message.MessageId}, clientId={ClientId}");
+                        Logger.LogError(e, "Failed to send message finally, 
run out of attempt times, " +
+                                                  $"topic={message.Topic}, 
maxAttempt={maxAttempts}, attempt={attempt}, " +
+                                                  $"endpoints={endpoints}, 
messageId={message.MessageId}, clientId={ClientId}");
                         throw;
                     }
 
                     if (MessageType.Transaction == message.MessageType)
                     {
-                        Logger.Error(e, "Failed to send transaction message, 
run out of attempt times, " +
-                                        $"topic={message.Topic}, maxAttempt=1, 
attempt={attempt}, " +
-                                        $"endpoints={endpoints}, 
messageId={message.MessageId}, clientId={ClientId}");
+                        Logger.LogError(e, "Failed to send transaction 
message, run out of attempt times, " +
+                                                  $"topic={message.Topic}, 
maxAttempt=1, attempt={attempt}, " +
+                                                  $"endpoints={endpoints}, 
messageId={message.MessageId}, clientId={ClientId}");
                         throw;
                     }
 
                     if (!(exception is TooManyRequestsException))
                     {
                         // Retry immediately if the request is not throttled.
-                        Logger.Warn(e, $"Failed to send message, 
topic={message.Topic}, maxAttempts={maxAttempts}, " +
-                                       $"attempt={attempt}, 
endpoints={endpoints}, messageId={message.MessageId}," +
-                                       $" clientId={ClientId}");
+                        Logger.LogWarning(e, $"Failed to send message, 
topic={message.Topic}, maxAttempts={maxAttempts}, " +
+                                              $"attempt={attempt}, 
endpoints={endpoints}, messageId={message.MessageId}," +
+                                              $" clientId={ClientId}");
                         continue;
                     }
 
                     var nextAttempt = 1 + attempt;
                     var delay = retryPolicy.GetNextAttemptDelay(nextAttempt);
                     await Task.Delay(delay);
-                    Logger.Warn(e, "Failed to send message due to too many 
request, would attempt to resend " +
-                                   $"after {delay}, topic={message.Topic}, 
maxAttempts={maxAttempts}, attempt={attempt}, " +
-                                   $"endpoints={endpoints}, 
messageId={message.MessageId}, clientId={ClientId}");
+                    Logger.LogWarning(e, "Failed to send message due to too 
many request, would attempt to resend " +
+                                                $"after {delay}, 
topic={message.Topic}, maxAttempts={maxAttempts}, attempt={attempt}, " +
+                                                $"endpoints={endpoints}, 
messageId={message.MessageId}, clientId={ClientId}");
                 }
                 finally
                 {
@@ -301,8 +301,8 @@ namespace Org.Apache.Rocketmq
             var messageId = command.Message.SystemProperties.MessageId;
             if (null == _checker)
             {
-                Logger.Error($"No transaction checker registered, ignore it, 
messageId={messageId}, " +
-                             $"transactionId={command.TransactionId}, 
endpoints={endpoints}, clientId={ClientId}");
+                Logger.LogError($"No transaction checker registered, ignore 
it, messageId={messageId}, " +
+                                       
$"transactionId={command.TransactionId}, endpoints={endpoints}, 
clientId={ClientId}");
                 return;
             }
 
diff --git a/csharp/rocketmq-client-csharp/PublishingSettings.cs 
b/csharp/rocketmq-client-csharp/PublishingSettings.cs
index 22423b56..a5ab74d4 100644
--- a/csharp/rocketmq-client-csharp/PublishingSettings.cs
+++ b/csharp/rocketmq-client-csharp/PublishingSettings.cs
@@ -19,14 +19,14 @@ using System;
 using System.Collections.Concurrent;
 using System.Linq;
 using Google.Protobuf.WellKnownTypes;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Proto = Apache.Rocketmq.V2;
 
 namespace Org.Apache.Rocketmq
 {
     public class PublishingSettings : Settings
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<PublishingSettings>();
 
         private volatile int _maxBodySizeBytes = 4 * 1024 * 1024;
         private volatile bool _validateMessageType = true;
@@ -54,7 +54,7 @@ namespace Org.Apache.Rocketmq
         {
             if (Proto.Settings.PubSubOneofCase.Publishing != 
settings.PubSubCase)
             {
-                Logger.Error($"[Bug] Issued settings does not match with the 
client type, clientId={ClientId}, " +
+                Logger.LogError($"[Bug] Issued settings does not match with 
the client type, clientId={ClientId}, " +
                              $"pubSubCase={settings.PubSubCase}, 
clientType={ClientType}");
                 return;
             }
diff --git a/csharp/rocketmq-client-csharp/RpcClient.cs 
b/csharp/rocketmq-client-csharp/RpcClient.cs
index d5c24d7f..eeff96e5 100644
--- a/csharp/rocketmq-client-csharp/RpcClient.cs
+++ b/csharp/rocketmq-client-csharp/RpcClient.cs
@@ -25,13 +25,13 @@ using Proto = Apache.Rocketmq.V2;
 using Grpc.Core;
 using Grpc.Core.Interceptors;
 using Grpc.Net.Client;
-using NLog;
+using Microsoft.Extensions.Logging;
 
 namespace Org.Apache.Rocketmq
 {
     public class RpcClient : IRpcClient
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<RpcClient>();
         private readonly Proto::MessagingService.MessagingServiceClient _stub;
         private readonly GrpcChannel _channel;
         private readonly string _target;
@@ -126,17 +126,17 @@ namespace Org.Apache.Rocketmq
             var deadline = DateTime.UtcNow.Add(timeout);
             var callOptions = new CallOptions(metadata, deadline);
             var call = _stub.ReceiveMessage(request, callOptions);
-            Logger.Debug($"ReceiveMessageRequest has been written to 
{_target}");
+            Logger.LogDebug($"ReceiveMessageRequest has been written to 
{_target}");
             var result = new List<Proto::ReceiveMessageResponse>();
             var stream = call.ResponseStream;
             while (await stream.MoveNext())
             {
                 var entry = stream.Current;
-                Logger.Debug($"Got ReceiveMessageResponse {entry} from 
{_target}");
+                Logger.LogDebug($"Got ReceiveMessageResponse {entry} from 
{_target}");
                 result.Add(entry);
             }
 
-            Logger.Debug($"Receiving messages from {_target} completed");
+            Logger.LogDebug($"Receiving messages from {_target} completed");
             return result;
         }
 
diff --git a/csharp/rocketmq-client-csharp/Session.cs 
b/csharp/rocketmq-client-csharp/Session.cs
index f41694ec..ac66d5b7 100644
--- a/csharp/rocketmq-client-csharp/Session.cs
+++ b/csharp/rocketmq-client-csharp/Session.cs
@@ -19,8 +19,8 @@ using System;
 using System.Threading;
 using System.Threading.Tasks;
 using Grpc.Core;
+using Microsoft.Extensions.Logging;
 using grpc = Grpc.Core;
-using NLog;
 using Proto = Apache.Rocketmq.V2;
 
 namespace Org.Apache.Rocketmq
@@ -28,7 +28,7 @@ namespace Org.Apache.Rocketmq
     // refer to  
https://learn.microsoft.com/en-us/aspnet/core/grpc/client?view=aspnetcore-7.0#bi-directional-streaming-call.
     public class Session
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<Session>();
 
         private static readonly TimeSpan SettingsInitializationTimeout = 
TimeSpan.FromSeconds(3);
         private readonly ManualResetEventSlim _event = new 
ManualResetEventSlim(false);
@@ -92,7 +92,7 @@ namespace Org.Apache.Rocketmq
                     {
                         case Proto.TelemetryCommand.CommandOneofCase.Settings:
                             {
-                                Logger.Info(
+                                Logger.LogInformation(
                                     $"Receive setting from remote, 
endpoints={_endpoints}, clientId={_client.GetClientId()}");
                                 _client.OnSettingsCommand(_endpoints, 
response.Settings);
                                 _event.Set();
@@ -100,7 +100,7 @@ namespace Org.Apache.Rocketmq
                             }
                         case 
Proto.TelemetryCommand.CommandOneofCase.RecoverOrphanedTransactionCommand:
                             {
-                                Logger.Info(
+                                Logger.LogInformation(
                                     $"Receive orphaned transaction recovery 
command from remote, endpoints={_endpoints}, clientId={_client.GetClientId()}");
                                 
_client.OnRecoverOrphanedTransactionCommand(_endpoints,
                                     
response.RecoverOrphanedTransactionCommand);
@@ -108,21 +108,21 @@ namespace Org.Apache.Rocketmq
                             }
                         case 
Proto.TelemetryCommand.CommandOneofCase.VerifyMessageCommand:
                             {
-                                Logger.Info(
+                                Logger.LogInformation(
                                     $"Receive message verification command 
from remote, endpoints={_endpoints}, clientId={_client.GetClientId()}");
                                 _client.OnVerifyMessageCommand(_endpoints, 
response.VerifyMessageCommand);
                                 break;
                             }
                         case 
Proto.TelemetryCommand.CommandOneofCase.PrintThreadStackTraceCommand:
                             {
-                                Logger.Info(
+                                Logger.LogInformation(
                                     $"Receive thread stack print command from 
remote, endpoints={_endpoints}, clientId={_client.GetClientId()}");
                                 
_client.OnPrintThreadStackTraceCommand(_endpoints, 
response.PrintThreadStackTraceCommand);
                                 break;
                             }
                         default:
                             {
-                                Logger.Warn(
+                                Logger.LogWarning(
                                     $"Receive unrecognized command from 
remote, endpoints={_endpoints}, command={response}, 
clientId={_client.GetClientId()}");
                                 break;
                             }
diff --git a/csharp/rocketmq-client-csharp/SimpleConsumer.cs 
b/csharp/rocketmq-client-csharp/SimpleConsumer.cs
index da372177..d16a8c5f 100644
--- a/csharp/rocketmq-client-csharp/SimpleConsumer.cs
+++ b/csharp/rocketmq-client-csharp/SimpleConsumer.cs
@@ -21,15 +21,15 @@ using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
 using Google.Protobuf.WellKnownTypes;
+using Microsoft.Extensions.Logging;
 using Proto = Apache.Rocketmq.V2;
-using NLog;
 using Org.Apache.Rocketmq.Error;
 
 namespace Org.Apache.Rocketmq
 {
     public class SimpleConsumer : Consumer, IAsyncDisposable, IDisposable
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<SimpleConsumer>();
         private readonly ConcurrentDictionary<string /* topic */, 
SubscriptionLoadBalancer> _subscriptionRouteDataCache;
         private readonly ConcurrentDictionary<string /* topic */, 
FilterExpression> _subscriptionExpressions;
         private readonly TimeSpan _awaitDuration;
@@ -79,9 +79,9 @@ namespace Org.Apache.Rocketmq
             try
             {
                 State = State.Starting;
-                Logger.Info($"Begin to start the rocketmq simple consumer, 
clientId={ClientId}");
+                Logger.LogInformation($"Begin to start the rocketmq simple 
consumer, clientId={ClientId}");
                 await base.Start();
-                Logger.Info($"The rocketmq simple consumer starts 
successfully, clientId={ClientId}");
+                Logger.LogInformation($"The rocketmq simple consumer starts 
successfully, clientId={ClientId}");
                 State = State.Running;
             }
             catch (Exception)
@@ -108,9 +108,9 @@ namespace Org.Apache.Rocketmq
             try
             {
                 State = State.Stopping;
-                Logger.Info($"Begin to shutdown the rocketmq simple consumer, 
clientId={ClientId}");
+                Logger.LogInformation($"Begin to shutdown the rocketmq simple 
consumer, clientId={ClientId}");
                 await base.Shutdown();
-                Logger.Info($"Shutdown the rocketmq simple consumer 
successfully, clientId={ClientId}");
+                Logger.LogInformation($"Shutdown the rocketmq simple consumer 
successfully, clientId={ClientId}");
                 State = State.Terminated;
             }
             catch (Exception)
diff --git a/csharp/rocketmq-client-csharp/SimpleSubscriptionSettings.cs 
b/csharp/rocketmq-client-csharp/SimpleSubscriptionSettings.cs
index c83cca7d..2b214fa1 100644
--- a/csharp/rocketmq-client-csharp/SimpleSubscriptionSettings.cs
+++ b/csharp/rocketmq-client-csharp/SimpleSubscriptionSettings.cs
@@ -19,14 +19,14 @@ using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using Google.Protobuf.WellKnownTypes;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Proto = Apache.Rocketmq.V2;
 
 namespace Org.Apache.Rocketmq
 {
     public class SimpleSubscriptionSettings : Settings
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger<SimpleSubscriptionSettings>();
 
         private readonly Resource _group;
         private readonly TimeSpan _longPollingTimeout;
@@ -46,7 +46,7 @@ namespace Org.Apache.Rocketmq
         {
             if (Proto.Settings.PubSubOneofCase.Subscription != 
settings.PubSubCase)
             {
-                Logger.Error($"[Bug] Issued settings doesn't match with the 
client type, clientId={ClientId}, " +
+                Logger.LogError($"[Bug] Issued settings doesn't match with the 
client type, clientId={ClientId}, " +
                              $"pubSubCase={settings.PubSubCase}, 
clientType={ClientType}");
             }
         }
@@ -71,7 +71,7 @@ namespace Org.Apache.Rocketmq
                         filterExpression.Type = Proto.FilterType.Sql;
                         break;
                     default:
-                        Logger.Warn($"[Bug] Unrecognized filter 
type={value.Type} for simple consumer");
+                        Logger.LogWarning($"[Bug] Unrecognized filter 
type={value.Type} for simple consumer");
                         break;
                 }
 
diff --git a/csharp/rocketmq-client-csharp/StatusChecker.cs 
b/csharp/rocketmq-client-csharp/StatusChecker.cs
index 3fecfd95..12d12fe6 100644
--- a/csharp/rocketmq-client-csharp/StatusChecker.cs
+++ b/csharp/rocketmq-client-csharp/StatusChecker.cs
@@ -16,7 +16,7 @@
  */
 
 using Google.Protobuf;
-using NLog;
+using Microsoft.Extensions.Logging;
 using Org.Apache.Rocketmq.Error;
 using Proto = Apache.Rocketmq.V2;
 
@@ -24,7 +24,7 @@ namespace Org.Apache.Rocketmq
 {
     public static class StatusChecker
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger Logger = 
MqLogManager.CreateLogger(typeof(StatusChecker).FullName);
 
         public static void Check(Proto.Status status, IMessage request, string 
requestId)
         {
@@ -101,7 +101,7 @@ namespace Org.Apache.Rocketmq
                 case Proto.Code.FailedToConsumeMessage:
                 case Proto.Code.Unspecified:
                 default:
-                    Logger.Warn($"Unrecognized status code={statusCode}, 
requestId={requestId}, statusMessage={statusMessage}");
+                    Logger.LogWarning($"Unrecognized status code={statusCode}, 
requestId={requestId}, statusMessage={statusMessage}");
                     throw new UnsupportedException((int)statusCode, requestId, 
statusMessage);
             }
         }
diff --git a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj 
b/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj
index 46a1ad40..b13ea1d1 100644
--- a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj
+++ b/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj
@@ -29,7 +29,8 @@
             <IncludeAssets>runtime; build; native; contentfiles; analyzers; 
buildtransitive</IncludeAssets>
             <PrivateAssets>all</PrivateAssets>
         </PackageReference>
-        <PackageReference Include="NLog" Version="4.7.13" />
+        <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" 
Version="3.1.32" />
+        <PackageReference Include="NLog.Extensions.Logging" Version="5.3.4" />
         <PackageReference Include="OpenTelemetry" Version="1.3.1" />
         <PackageReference Include="OpenTelemetry.Api" Version="1.3.1" />
         <PackageReference 
Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.3.1" />
diff --git a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.nlog 
b/csharp/rocketmq-client-csharp/rocketmq-client-csharp.nlog
deleted file mode 100644
index 4a5319e7..00000000
--- a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.nlog
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-      http://www.apache.org/licenses/LICENSE-2.0
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd";
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-      throwconfigexceptions="true">
-    <variables>
-        <variable name="logLevel" 
value="${environment:rocketmq.log.level:whenEmpty=Info}" />
-        <variable name="ConsoleLogLevel" 
value="${environment:rocketmq.console.log.level:whenEmpty=Off}" />
-    </variables>
-    <targets>
-        <target name="asyncFile" xsi:type="AsyncWrapper">
-            <target name="log_file" xsi:type="File"
-                    
fileName="${specialfolder:folder=UserProfile}/logs/rocketmq/rocketmq-client.log"
-                    layout="${longdate} ${level:uppercase=true:padding=-5} 
[${processid}] [${threadid}] [${callsite}:${callsite-linenumber}] ${message} 
${onexception:${exception:format=ToString,Data}}"
-                    
archiveFileName="${specialfolder:folder=UserProfile}/logs/rocketmq/rocketmq-client.{######}.log"
-                    archiveAboveSize="67108864"
-                    archiveNumbering="DateAndSequence"
-                    maxArchiveFiles="10"
-                    concurrentWrites="true"
-                    keepFileOpen="false" />
-        </target>
-        <target name="colorConsole" xsi:type="ColoredConsole"
-                useDefaultRowHighlightingRules="true"
-                layout="${longdate} ${level:uppercase=true:padding=-5} 
[${processid}] [${threadid}] [${callsite}:${callsite-linenumber}] ${message} 
${onexception:${exception:format=ToString,Data}}" >
-        </target>
-    </targets>
-    <rules>
-        <logger name="*" minLevel="${logLevel}" writeTo="asyncFile" />
-        <logger name="*" minLevel="${ConsoleLogLevel}" writeTo="colorConsole" 
/>
-    </rules>
-</nlog>
\ No newline at end of file
diff --git a/csharp/tests/MqLogManagerTest.cs b/csharp/tests/MqLogManagerTest.cs
index 076c9331..cd7b88eb 100644
--- a/csharp/tests/MqLogManagerTest.cs
+++ b/csharp/tests/MqLogManagerTest.cs
@@ -16,8 +16,8 @@
  */
 
 using System;
+using Microsoft.Extensions.Logging;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
-using NLog;
 using Org.Apache.Rocketmq;
 
 namespace tests
@@ -25,20 +25,45 @@ namespace tests
     [TestClass]
     public class MqLogManagerTest
     {
-        private static readonly Logger Logger = 
MqLogManager.Instance.GetCurrentClassLogger();
+        private static readonly ILogger DefaultLogger1;
+        private static readonly ILogger DefaultLogger2;
+        private static readonly ILogger ConsoleLogger1;
+        private static readonly ILogger ConsoleLogger2;
+
+        static MqLogManagerTest()
+        {
+            DefaultLogger1 = MqLogManager.CreateLogger<MqLogManagerTest>();
+            DefaultLogger2 = MqLogManager.CreateLogger("MqLogManagerTest2");
+
+            var loggerFactory = LoggerFactory.Create(
+                builder => builder
+                    .AddFilter("tests", LogLevel.Information)
+                    .AddConsole());
+            MqLogManager.UseLoggerFactory(loggerFactory);
+            ConsoleLogger1 = MqLogManager.CreateLogger<MqLogManagerTest>();
+            ConsoleLogger2 = MqLogManager.CreateLogger("MqLogManagerTest2");
+        }
 
         [TestMethod]
         public void TestLog()
         {
-            Logger.Trace("This is a trace message.");
-            Logger.Debug("This is a debug message.");
-            Logger.Info("This is an info message.");
-            Logger.Warn("This is a warn message.");
-            Logger.Error("This is an error message.");
-            Logger.Fatal("This is a fatal message.");
+            TestLog(DefaultLogger1);
+            TestLog(DefaultLogger2);
+            TestLog(ConsoleLogger1);
+            TestLog(ConsoleLogger2);
+        }
+
+        private void TestLog(ILogger logger)
+        {
+            logger.LogTrace("This is a trace message.");
+            logger.LogDebug("This is a debug message.");
+            logger.LogInformation("This is an info message.");
+            logger.LogWarning("This is a warn message.");
+            logger.LogError("This is an error message.");
+            logger.LogCritical("This is a critical message.");
 
-            Logger.Error(new Exception("foobar"), "this is an error message 
with exception.");
-            Logger.Fatal(new Exception("foobar"), "this is a fatal message 
with exception.");
+            logger.LogError(new Exception("foobar"), "this is an error message 
with exception.");
+            logger.LogCritical(new Exception("foobar"), "this is a critical 
message with exception.");
         }
     }
 }
\ No newline at end of file
diff --git a/csharp/tests/tests.csproj b/csharp/tests/tests.csproj
index ab8aad59..1e3b9fee 100644
--- a/csharp/tests/tests.csproj
+++ b/csharp/tests/tests.csproj
@@ -7,6 +7,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Microsoft.Extensions.Logging.Console" 
Version="3.1.32" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
     <PackageReference Include="Moq" Version="4.16.1" />
     <PackageReference Include="MSTest.TestAdapter" Version="2.2.3" />

Reply via email to