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

ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 91323af877 IGNITE-20569 .NET: Use Microsoft.Extensions.Logging instead 
of custom approach (#2874)
91323af877 is described below

commit 91323af877c2591d7238fae03c373c0539e75afe
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Fri Nov 24 15:37:19 2023 +0200

    IGNITE-20569 .NET: Use Microsoft.Extensions.Logging instead of custom 
approach (#2874)
    
    * Remove custom `ILogger` and related code
    * Adopt industry standard `Microsoft.Extensions.Logging`
    * Reference `Microsoft.Extensions.Logging.Abstractions` - contains 
interfaces only, no implementations (besides `NullLogger`)
    * `IgniteClientConfiguration` accepts `ILoggerFactory`, as recommended in 
[Logging guidance for .NET library 
authors](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging-library-authors)
    * Change all logging calls to use [Compile-time logging source 
generation](https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator)
 for max performance
      * `IsEnabled` checks are built in
    
    As a result, any popular logging library can be used with Ignite.NET, such 
as Serilog, NLog, log4net, etc.
---
 .../ManyConnectionsBenchmark.cs                    |   5 +-
 .../Apache.Ignite.Tests/Apache.Ignite.Tests.csproj |   1 +
 .../dotnet/Apache.Ignite.Tests/ConsoleLogger.cs    | 101 +++++++
 .../dotnet/Apache.Ignite.Tests/HeartbeatTests.cs   |  16 +-
 .../dotnet/Apache.Ignite.Tests/IgniteTestsBase.cs  |   6 +-
 .../dotnet/Apache.Ignite.Tests/Linq/LinqTests.cs   |  12 +-
 .../dotnet/Apache.Ignite.Tests/ListLogger.cs       | 107 ++-----
 .../Apache.Ignite.Tests/ListLoggerFactory.cs       |  92 ++++++
 .../dotnet/Apache.Ignite.Tests/LoggingTests.cs     |  60 +++-
 .../dotnet/Apache.Ignite.Tests/MultiClusterTest.cs |   5 +-
 .../dotnet/Apache.Ignite.Tests/ReconnectTests.cs   |  22 +-
 .../Apache.Ignite.Tests/SocketTimeoutTest.cs       |   5 +-
 .../dotnet/Apache.Ignite.Tests/SslTests.cs         |   4 +-
 .../dotnet/Apache.Ignite.Tests/TestUtils.cs        |   3 +
 .../dotnet/Apache.Ignite.Tests/VersionTests.cs     |   2 +-
 .../dotnet/Apache.Ignite/Apache.Ignite.csproj      |   1 +
 .../Apache.Ignite/IgniteClientConfiguration.cs     |   9 +-
 .../Apache.Ignite/Internal/ClientFailoverSocket.cs |  39 +--
 .../dotnet/Apache.Ignite/Internal/ClientSocket.cs  |  84 ++----
 .../Internal/Linq/IgniteQueryExecutor.cs           |  12 +-
 .../dotnet/Apache.Ignite/Internal/Linq/README.md   |   2 +-
 .../dotnet/Apache.Ignite/Internal/LogMessages.cs   | 207 +++++++++++++
 .../Apache.Ignite/Internal/Table/RecordView.cs     |  47 +--
 .../dotnet/Apache.Ignite/Internal/Table/Table.cs   |  11 +-
 .../dotnet/Apache.Ignite/Internal/VersionUtils.cs  |   2 +-
 .../dotnet/Apache.Ignite/Log/CategoryLogger.cs     |  95 ------
 .../dotnet/Apache.Ignite/Log/ConsoleLogger.cs      | 120 --------
 .../dotnet/Apache.Ignite/Log/IDateTimeProvider.cs  |  33 --
 .../dotnet/Apache.Ignite/Log/IIgniteLogger.cs      |  57 ----
 .../Apache.Ignite/Log/LocalDateTimeProvider.cs     |  47 ---
 .../platforms/dotnet/Apache.Ignite/Log/LogLevel.cs |  53 ----
 .../dotnet/Apache.Ignite/Log/LoggerExtensions.cs   | 333 ---------------------
 modules/platforms/dotnet/README.md                 |  29 +-
 33 files changed, 620 insertions(+), 1002 deletions(-)

diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ManyConnectionsBenchmark.cs 
b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ManyConnectionsBenchmark.cs
index 117d034426..c24eab2339 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ManyConnectionsBenchmark.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ManyConnectionsBenchmark.cs
@@ -21,7 +21,8 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Threading.Tasks;
-using Log;
+using Microsoft.Extensions.Logging;
+using Tests;
 
 /// <summary>
 /// Establishes many connections to the server node to see how it affects 
server-side performance.
@@ -57,7 +58,7 @@ public static class ManyConnectionsBenchmark
         var cfg = new IgniteClientConfiguration
         {
             RetryPolicy = new RetryNonePolicy(),
-            Logger = new ConsoleLogger { MinLevel = LogLevel.Warn },
+            LoggerFactory = 
TestUtils.GetConsoleLoggerFactory(LogLevel.Warning),
             HeartbeatInterval = TimeSpan.FromMinutes(5)
         };
 
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Tests/Apache.Ignite.Tests.csproj 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Apache.Ignite.Tests.csproj
index 0e776fe96c..12dbc80cb0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Apache.Ignite.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Apache.Ignite.Tests.csproj
@@ -31,6 +31,7 @@
         <PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
         <PackageReference Include="System.Linq.Async" Version="6.0.1" />
         <PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
+        <PackageReference Include="Microsoft.Extensions.Logging.Console" 
Version="6.0.0" />
 
         <!-- Test-only dependency to use as a reference implementation. -->
         <PackageReference Include="MessagePack" Version="[2.1.90,)" />
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/ConsoleLogger.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/ConsoleLogger.cs
new file mode 100644
index 0000000000..bdc770e82b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/ConsoleLogger.cs
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Tests;
+
+using System;
+using System.Globalization;
+using System.Text;
+using Microsoft.Extensions.Logging;
+
+/// <summary>
+/// Console logger for tests. We don't use <see 
cref="Microsoft.Extensions.Logging.Console.ConsoleLogger"/> because it is 
asynchronous,
+/// which means the log messages may not correspond to the current test.
+/// </summary>
+public class ConsoleLogger : ILogger, ILoggerFactory
+{
+    private readonly string _categoryName;
+    private readonly LogLevel _minLevel;
+
+    public ConsoleLogger(LogLevel minLevel)
+        : this(string.Empty, minLevel)
+    {
+        // No-op.
+    }
+
+    public ConsoleLogger(string categoryName, LogLevel minLevel)
+    {
+        _categoryName = categoryName;
+        _minLevel = minLevel;
+    }
+
+    public void Log<TState>(
+        LogLevel logLevel,
+        EventId eventId,
+        TState state,
+        Exception? exception,
+        Func<TState, Exception?, string> formatter)
+    {
+        if (!IsEnabled(logLevel))
+        {
+            return;
+        }
+
+        var sb = new StringBuilder().AppendFormat(
+            CultureInfo.InvariantCulture,
+            "[{0:HH:mm:ss}] [{1}] [{2}] ",
+            DateTime.Now,
+            GetLogLevelString(logLevel),
+            _categoryName);
+
+        sb.Append(formatter(state, exception));
+
+        if (exception != null)
+        {
+            sb.AppendFormat(CultureInfo.InvariantCulture, " (exception: {0})", 
exception);
+        }
+
+        Console.WriteLine(sb.ToString());
+    }
+
+    public bool IsEnabled(LogLevel logLevel) => logLevel >= _minLevel;
+
+    public IDisposable BeginScope<TState>(TState state) => new 
DisposeAction(() => { });
+
+    public void Dispose()
+    {
+        // No-op.
+    }
+
+    public ILogger CreateLogger(string categoryName) => new 
ConsoleLogger(categoryName, _minLevel);
+
+    public void AddProvider(ILoggerProvider provider) => throw new 
NotSupportedException();
+
+    private static string GetLogLevelString(LogLevel logLevel) =>
+        logLevel switch
+        {
+            LogLevel.Trace => "trce",
+            LogLevel.Debug => "dbug",
+            LogLevel.Information => "info",
+            LogLevel.Warning => "warn",
+            LogLevel.Error => "fail",
+            LogLevel.Critical => "crit",
+
+            // ReSharper disable once PatternIsRedundant
+            LogLevel.None or _ => throw new 
ArgumentOutOfRangeException(nameof(logLevel))
+        };
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/HeartbeatTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/HeartbeatTests.cs
index 010425a634..bae85b5fb3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/HeartbeatTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/HeartbeatTests.cs
@@ -19,7 +19,7 @@ namespace Apache.Ignite.Tests
 {
     using System;
     using System.Threading.Tasks;
-    using Log;
+    using Microsoft.Extensions.Logging;
     using NUnit.Framework;
 
     /// <summary>
@@ -30,12 +30,12 @@ namespace Apache.Ignite.Tests
         [Test]
         public async Task TestServerDoesNotDisconnectIdleClientWithHeartbeats()
         {
-            var logger = new ListLogger(enabledLevels: new[] { LogLevel.Error, 
LogLevel.Warn });
+            var logger = new ListLoggerFactory(enabledLevels: new[] { 
LogLevel.Error, LogLevel.Warning });
 
             var cfg = new IgniteClientConfiguration
             {
                 Endpoints = { "127.0.0.1:" + ServerPort },
-                Logger = logger
+                LoggerFactory = logger
             };
             using var client = await IgniteClient.StartAsync(cfg);
 
@@ -53,7 +53,7 @@ namespace Apache.Ignite.Tests
             var log = await 
ConnectAndGetLog(IgniteClientConfiguration.DefaultHeartbeatInterval);
 
             StringAssert.Contains(
-                "[Warn] Server-side IdleTimeout is 00:00:03, " +
+                "[Warning] Server-side IdleTimeout is 00:00:03, " +
                 "configured IgniteClientConfiguration.HeartbeatInterval is 
00:00:30, which is longer than recommended IdleTimeout / 3. " +
                 "Overriding heartbeat interval with max(IdleTimeout / 3, 
500ms): 00:00:01",
                 log);
@@ -65,7 +65,7 @@ namespace Apache.Ignite.Tests
             var log = await ConnectAndGetLog(TimeSpan.FromMilliseconds(50));
 
             StringAssert.Contains(
-                "[Info] Server-side IdleTimeout is 00:00:03, " +
+                "[Information] Server-side IdleTimeout is 00:00:03, " +
                 "using configured IgniteClientConfiguration.HeartbeatInterval: 
00:00:00.0500000",
                 log);
         }
@@ -76,7 +76,7 @@ namespace Apache.Ignite.Tests
             var log = await ConnectAndGetLog(TimeSpan.FromSeconds(4));
 
             StringAssert.Contains(
-                "[Warn] Server-side IdleTimeout is 00:00:03, " +
+                "[Warning] Server-side IdleTimeout is 00:00:03, " +
                 "configured IgniteClientConfiguration.HeartbeatInterval is 
00:00:04, which is longer than recommended IdleTimeout / 3. " +
                 "Overriding heartbeat interval with max(IdleTimeout / 3, 
500ms): 00:00:01",
                 log);
@@ -91,11 +91,11 @@ namespace Apache.Ignite.Tests
 
         private static async Task<string> ConnectAndGetLog(TimeSpan 
heartbeatInterval)
         {
-            var logger = new ListLogger();
+            var logger = new ListLoggerFactory();
 
             var cfg = new IgniteClientConfiguration(GetConfig())
             {
-                Logger = logger,
+                LoggerFactory = logger,
                 HeartbeatInterval = heartbeatInterval
             };
 
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/IgniteTestsBase.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/IgniteTestsBase.cs
index c5f46c5953..da222099d9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/IgniteTestsBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/IgniteTestsBase.cs
@@ -23,7 +23,7 @@ namespace Apache.Ignite.Tests
     using System.Threading.Tasks;
     using Ignite.Table;
     using Internal.Proto;
-    using Log;
+    using Microsoft.Extensions.Logging;
     using NUnit.Framework;
     using Table;
 
@@ -180,13 +180,13 @@ namespace Apache.Ignite.Tests
                 "127.0.0.1:" + ServerNode.Port,
                 "127.0.0.1:" + (ServerNode.Port + 1)
             },
-            Logger = new ConsoleLogger { MinLevel = LogLevel.Trace }
+            LoggerFactory = TestUtils.GetConsoleLoggerFactory(LogLevel.Trace)
         };
 
         protected static IgniteClientConfiguration 
GetConfig(IEnumerable<IgniteProxy> proxies) =>
             new(proxies.Select(x => x.Endpoint).ToArray())
             {
-                Logger = new ConsoleLogger { MinLevel = LogLevel.Trace }
+                LoggerFactory = 
TestUtils.GetConsoleLoggerFactory(LogLevel.Trace)
             };
 
         protected List<IgniteProxy> GetProxies()
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Linq/LinqTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Linq/LinqTests.cs
index 8d0b353c2f..2d91b21acc 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Linq/LinqTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Linq/LinqTests.cs
@@ -24,7 +24,7 @@ using System.Linq;
 using System.Threading.Tasks;
 using Ignite.Sql;
 using Ignite.Table;
-using Log;
+using Microsoft.Extensions.Logging;
 using NodaTime;
 using NUnit.Framework;
 using Table;
@@ -689,8 +689,8 @@ public partial class LinqTests : IgniteTestsBase
     public async Task TestGeneratedSqlIsLoggedWithDebugLevel()
     {
         var config = GetConfig();
-        var logger = new ListLogger { EnabledLevels = { LogLevel.Debug } };
-        config.Logger = logger;
+        var logger = new ListLoggerFactory(new[] { LogLevel.Debug });
+        config.LoggerFactory = logger;
 
         using var client = await IgniteClient.StartAsync(config);
         var table = (await client.Tables.GetTableAsync(TableName))!;
@@ -700,16 +700,16 @@ public partial class LinqTests : IgniteTestsBase
             .Where(x => x.Key > 5 && x.Val!.ToUpper() == "abc")
             .SumAsync(x => x.Key);
 
-        var logEntry = logger.Entries.Single(x => x.Category == 
"IgniteQueryExecutor");
+        var logEntry = logger.Entries.Single(x => x.Category == 
"Apache.Ignite.Internal.Linq.IgniteQueryExecutor");
 
         var expectedMessage =
-            "Executing SQL statement generated by LINQ provider: SqlStatement 
{ " +
+            "Executing SQL statement generated by LINQ provider 
[statement=SqlStatement { " +
             "Query = select sum(_T0.KEY) from PUBLIC.TBL1 as _T0 where 
((_T0.KEY > ?) and (upper(_T0.VAL) IS NOT DISTINCT FROM ?)), " +
             "Timeout = 00:00:15, " +
             "Schema = PUBLIC, " +
             "PageSize = 123, " +
             "Properties = { } }, " +
-            "parameters: 5, abc";
+            "parameters=5, abc]";
 
         Assert.AreEqual(expectedMessage, logEntry.Message);
         Assert.AreEqual(LogLevel.Debug, logEntry.Level);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/ListLogger.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/ListLogger.cs
index 77b443369f..7a117ec98c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/ListLogger.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/ListLogger.cs
@@ -21,28 +21,25 @@ namespace Apache.Ignite.Tests
     using System.Collections.Generic;
     using System.Diagnostics.CodeAnalysis;
     using System.Linq;
-    using Internal.Common;
-    using Log;
+    using Microsoft.Extensions.Logging;
     using NUnit.Framework;
 
     /// <summary>
     /// Stores log entries in a list.
     /// </summary>
-    public class ListLogger : IIgniteLogger
+    public class ListLogger : ILogger
     {
-        /** */
-        private readonly List<Entry> _entries = new();
+        private readonly string _categoryName;
+        private readonly Action<Entry> _addEntry;
 
-        /** */
-        private readonly object _lock = new();
-
-        /** */
-        private readonly IIgniteLogger? _wrappedLogger;
-
-        public ListLogger(IIgniteLogger? wrappedLogger = null, 
IEnumerable<LogLevel>? enabledLevels = null)
+        public ListLogger(
+            string categoryName,
+            Action<Entry> addEntry,
+            IEnumerable<LogLevel>? enabledLevels = null)
         {
-            _wrappedLogger = wrappedLogger;
-            EnabledLevels = enabledLevels?.ToList() ?? new() { LogLevel.Debug, 
LogLevel.Info, LogLevel.Warn, LogLevel.Error };
+            _categoryName = categoryName;
+            _addEntry = addEntry;
+            EnabledLevels = enabledLevels?.ToList() ?? new() { LogLevel.Debug, 
LogLevel.Information, LogLevel.Warning, LogLevel.Error };
         }
 
         /// <summary>
@@ -50,83 +47,29 @@ namespace Apache.Ignite.Tests
         /// </summary>
         public List<LogLevel> EnabledLevels { get; }
 
-        /// <summary>
-        /// Gets the entries.
-        /// </summary>
-        public List<Entry> Entries
-        {
-            get
-            {
-                lock (_lock)
-                {
-                    return _entries.ToList();
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the log as a string.
-        /// </summary>
-        /// <returns>Log string.</returns>
-        public string GetLogString()
-        {
-            lock (_lock)
-            {
-                return _entries.Select(e => $"{e.Category} [{e.Level}] 
{e.Message}").StringJoin();
-            }
-        }
-
-        /// <summary>
-        /// Clears the entries.
-        /// </summary>
-        public void Clear()
-        {
-            lock (_lock)
-            {
-                _entries.Clear();
-            }
-        }
-
-        /** <inheritdoc /> */
-        public void Log(
-            LogLevel level,
-            string message,
-            object?[]? args,
-            IFormatProvider? formatProvider,
-            string? category,
-            string? nativeErrorInfo,
-            Exception? ex)
+        public void Log<TState>(
+            LogLevel logLevel,
+            EventId eventId,
+            TState state,
+            Exception? exception,
+            Func<TState, Exception?, string> formatter)
         {
-            Assert.NotNull(message);
+            Assert.NotNull(state);
+            Assert.NotNull(formatter);
 
-            if (!IsEnabled(level))
+            if (!IsEnabled(logLevel))
             {
                 return;
             }
 
-            _wrappedLogger?.Log(level, message, args, formatProvider, 
category, nativeErrorInfo, ex);
-
-            lock (_lock)
-            {
-                if (args != null)
-                {
-                    message = string.Format(formatProvider, message, args);
-                }
-
-                if (ex != null)
-                {
-                    message += Environment.NewLine + ex;
-                }
-
-                _entries.Add(new Entry(message, level, category, ex));
-            }
+            var message = formatter(state, exception);
+            _addEntry(new Entry(message, logLevel, _categoryName, exception));
         }
 
         /** <inheritdoc /> */
-        public bool IsEnabled(LogLevel level)
-        {
-            return EnabledLevels.Contains(level);
-        }
+        public bool IsEnabled(LogLevel logLevel) => 
EnabledLevels.Contains(logLevel);
+
+        public IDisposable BeginScope<TState>(TState state) => throw new 
NotImplementedException();
 
         [SuppressMessage("Microsoft.Design", 
"CA1034:NestedTypesShouldNotBeVisible", Justification = "Tests.")]
         public record Entry(string Message, LogLevel Level, string? Category, 
Exception? Exception);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/ListLoggerFactory.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/ListLoggerFactory.cs
new file mode 100644
index 0000000000..62d5e3d8d4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/ListLoggerFactory.cs
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Tests;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Internal.Common;
+using Microsoft.Extensions.Logging;
+
+public class ListLoggerFactory : ILoggerFactory
+{
+    private readonly List<ListLogger.Entry> _entries = new();
+
+    private readonly object _lock = new();
+
+    public ListLoggerFactory(ICollection<LogLevel>? enabledLevels = null)
+    {
+        EnabledLevels = enabledLevels;
+    }
+
+    public ICollection<LogLevel>? EnabledLevels { get; }
+
+    /// <summary>
+    /// Gets the entries.
+    /// </summary>
+    public List<ListLogger.Entry> Entries
+    {
+        get
+        {
+            lock (_lock)
+            {
+                return _entries.ToList();
+            }
+        }
+    }
+
+    public void Dispose()
+    {
+        // No-op.
+    }
+
+    public ILogger CreateLogger(string categoryName) => new 
ListLogger(categoryName, AddEntry, enabledLevels: EnabledLevels);
+
+    public void AddProvider(ILoggerProvider provider) => throw new 
NotSupportedException();
+
+    /// <summary>
+    /// Gets the log as a string.
+    /// </summary>
+    /// <returns>Log string.</returns>
+    public string GetLogString()
+    {
+        lock (_lock)
+        {
+            return _entries.Select(e => $"{e.Category} [{e.Level}] 
{e.Message}").StringJoin();
+        }
+    }
+
+    /// <summary>
+    /// Clears the entries.
+    /// </summary>
+    public void Clear()
+    {
+        lock (_lock)
+        {
+            _entries.Clear();
+        }
+    }
+
+    private void AddEntry(ListLogger.Entry entry)
+    {
+        lock (_lock)
+        {
+            _entries.Add(entry);
+        }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/LoggingTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/LoggingTests.cs
index 77e726a3b3..1b52c32645 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/LoggingTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/LoggingTests.cs
@@ -19,9 +19,11 @@ namespace Apache.Ignite.Tests;
 
 using System;
 using System.Diagnostics.CodeAnalysis;
+using System.IO;
 using System.Threading.Tasks;
 using Internal;
-using Log;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Console;
 using NUnit.Framework;
 
 /// <summary>
@@ -33,11 +35,8 @@ public class LoggingTests
     [SuppressMessage("ReSharper", "AccessToDisposedClosure", Justification = 
"Reviewed.")]
     public async Task TestBasicLogging()
     {
-        var logger = new ListLogger(new ConsoleLogger { MinLevel = 
LogLevel.Trace });
-        logger.EnabledLevels.Clear();
-        logger.EnabledLevels.AddRange(Enum.GetValues<LogLevel>());
-
-        var cfg = new IgniteClientConfiguration { Logger = logger };
+        var logger = new ListLoggerFactory(Enum.GetValues<LogLevel>());
+        var cfg = new IgniteClientConfiguration { LoggerFactory = logger };
 
         using var servers = FakeServerGroup.Create(3);
         using (var client = await servers.ConnectClientAsync(cfg))
@@ -51,15 +50,48 @@ public class LoggingTests
         var log = logger.GetLogString();
 
         StringAssert.Contains(
-            $"ClientFailoverSocket [Info] Ignite.NET client version 
{VersionUtils.GetInformationalVersion()} is starting",
+            $"Apache.Ignite.Internal.ClientFailoverSocket [Information] " +
+            $"Ignite.NET client version {VersionUtils.InformationalVersion} is 
starting",
             log);
 
-        StringAssert.Contains("Connection established", log);
-        StringAssert.Contains("Handshake succeeded", log);
-        StringAssert.Contains("Trying to establish secondary connections - 
awaiting 2 tasks", log);
-        StringAssert.Contains("2 secondary connections established, 0 failed", 
log);
-        StringAssert.Contains("Sending request [op=TablesGet", log);
-        StringAssert.Contains("Sending request [op=SqlExec", log);
-        StringAssert.Contains("Connection closed", log);
+        StringAssert.Contains("[Debug] Connection established", log);
+        StringAssert.Contains("[Debug] Handshake succeeded [remoteAddress=[", 
log);
+        StringAssert.Contains("ClientFailoverSocket [Debug] Trying to 
establish secondary connections - awaiting 2 tasks", log);
+        StringAssert.Contains("ClientFailoverSocket [Debug] 2 secondary 
connections established, 0 failed", log);
+        StringAssert.Contains("[Trace] Sending request [requestId=1, 
op=TablesGet, remoteAddress=", log);
+        StringAssert.Contains("[Trace] Received response [requestId=1, 
remoteAddress=", log);
+        StringAssert.Contains("op=SqlExec", log);
+        StringAssert.Contains("[Debug] Connection closed gracefully", log);
+    }
+
+    [Test]
+    public async Task TestMicrosoftConsoleLogger()
+    {
+        var oldWriter = Console.Out;
+        var writer = new StringWriter();
+        Console.SetOut(writer);
+
+        try
+        {
+            var cfg = new IgniteClientConfiguration
+            {
+                LoggerFactory = LoggerFactory.Create(builder =>
+                    builder.AddSimpleConsole(opt => opt.ColorBehavior = 
LoggerColorBehavior.Disabled)
+                        .SetMinimumLevel(LogLevel.Trace))
+            };
+
+            using var server = new FakeServer();
+            using var client = await server.ConnectClientAsync(cfg);
+            await client.Tables.GetTablesAsync();
+
+            var log = writer.ToString();
+            StringAssert.Contains("dbug: Apache.Ignite.Internal.ClientSocket", 
log);
+            StringAssert.Contains("Connection established", log);
+            StringAssert.Contains("Handshake succeeded [remoteAddress=[", log);
+        }
+        finally
+        {
+            Console.SetOut(oldWriter);
+        }
     }
 }
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/MultiClusterTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/MultiClusterTest.cs
index 9478150dba..cec14fdbc1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/MultiClusterTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/MultiClusterTest.cs
@@ -21,7 +21,6 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
-using Log;
 using NUnit.Framework;
 
 /// <summary>
@@ -35,10 +34,10 @@ public class MultiClusterTest
         using var server1 = new FakeServer(nodeName: "s1") { ClusterId = new 
Guid(1, 0, 0, new byte[8]) };
         using var server2 = new FakeServer(nodeName: "s2") { ClusterId = new 
Guid(2, 0, 0, new byte[8]) };
 
-        var log = new ListLogger(new ConsoleLogger());
+        var log = new ListLoggerFactory();
         var cfg = new IgniteClientConfiguration(server1.Endpoint, 
server2.Endpoint)
         {
-            Logger = log
+            LoggerFactory = log
         };
 
         using var client = await IgniteClient.StartAsync(cfg);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs
index 60767f09fd..1c04272072 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs
@@ -21,7 +21,7 @@ using System;
 using System.Diagnostics.CodeAnalysis;
 using System.Threading.Tasks;
 using Internal;
-using Log;
+using Microsoft.Extensions.Logging;
 using NUnit.Framework;
 
 /// <summary>
@@ -72,7 +72,7 @@ public class ReconnectTests
     {
         var cfg = new IgniteClientConfiguration
         {
-            Logger = new ConsoleLogger { MinLevel = LogLevel.Debug }
+            LoggerFactory = TestUtils.GetConsoleLoggerFactory(LogLevel.Debug)
         };
 
         using var server = new FakeServer();
@@ -92,7 +92,7 @@ public class ReconnectTests
         {
             HeartbeatInterval = TimeSpan.FromMilliseconds(100),
             ReconnectInterval = TimeSpan.FromMilliseconds(300),
-            Logger = new ConsoleLogger { MinLevel = LogLevel.Trace }
+            LoggerFactory = TestUtils.GetConsoleLoggerFactory(LogLevel.Trace)
         };
 
         using var servers = FakeServerGroup.Create(10);
@@ -134,15 +134,17 @@ public class ReconnectTests
     }
 
     [Test]
+    [SuppressMessage("Performance", "CA1848:Use the LoggerMessage delegates", 
Justification = "Test")]
     public async Task TestReconnectAfterFullClusterRestart()
     {
-        var logger = new ConsoleLogger { MinLevel = LogLevel.Trace };
+        var loggerFactory = TestUtils.GetConsoleLoggerFactory(LogLevel.Trace);
+        var logger = loggerFactory.CreateLogger("test");
 
         var cfg = new IgniteClientConfiguration
         {
             ReconnectInterval = TimeSpan.FromMilliseconds(100),
             SocketTimeout = TimeSpan.FromSeconds(2),
-            Logger = logger
+            LoggerFactory = loggerFactory
         };
 
         using var servers = FakeServerGroup.Create(10);
@@ -151,24 +153,24 @@ public class ReconnectTests
         Assert.DoesNotThrowAsync(async () => await 
client.Tables.GetTablesAsync());
 
         // Drop all connections and block new connections.
-        logger.Debug("Dropping all connections and blocking new 
connections...");
+        logger.LogDebug("Dropping all connections and blocking new 
connections...");
         servers.DropNewConnections = true;
         servers.DropExistingConnections();
-        logger.Debug("Dropped all connections and blocked new connections.");
+        logger.LogDebug("Dropped all connections and blocked new 
connections.");
 
         // Client fails to perform operations.
         Assert.ThrowsAsync<IgniteClientConnectionException>(async () => await 
client.Tables.GetTablesAsync());
 
         // Allow new connections.
-        logger.Debug("Allowing new connections...");
+        logger.LogDebug("Allowing new connections...");
         servers.DropNewConnections = false;
-        logger.Debug("Allowed new connections.");
+        logger.LogDebug("Allowed new connections.");
 
         // Client works again.
         Assert.DoesNotThrowAsync(async () => await 
client.Tables.GetTablesAsync());
 
         // All connections are restored.
-        logger.Debug("Waiting for all connections to be restored...");
+        logger.LogDebug("Waiting for all connections to be restored...");
         client.WaitForConnections(10);
     }
 }
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/SocketTimeoutTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/SocketTimeoutTest.cs
index 6e852abade..3806d6eefe 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/SocketTimeoutTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/SocketTimeoutTest.cs
@@ -20,7 +20,6 @@ namespace Apache.Ignite.Tests;
 using System;
 using System.Linq;
 using System.Threading.Tasks;
-using Log;
 using NUnit.Framework;
 
 /// <summary>
@@ -53,14 +52,14 @@ public class SocketTimeoutTest
             HeartbeatDelay = TimeSpan.FromMilliseconds(100)
         };
 
-        var log = new ListLogger(new ConsoleLogger { MinLevel = LogLevel.Trace 
});
+        var log = new ListLoggerFactory();
 
         var cfg = new IgniteClientConfiguration
         {
             SocketTimeout = TimeSpan.FromMilliseconds(50),
             HeartbeatInterval = TimeSpan.FromMilliseconds(100),
             RetryPolicy = new RetryNonePolicy(),
-            Logger = log
+            LoggerFactory = log
         };
 
         using var client = await server.ConnectClientAsync(cfg);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/SslTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/SslTests.cs
index 283f24cfd3..81aa7788c9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/SslTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/SslTests.cs
@@ -26,7 +26,7 @@ using System.Security.Authentication;
 using System.Security.Cryptography.X509Certificates;
 using System.Threading;
 using System.Threading.Tasks;
-using Log;
+using Microsoft.Extensions.Logging;
 using NUnit.Framework;
 
 /// <summary>
@@ -91,7 +91,7 @@ public class SslTests : IgniteTestsBase
                     ClientCertificates = new X509Certificate2Collection(new 
X509Certificate2(CertificatePath, CertificatePassword))
                 }
             },
-            Logger = new ConsoleLogger { MinLevel = LogLevel.Trace }
+            LoggerFactory = TestUtils.GetConsoleLoggerFactory(LogLevel.Trace)
         };
 
         using var client = await IgniteClient.StartAsync(cfg);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/TestUtils.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/TestUtils.cs
index 1927c122b9..8707cd5452 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/TestUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/TestUtils.cs
@@ -23,6 +23,7 @@ namespace Apache.Ignite.Tests
     using System.Reflection;
     using System.Runtime.InteropServices;
     using System.Threading.Tasks;
+    using Microsoft.Extensions.Logging;
     using NUnit.Framework;
 
     public static class TestUtils
@@ -76,6 +77,8 @@ namespace Apache.Ignite.Tests
             return (T) field!.GetValue(obj)!;
         }
 
+        public static ILoggerFactory GetConsoleLoggerFactory(LogLevel 
minLevel) => new ConsoleLogger(minLevel);
+
         private static string GetSolutionDir()
         {
             var dir = 
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/VersionTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/VersionTests.cs
index f551488825..36618ac337 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/VersionTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/VersionTests.cs
@@ -27,7 +27,7 @@ public class VersionTests
     [Test]
     public void TestAssemblyInformationalVersionHasGitCommitHash()
     {
-        var informationalVersion = VersionUtils.GetInformationalVersion();
+        var informationalVersion = VersionUtils.InformationalVersion;
         StringAssert.StartsWith(GetAssemblyVersion(), informationalVersion);
 
         var parts = informationalVersion.Split('+');
diff --git a/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj 
b/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj
index 02c6efcd15..614ad9274d 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite/Apache.Ignite.csproj
@@ -37,6 +37,7 @@
     <PackageReference Include="JetBrains.Annotations" Version="2022.3.1" 
PrivateAssets="all" />
     <PackageReference Include="NodaTime" Version="[3.*,)" />
     <PackageReference Include="Remotion.Linq" Version="2.2.0" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" 
Version="[6.*,)" />
   </ItemGroup>
 
   <ItemGroup>
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/IgniteClientConfiguration.cs 
b/modules/platforms/dotnet/Apache.Ignite/IgniteClientConfiguration.cs
index 93f9c0853a..bb48973557 100644
--- a/modules/platforms/dotnet/Apache.Ignite/IgniteClientConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/IgniteClientConfiguration.cs
@@ -22,7 +22,8 @@ namespace Apache.Ignite
     using System.ComponentModel;
     using System.Linq;
     using Internal.Common;
-    using Log;
+    using Microsoft.Extensions.Logging;
+    using Microsoft.Extensions.Logging.Abstractions;
 
     /// <summary>
     /// Ignite client driver configuration.
@@ -80,7 +81,7 @@ namespace Apache.Ignite
         {
             IgniteArgumentCheck.NotNull(other);
 
-            Logger = other.Logger;
+            LoggerFactory = other.LoggerFactory;
             SocketTimeout = other.SocketTimeout;
             Endpoints = other.Endpoints.ToList();
             RetryPolicy = other.RetryPolicy;
@@ -91,9 +92,9 @@ namespace Apache.Ignite
         }
 
         /// <summary>
-        /// Gets or sets the logger.
+        /// Gets or sets the logger factory. Default is <see 
cref="NullLoggerFactory.Instance"/>.
         /// </summary>
-        public IIgniteLogger? Logger { get; set; }
+        public ILoggerFactory LoggerFactory { get; set; } = 
NullLoggerFactory.Instance;
 
         /// <summary>
         /// Gets or sets the socket timeout.
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs
index 6e6e79a9f5..4650b2d150 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs
@@ -30,7 +30,7 @@ namespace Apache.Ignite.Internal
     using System.Threading.Tasks;
     using Buffers;
     using Ignite.Network;
-    using Log;
+    using Microsoft.Extensions.Logging;
     using Network;
     using Proto;
     using Transactions;
@@ -44,7 +44,7 @@ namespace Apache.Ignite.Internal
         private static long _globalEndPointIndex;
 
         /** Logger. */
-        private readonly IIgniteLogger? _logger;
+        private readonly ILogger _logger;
 
         /** Endpoints with corresponding hosts - from configuration. */
         private readonly IReadOnlyList<SocketEndpoint> _endpoints;
@@ -82,7 +82,8 @@ namespace Apache.Ignite.Internal
         /// Initializes a new instance of the <see 
cref="ClientFailoverSocket"/> class.
         /// </summary>
         /// <param name="configuration">Client configuration.</param>
-        private ClientFailoverSocket(IgniteClientConfiguration configuration)
+        /// <param name="logger">Logger.</param>
+        private ClientFailoverSocket(IgniteClientConfiguration configuration, 
ILogger logger)
         {
             if (configuration.Endpoints.Count == 0)
             {
@@ -91,7 +92,7 @@ namespace Apache.Ignite.Internal
                     $"Invalid {nameof(IgniteClientConfiguration)}: 
{nameof(IgniteClientConfiguration.Endpoints)} is empty. Nowhere to connect.");
             }
 
-            _logger = configuration.Logger.GetLogger(GetType());
+            _logger = logger;
             _endpoints = GetIpEndPoints(configuration).ToList();
 
             Configuration = new(configuration); // Defensive copy.
@@ -119,10 +120,10 @@ namespace Apache.Ignite.Internal
         /// <returns>A <see cref="Task"/> representing the asynchronous 
operation.</returns>
         public static async Task<ClientFailoverSocket> 
ConnectAsync(IgniteClientConfiguration configuration)
         {
-            var socket = new ClientFailoverSocket(configuration);
+            var logger = 
configuration.LoggerFactory.CreateLogger<ClientFailoverSocket>();
+            logger.LogClientStartInfo(VersionUtils.InformationalVersion);
 
-            var logger = 
configuration.Logger.GetLogger(typeof(ClientFailoverSocket));
-            logger?.Info("Ignite.NET client version " + 
VersionUtils.GetInformationalVersion() + " is starting");
+            var socket = new ClientFailoverSocket(configuration, logger);
 
             await socket.GetNextSocketAsync().ConfigureAwait(false);
 
@@ -307,7 +308,7 @@ namespace Apache.Ignite.Internal
                 }
                 catch (Exception e)
                 {
-                    _logger?.Warn(e, $"Failed to connect to preferred node 
[{preferredNode}]: {e.Message}");
+                    
_logger.LogFailedToConnectPreferredNodeDebug(preferredNode.Name, e.Message);
                 }
             }
 
@@ -347,13 +348,13 @@ namespace Apache.Ignite.Internal
                     }
                     catch (Exception e)
                     {
-                        _logger?.Warn(e, "Error while trying to establish 
secondary connections: " + e.Message);
+                        
_logger.LogErrorWhileEstablishingSecondaryConnectionsWarn(e, e.Message);
                     }
                 }
 
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
+                if (_logger.IsEnabled(LogLevel.Debug))
                 {
-                    _logger.Debug("Trying to establish secondary connections - 
awaiting {0} tasks...", tasks.Count);
+                    
_logger.LogTryingToEstablishSecondaryConnectionsDebug(tasks.Count);
                 }
 
                 // Await every task separately instead of using WhenAll to 
capture exceptions and avoid extra allocations.
@@ -366,14 +367,14 @@ namespace Apache.Ignite.Internal
                     }
                     catch (Exception e)
                     {
-                        _logger?.Warn(e, "Error while trying to establish 
secondary connections: " + e.Message);
+                        
_logger.LogErrorWhileEstablishingSecondaryConnectionsWarn(e, e.Message);
                         failed++;
                     }
                 }
 
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
+                if (_logger.IsEnabled(LogLevel.Debug))
                 {
-                    _logger.Debug($"{tasks.Count - failed} secondary 
connections established, {failed} failed.");
+                    
_logger.LogSecondaryConnectionsEstablishedDebug(tasks.Count - failed, failed);
                 }
 
                 if (Configuration.ReconnectInterval <= TimeSpan.Zero)
@@ -530,7 +531,7 @@ namespace Apache.Ignite.Internal
             }
             catch (SocketException e)
             {
-                _logger?.Debug(e, "Failed to parse host: " + host);
+                _logger.LogFailedToParseHostDebug(e, host, e.Message);
 
                 if (suppressExceptions)
                 {
@@ -608,9 +609,9 @@ namespace Apache.Ignite.Internal
         {
             if (!ShouldRetry(exception, op, attempt, retryPolicy))
             {
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
+                if (_logger.IsEnabled(LogLevel.Debug))
                 {
-                    _logger.Debug($"Not retrying operation [opCode={(int)op}, 
opType={op}, attempt={attempt}, lastError={exception}]");
+                    _logger.LogRetryingOperationDebug("Not retrying", (int)op, 
op, attempt, exception.Message);
                 }
 
                 if (errors == null)
@@ -627,9 +628,9 @@ namespace Apache.Ignite.Internal
                     inner);
             }
 
-            if (_logger?.IsEnabled(LogLevel.Debug) == true)
+            if (_logger.IsEnabled(LogLevel.Debug))
             {
-                _logger.Debug($"Retrying operation [opCode={(int)op}, 
opType={op}, attempt={attempt}, lastError={exception}]");
+                _logger.LogRetryingOperationDebug("Retrying", (int)op, op, 
attempt, exception.Message);
             }
 
             Metrics.RequestsRetried.Add(1);
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs
index 591c6a78e8..9a119c7aa5 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs
@@ -31,7 +31,7 @@ namespace Apache.Ignite.Internal
     using System.Threading.Tasks;
     using Buffers;
     using Ignite.Network;
-    using Log;
+    using Microsoft.Extensions.Logging;
     using Network;
     using Proto;
     using Proto.MsgPack;
@@ -90,7 +90,7 @@ namespace Apache.Ignite.Internal
         private readonly TimeSpan _socketTimeout;
 
         /** Logger. */
-        private readonly IIgniteLogger? _logger;
+        private readonly ILogger _logger;
 
         /** Event listener. */
         private readonly IClientSocketEventListener _listener;
@@ -117,7 +117,7 @@ namespace Apache.Ignite.Internal
             IgniteClientConfiguration configuration,
             ConnectionContext connectionContext,
             IClientSocketEventListener listener,
-            IIgniteLogger? logger)
+            ILogger logger)
         {
             _stream = stream;
             ConnectionContext = connectionContext;
@@ -168,7 +168,8 @@ namespace Apache.Ignite.Internal
             IClientSocketEventListener listener)
         {
             using var cts = new CancellationTokenSource();
-            var logger = configuration.Logger.GetLogger(nameof(ClientSocket) + 
"-" + Interlocked.Increment(ref _socketId));
+            var logger = 
configuration.LoggerFactory.CreateLogger(typeof(ClientSocket).FullName! + "-" +
+                                                                  
Interlocked.Increment(ref _socketId));
 
             bool connected = false;
             Socket? socket = null;
@@ -187,11 +188,7 @@ namespace Apache.Ignite.Internal
                     .ConfigureAwait(false);
 
                 connected = true;
-
-                if (logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    logger.Debug($"Connection established 
[remoteAddress={socket.RemoteEndPoint}]");
-                }
+                logger.LogConnectionEstablishedDebug(socket.RemoteEndPoint);
 
                 Metrics.ConnectionsEstablished.Add(1);
                 Metrics.ConnectionsActiveIncrement();
@@ -204,22 +201,14 @@ namespace Apache.Ignite.Internal
                         .ConfigureAwait(false) is { } sslStream)
                 {
                     stream = sslStream;
-
-                    if (logger?.IsEnabled(LogLevel.Debug) == true)
-                    {
-                        logger.Debug(
-                            $"SSL connection established 
[remoteAddress={socket.RemoteEndPoint}]: {sslStream.NegotiatedCipherSuite}");
-                    }
+                    
logger.LogSslConnectionEstablishedDebug(socket.RemoteEndPoint, 
sslStream.NegotiatedCipherSuite);
                 }
 
                 var context = await HandshakeAsync(stream, endPoint.EndPoint, 
configuration, cts.Token)
                     .WaitAsync(configuration.SocketTimeout, cts.Token)
                     .ConfigureAwait(false);
 
-                if (logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    logger.Debug($"Handshake succeeded 
[remoteAddress={socket.RemoteEndPoint}]: {context}.");
-                }
+                logger.LogHandshakeSucceededDebug(socket.RemoteEndPoint, 
context);
 
                 return new ClientSocket(stream, configuration, context, 
listener, logger);
             }
@@ -237,10 +226,10 @@ namespace Apache.Ignite.Internal
                 }
                 catch (Exception disposeEx)
                 {
-                    logger?.Warn(disposeEx, "Failed to dispose socket after 
failed connection attempt: " + disposeEx.Message);
+                    
logger.LogFailedToDisposeSocketAfterFailedConnectionAttemptWarn(disposeEx, 
disposeEx.Message);
                 }
 
-                logger?.Warn(ex, $"Connection failed before or during 
handshake [remoteAddress={endPoint.EndPoint}]: {ex.Message}.");
+                logger.LogConnectionFailedBeforeOrDuringHandshakeWarn(ex, 
endPoint.EndPoint, ex.Message);
 
                 if (ex.GetBaseException() is TimeoutException)
                 {
@@ -561,7 +550,7 @@ namespace Apache.Ignite.Internal
 
         private static int ReadMessageSize(Span<byte> responseLenBytes) => 
BinaryPrimitives.ReadInt32BigEndian(responseLenBytes);
 
-        private static TimeSpan GetHeartbeatInterval(TimeSpan 
configuredInterval, TimeSpan serverIdleTimeout, IIgniteLogger? logger)
+        private static TimeSpan GetHeartbeatInterval(TimeSpan 
configuredInterval, TimeSpan serverIdleTimeout, ILogger logger)
         {
             if (configuredInterval <= TimeSpan.Zero)
             {
@@ -572,9 +561,7 @@ namespace Apache.Ignite.Internal
 
             if (serverIdleTimeout <= TimeSpan.Zero)
             {
-                logger?.Info(
-                    $"Server-side IdleTimeout is not set, using configured 
{nameof(IgniteClientConfiguration)}." +
-                    $"{nameof(IgniteClientConfiguration.HeartbeatInterval)}: 
{configuredInterval}");
+                logger.LogServerSizeIdleTimeoutNotSetInfo(configuredInterval);
 
                 return configuredInterval;
             }
@@ -588,20 +575,13 @@ namespace Apache.Ignite.Internal
 
             if (configuredInterval < recommendedHeartbeatInterval)
             {
-                logger?.Info(
-                    $"Server-side IdleTimeout is {serverIdleTimeout}, " +
-                    $"using configured {nameof(IgniteClientConfiguration)}." +
-                    $"{nameof(IgniteClientConfiguration.HeartbeatInterval)}: " 
+
-                    configuredInterval);
+                logger.LogServerSideIdleTimeoutIgnoredInfo(serverIdleTimeout, 
configuredInterval);
 
                 return configuredInterval;
             }
 
-            logger?.Warn(
-                $"Server-side IdleTimeout is {serverIdleTimeout}, configured " 
+
-                
$"{nameof(IgniteClientConfiguration)}.{nameof(IgniteClientConfiguration.HeartbeatInterval)}
 " +
-                $"is {configuredInterval}, which is longer than recommended 
IdleTimeout / 3. " +
-                $"Overriding heartbeat interval with max(IdleTimeout / 3, 
500ms): {recommendedHeartbeatInterval}");
+            
logger.LogServerSideIdleTimeoutOverridesConfiguredHeartbeatIntervalWarn(
+                serverIdleTimeout, configuredInterval, 
recommendedHeartbeatInterval);
 
             return recommendedHeartbeatInterval;
         }
@@ -626,10 +606,7 @@ namespace Apache.Ignite.Internal
             // Reset heartbeat timer - don't sent heartbeats when connection 
is active anyway.
             _heartbeatTimer.Change(dueTime: _heartbeatInterval, period: 
TimeSpan.FromMilliseconds(-1));
 
-            if (_logger?.IsEnabled(LogLevel.Trace) == true)
-            {
-                _logger.Trace($"Sending request [op={op}, 
remoteAddress={ConnectionContext.ClusterNode.Address}, requestId={requestId}]");
-            }
+            _logger.LogSendingRequestTrace(requestId, op, 
ConnectionContext.ClusterNode.Address);
 
             await 
_sendLock.WaitAsync(_disposeTokenSource.Token).ConfigureAwait(false);
 
@@ -672,7 +649,7 @@ namespace Apache.Ignite.Internal
             {
                 var message = "Exception while writing to socket, connection 
closed: " + e.Message;
 
-                _logger?.Error(e, message);
+                _logger.LogSocketIoError(e, message);
                 var connEx = new 
IgniteClientConnectionException(ErrorGroups.Client.Connection, message, new 
SocketException());
 
                 Dispose(connEx);
@@ -708,7 +685,7 @@ namespace Apache.Ignite.Internal
             {
                 var message = "Exception while reading from socket, connection 
closed: " + e.Message;
 
-                _logger?.Error(e, message);
+                _logger.LogSocketIoError(e, message);
                 Dispose(new 
IgniteClientConnectionException(ErrorGroups.Client.Connection, message, e));
             }
         }
@@ -732,26 +709,24 @@ namespace Apache.Ignite.Internal
                 var message = $"Unexpected response ID ({requestId}) received 
from the server " +
                               
$"[remoteAddress={ConnectionContext.ClusterNode.Address}], closing the socket.";
 
-                _logger?.Error(message);
+                _logger.LogUnexpectedResponseIdError(null, message);
                 Dispose(new 
IgniteClientConnectionException(ErrorGroups.Client.Protocol, message));
 
                 return;
             }
 
             Metrics.RequestsActiveDecrement();
+            _logger.LogReceivedResponseTrace(requestId, 
ConnectionContext.ClusterNode.Address);
 
             var flags = (ResponseFlags)reader.ReadInt32();
 
             if (flags.HasFlag(ResponseFlags.PartitionAssignmentChanged))
             {
-                if (_logger?.IsEnabled(LogLevel.Info) == true)
-                {
-                    _logger.Info(
-                        $"Partition assignment change notification received 
[remoteAddress={ConnectionContext.ClusterNode.Address}]");
-                }
+                long timestamp = reader.ReadInt64();
 
-                // TODO IGNITE-20900: Read and propagate assignment timestamp 
- separate ticket.
-                _ = reader.ReadInt64();
+                
_logger.LogPartitionAssignmentChangeNotificationInfo(ConnectionContext.ClusterNode.Address,
 timestamp);
+
+                // TODO IGNITE-20900: Propagate assignment timestamp.
                 _listener.OnAssignmentChanged(this);
             }
 
@@ -793,9 +768,10 @@ namespace Apache.Ignite.Internal
             }
             catch (Exception e)
             {
-                _logger?.Error(e, "Heartbeat failed: " + e.Message);
+                var message = "Heartbeat failed: " + e.Message;
+                _logger.LogHeartbeatError(e, message);
 
-                Dispose(e);
+                Dispose(new 
IgniteClientConnectionException(ErrorGroups.Client.Connection, message, e));
             }
         }
 
@@ -816,7 +792,7 @@ namespace Apache.Ignite.Internal
 
                 if (ex != null)
                 {
-                    _logger?.Warn(ex, $"Connection closed 
[remoteAddress={ConnectionContext.ClusterNode.Address}]: " + ex.Message);
+                    _logger.LogConnectionClosedWithErrorWarn(ex, 
ConnectionContext.ClusterNode.Address, ex.Message);
 
                     if (ex.GetBaseException() is TimeoutException)
                     {
@@ -827,9 +803,9 @@ namespace Apache.Ignite.Internal
                         Metrics.ConnectionsLost.Add(1);
                     }
                 }
-                else if (_logger?.IsEnabled(LogLevel.Debug) == true)
+                else
                 {
-                    _logger.Debug($"Connection closed 
[remoteAddress={ConnectionContext.ClusterNode.Address}]");
+                    
_logger.LogConnectionClosedGracefullyDebug(ConnectionContext.ClusterNode.Address);
                 }
 
                 _heartbeatTimer.Dispose();
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/IgniteQueryExecutor.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/IgniteQueryExecutor.cs
index f1eaaa61ea..28e5781cbf 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/IgniteQueryExecutor.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/IgniteQueryExecutor.cs
@@ -25,7 +25,7 @@ using System.Threading.Tasks;
 using Common;
 using Ignite.Sql;
 using Ignite.Transactions;
-using Log;
+using Microsoft.Extensions.Logging;
 using Remotion.Linq;
 using Remotion.Linq.Clauses.ResultOperators;
 using Sql;
@@ -38,7 +38,7 @@ internal sealed class IgniteQueryExecutor : IQueryExecutor
     private readonly Sql _sql;
     private readonly ITransaction? _transaction;
     private readonly QueryableOptions? _options;
-    private readonly IIgniteLogger? _logger;
+    private readonly ILogger _logger;
 
     /// <summary>
     /// Initializes a new instance of the <see cref="IgniteQueryExecutor" /> 
class.
@@ -52,7 +52,7 @@ internal sealed class IgniteQueryExecutor : IQueryExecutor
         _sql = sql;
         _transaction = transaction;
         _options = options;
-        _logger = configuration.Logger.GetLogger(GetType());
+        _logger = 
configuration.LoggerFactory.CreateLogger<IgniteQueryExecutor>();
     }
 
     /// <summary>
@@ -123,10 +123,10 @@ internal sealed class IgniteQueryExecutor : IQueryExecutor
 
         var selectorOptions = GetResultSelectorOptions(queryModel, 
queryData.HasOuterJoins);
 
-        if (_logger?.IsEnabled(LogLevel.Debug) == true)
+        // Explicit enabled check because of StringJoin.
+        if (_logger.IsEnabled(LogLevel.Debug))
         {
-            _logger.Debug($"Executing SQL statement generated by LINQ 
provider: {statement}, " +
-                          $"parameters: {queryData.Parameters.StringJoin()}");
+            _logger.LogExecutingSqlStatementDebug(statement, 
queryData.Parameters.StringJoin());
         }
 
         IResultSet<T> resultSet = await _sql.ExecuteAsyncInternal(
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/README.md 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/README.md
index 8b02e7ef8e..68f5dd3ec5 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/README.md
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Linq/README.md
@@ -93,7 +93,7 @@ string sql = query.ToQueryString();
 ```csharp
 var cfg = new IgniteClientConfiguration
 {
-    Logger = new ConsoleLogger { MinLevel = LogLevel.Debug },
+    Logger = LoggerFactory.Create(builder => 
builder.AddConsole().SetMinimumLevel(LogLevel.Debug)),
     ...
 };
 
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/LogMessages.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/LogMessages.cs
new file mode 100644
index 0000000000..8ccaed4ecc
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/LogMessages.cs
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Internal;
+
+using System;
+using System.Net;
+using System.Net.Security;
+using Ignite.Sql;
+using Microsoft.Extensions.Logging;
+using Proto;
+
+/// <summary>
+/// Source-generated logger delegates.
+/// </summary>
+internal static partial class LogMessages
+{
+    [LoggerMessage(
+        Message = "Schema loaded [tableId={TableId}, 
schemaVersion={SchemaVersion}]",
+        Level = LogLevel.Debug,
+        EventId = 1001)]
+    internal static partial void LogSchemaLoadedDebug(this ILogger logger, int 
tableId, int schemaVersion);
+
+    [LoggerMessage(
+        Message = "Retrying unmapped columns error [tableId={TableId}, 
schemaVersion={SchemaVersion}, message={Message}]",
+        Level = LogLevel.Debug,
+        EventId = 1002)]
+    internal static partial void LogRetryingUnmappedColumnsErrorDebug(this 
ILogger logger, int tableId, int? schemaVersion, string message);
+
+    [LoggerMessage(
+        Message = "Retrying SchemaVersionMismatch error [tableId={TableId}, " +
+                  "schemaVersion={SchemaVersion}, 
expectedSchemaVersion={ExpectedSchemaVersion}]",
+        Level = LogLevel.Debug,
+        EventId = 1003)]
+    internal static partial void LogRetryingSchemaVersionMismatchErrorDebug(
+        this ILogger logger, int tableId, int? schemaVersion, int? 
expectedSchemaVersion);
+
+    [LoggerMessage(
+        Message = "Executing SQL statement generated by LINQ provider 
[statement={Statement}, parameters={Parameters}]",
+        Level = LogLevel.Debug,
+        SkipEnabledCheck = true,
+        EventId = 1004)]
+    internal static partial void LogExecutingSqlStatementDebug(this ILogger 
logger, SqlStatement statement, string parameters);
+
+    [LoggerMessage(
+        Message = "Connection established [remoteAddress={Endpoint}]",
+        Level = LogLevel.Debug,
+        EventId = 1005)]
+    internal static partial void LogConnectionEstablishedDebug(this ILogger 
logger, EndPoint? endpoint);
+
+    [LoggerMessage(
+        Message = "SSL connection established [remoteAddress={Endpoint}, 
cipherSuite={CipherSuite}]",
+        Level = LogLevel.Debug,
+        EventId = 1006)]
+    internal static partial void LogSslConnectionEstablishedDebug(this ILogger 
logger, EndPoint? endpoint, TlsCipherSuite cipherSuite);
+
+    [LoggerMessage(
+        Message = "Handshake succeeded [remoteAddress={Endpoint}, 
context={Context}]",
+        Level = LogLevel.Debug,
+        EventId = 1007)]
+    internal static partial void LogHandshakeSucceededDebug(this ILogger 
logger, EndPoint? endpoint, ConnectionContext context);
+
+    [LoggerMessage(
+        Message = "Failed to dispose socket after failed connection attempt: 
{Message}",
+        Level = LogLevel.Warning,
+        EventId = 1008)]
+    internal static partial void 
LogFailedToDisposeSocketAfterFailedConnectionAttemptWarn(
+        this ILogger logger, Exception ex, string message);
+
+    [LoggerMessage(
+        Message = "Connection failed before or during handshake 
[remoteAddress={Endpoint}]: {Message}",
+        Level = LogLevel.Warning,
+        EventId = 1009)]
+    internal static partial void 
LogConnectionFailedBeforeOrDuringHandshakeWarn(
+        this ILogger logger, Exception ex, EndPoint? endpoint, string message);
+
+    [LoggerMessage(
+        Message = "Server-side IdleTimeout is not set, using configured 
IgniteClientConfiguration.HeartbeatInterval: {Interval}",
+        Level = LogLevel.Information,
+        EventId = 1010)]
+    internal static partial void LogServerSizeIdleTimeoutNotSetInfo(this 
ILogger logger, TimeSpan interval);
+
+    [LoggerMessage(
+        Message = "Server-side IdleTimeout is {ServerIdleTimeout}, " +
+                  "using configured 
IgniteClientConfiguration.HeartbeatInterval: {ConfiguredInterval}",
+        Level = LogLevel.Information,
+        EventId = 1011)]
+    internal static partial void LogServerSideIdleTimeoutIgnoredInfo(
+        this ILogger logger, TimeSpan serverIdleTimeout, TimeSpan 
configuredInterval);
+
+    [LoggerMessage(
+        Message = "Server-side IdleTimeout is {ServerIdleTimeout}, " +
+                  "configured IgniteClientConfiguration.HeartbeatInterval is 
{ConfiguredInterval}, " +
+                  "which is longer than recommended IdleTimeout / 3. " +
+                  "Overriding heartbeat interval with max(IdleTimeout / 3, 
500ms): {RecommendedHeartbeatInterval}",
+        Level = LogLevel.Warning,
+        EventId = 1012)]
+    internal static partial void 
LogServerSideIdleTimeoutOverridesConfiguredHeartbeatIntervalWarn(
+        this ILogger logger, TimeSpan serverIdleTimeout, TimeSpan 
configuredInterval, TimeSpan recommendedHeartbeatInterval);
+
+    [LoggerMessage(
+        Message = "Sending request [requestId={RequestId}, op={Op}, 
remoteAddress={RemoteAddress}]",
+        Level = LogLevel.Trace,
+        EventId = 1013)]
+    internal static partial void LogSendingRequestTrace(this ILogger logger, 
long requestId, ClientOp op, IPEndPoint remoteAddress);
+
+    [LoggerMessage(
+        Message = "{Message}",
+        Level = LogLevel.Error,
+        EventId = 1014)]
+    internal static partial void LogSocketIoError(this ILogger logger, 
Exception? ex, string message);
+
+    [LoggerMessage(
+        Message = "{Message}",
+        Level = LogLevel.Error,
+        EventId = 1015)]
+    internal static partial void LogHeartbeatError(this ILogger logger, 
Exception? ex, string message);
+
+    [LoggerMessage(
+        Message = "{Message}",
+        Level = LogLevel.Error,
+        EventId = 1016)]
+    internal static partial void LogUnexpectedResponseIdError(this ILogger 
logger, Exception? ex, string message);
+
+    [LoggerMessage(
+        Message = "Partition assignment change notification received 
[remoteAddress={RemoteAddress}, timestamp={Timestamp}",
+        Level = LogLevel.Information,
+        EventId = 1017)]
+    internal static partial void LogPartitionAssignmentChangeNotificationInfo(
+        this ILogger logger, IPEndPoint remoteAddress, long timestamp);
+
+    [LoggerMessage(
+        Message = "Connection closed with error 
[remoteAddress={RemoteAddress}]: {Message}",
+        Level = LogLevel.Warning,
+        EventId = 1018)]
+    internal static partial void LogConnectionClosedWithErrorWarn(
+        this ILogger logger, Exception ex, IPEndPoint remoteAddress, string 
message);
+
+    [LoggerMessage(
+        Message = "Connection closed gracefully 
[remoteAddress={RemoteAddress}]",
+        Level = LogLevel.Debug,
+        EventId = 1019)]
+    internal static partial void LogConnectionClosedGracefullyDebug(this 
ILogger logger, IPEndPoint remoteAddress);
+
+    [LoggerMessage(
+        Message = "Ignite.NET client version {Version} is starting",
+        Level = LogLevel.Information,
+        EventId = 1020)]
+    internal static partial void LogClientStartInfo(this ILogger logger, 
string version);
+
+    [LoggerMessage(
+        Message = "Failed to connect to preferred node [name={NodeName}]: 
{Message}",
+        Level = LogLevel.Debug,
+        EventId = 1021)]
+    internal static partial void LogFailedToConnectPreferredNodeDebug(this 
ILogger logger, string nodeName, string message);
+
+    [LoggerMessage(
+        Message = "Error while trying to establish secondary connections: 
{Message}",
+        Level = LogLevel.Warning,
+        EventId = 1022)]
+    internal static partial void 
LogErrorWhileEstablishingSecondaryConnectionsWarn(this ILogger logger, 
Exception e, string message);
+
+    [LoggerMessage(
+        Message = "Trying to establish secondary connections - awaiting 
{Tasks} tasks...",
+        Level = LogLevel.Debug,
+        EventId = 1023)]
+    internal static partial void 
LogTryingToEstablishSecondaryConnectionsDebug(this ILogger logger, int tasks);
+
+    [LoggerMessage(
+        Message = "{Established} secondary connections established, {Failed} 
failed.",
+        Level = LogLevel.Debug,
+        EventId = 1024)]
+    internal static partial void LogSecondaryConnectionsEstablishedDebug(this 
ILogger logger, int established, int failed);
+
+    [LoggerMessage(
+        Message = "Failed to parse host '{Host}': {Message}",
+        Level = LogLevel.Debug,
+        EventId = 1025)]
+    internal static partial void LogFailedToParseHostDebug(this ILogger 
logger, Exception e, string host, string message);
+
+    [LoggerMessage(
+        Message = "{Retrying} operation [opCode={Op}, opType={OpType}, 
attempt={Attempt}, lastError={LastErrorMessage}]",
+        Level = LogLevel.Debug,
+        EventId = 1026)]
+    internal static partial void LogRetryingOperationDebug(
+        this ILogger logger, string retrying, int op, ClientOp opType, int 
attempt, string lastErrorMessage);
+
+    [LoggerMessage(
+        Message = "Received response [requestId={RequestId}, 
remoteAddress={RemoteAddress}]",
+        Level = LogLevel.Trace,
+        EventId = 1027)]
+    internal static partial void LogReceivedResponseTrace(this ILogger logger, 
long requestId, IPEndPoint remoteAddress);
+}
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs
index f8222b7cd7..277d48fe74 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs
@@ -29,7 +29,7 @@ namespace Apache.Ignite.Internal.Table
     using Ignite.Table;
     using Ignite.Transactions;
     using Linq;
-    using Log;
+    using Microsoft.Extensions.Logging;
     using Proto;
     using Serialization;
     using Sql;
@@ -51,7 +51,7 @@ namespace Apache.Ignite.Internal.Table
         /** SQL. */
         private readonly Sql _sql;
 
-        private readonly IIgniteLogger? _logger;
+        private readonly ILogger _logger;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="RecordView{T}"/> 
class.
@@ -64,7 +64,7 @@ namespace Apache.Ignite.Internal.Table
             _table = table;
             _ser = ser;
             _sql = sql;
-            _logger = table.Socket.Configuration.Logger.GetLogger(GetType());
+            _logger = 
table.Socket.Configuration.LoggerFactory.CreateLogger<RecordView<T>>();
         }
 
         /// <summary>
@@ -427,22 +427,16 @@ namespace Apache.Ignite.Internal.Table
             catch (IgniteException e) when (e.Code == 
ErrorGroups.Table.SchemaVersionMismatch &&
                                             schemaVersionOverride != 
e.GetExpectedSchemaVersion())
             {
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    _logger.Debug($"Retrying SchemaVersionMismatch error 
[tableId={_table.Id}, schemaVersion={schema?.Version}, " +
-                                  
$"expectedSchemaVersion={e.GetExpectedSchemaVersion()}]");
-                }
-
                 schemaVersionOverride = e.GetExpectedSchemaVersion();
+
+                _logger.LogRetryingSchemaVersionMismatchErrorDebug(_table.Id, 
schema?.Version, schemaVersionOverride);
+
                 return await DoRecordOutOpAsync(op, transaction, record, 
keyOnly, schemaVersionOverride).ConfigureAwait(false);
             }
             catch (Exception e) when (e.CausedByUnmappedColumns() &&
                                       schemaVersionOverride == null)
             {
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    _logger.Debug($"Retrying unmapped columns error 
[tableId={_table.Id}, schemaVersion={schema?.Version}]");
-                }
+                _logger.LogRetryingUnmappedColumnsErrorDebug(_table.Id, 
schema?.Version, e.Message);
 
                 schemaVersionOverride = Table.SchemaVersionForceLatest;
                 return await DoRecordOutOpAsync(op, transaction, record, 
keyOnly, schemaVersionOverride).ConfigureAwait(false);
@@ -474,22 +468,16 @@ namespace Apache.Ignite.Internal.Table
             catch (IgniteException e) when (e.Code == 
ErrorGroups.Table.SchemaVersionMismatch &&
                                             schemaVersionOverride != 
e.GetExpectedSchemaVersion())
             {
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    _logger.Debug($"Retrying SchemaVersionMismatch error 
[tableId={_table.Id}, schemaVersion={schema?.Version}, " +
-                                  
$"expectedSchemaVersion={e.GetExpectedSchemaVersion()}]");
-                }
-
                 schemaVersionOverride = e.GetExpectedSchemaVersion();
+
+                _logger.LogRetryingSchemaVersionMismatchErrorDebug(_table.Id, 
schema?.Version, schemaVersionOverride);
+
                 return await DoTwoRecordOutOpAsync(op, transaction, record, 
record2, keyOnly, schemaVersionOverride).ConfigureAwait(false);
             }
             catch (Exception e) when (e.CausedByUnmappedColumns() &&
                                       schemaVersionOverride == null)
             {
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    _logger.Debug($"Retrying unmapped columns error 
[tableId={_table.Id}, schemaVersion={schema?.Version}]");
-                }
+                _logger.LogRetryingUnmappedColumnsErrorDebug(_table.Id, 
schema?.Version, e.Message);
 
                 schemaVersionOverride = Table.SchemaVersionForceLatest;
                 return await DoTwoRecordOutOpAsync(op, transaction, record, 
record2, keyOnly, schemaVersionOverride).ConfigureAwait(false);
@@ -527,24 +515,17 @@ namespace Apache.Ignite.Internal.Table
             catch (IgniteException e) when (e.Code == 
ErrorGroups.Table.SchemaVersionMismatch &&
                                             schemaVersionOverride != 
e.GetExpectedSchemaVersion())
             {
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    _logger.Debug($"Retrying SchemaVersionMismatch error 
[tableId={_table.Id}, schemaVersion={schema?.Version}, " +
-                                  
$"expectedSchemaVersion={e.GetExpectedSchemaVersion()}]");
-                }
-
                 schemaVersionOverride = e.GetExpectedSchemaVersion();
 
+                _logger.LogRetryingSchemaVersionMismatchErrorDebug(_table.Id, 
schema?.Version, schemaVersionOverride);
+
                 // ReSharper disable once PossibleMultipleEnumeration (we have 
to retry, but this is very rare)
                 return await DoMultiRecordOutOpAsync(op, transaction, recs, 
keyOnly, schemaVersionOverride).ConfigureAwait(false);
             }
             catch (Exception e) when (e.CausedByUnmappedColumns() &&
                                       schemaVersionOverride == null)
             {
-                if (_logger?.IsEnabled(LogLevel.Debug) == true)
-                {
-                    _logger.Debug($"Retrying unmapped columns error 
[tableId={_table.Id}, schemaVersion={schema?.Version}]");
-                }
+                _logger.LogRetryingUnmappedColumnsErrorDebug(_table.Id, 
schema?.Version, e.Message);
 
                 schemaVersionOverride = Table.SchemaVersionForceLatest;
 
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs
index 5582b13f19..80e5e97502 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/Table.cs
@@ -28,7 +28,7 @@ namespace Apache.Ignite.Internal.Table
     using Ignite.Sql;
     using Ignite.Table;
     using Ignite.Transactions;
-    using Log;
+    using Microsoft.Extensions.Logging;
     using Proto;
     using Proto.MsgPack;
     using Serialization;
@@ -65,7 +65,7 @@ namespace Apache.Ignite.Internal.Table
         private readonly object _latestSchemaLock = new();
 
         /** */
-        private readonly IIgniteLogger? _logger;
+        private readonly ILogger _logger;
 
         /** */
         private readonly SemaphoreSlim _partitionAssignmentSemaphore = new(1);
@@ -94,7 +94,7 @@ namespace Apache.Ignite.Internal.Table
             Name = name;
             Id = id;
 
-            _logger = socket.Configuration.Logger.GetLogger(GetType());
+            _logger = socket.Configuration.LoggerFactory.CreateLogger<Table>();
 
             RecordBinaryView = new RecordView<IIgniteTuple>(
                 this,
@@ -372,10 +372,7 @@ namespace Apache.Ignite.Internal.Table
 
             _schemas[schemaVersion] = Task.FromResult(schema);
 
-            if (_logger?.IsEnabled(LogLevel.Debug) == true)
-            {
-                _logger.Debug($"Schema loaded [tableId={Id}, 
schemaVersion={schema.Version}]");
-            }
+            _logger.LogSchemaLoadedDebug(Id, schema.Version);
 
             lock (_latestSchemaLock)
             {
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/VersionUtils.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/VersionUtils.cs
index 1a020aa7fe..a62c5187c6 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/VersionUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/VersionUtils.cs
@@ -28,7 +28,7 @@ internal static class VersionUtils
     /// Gets the informational version.
     /// </summary>
     /// <returns>Version string.</returns>
-    public static string GetInformationalVersion() =>
+    public static readonly string InformationalVersion =
         typeof(VersionUtils).Assembly
             .GetCustomAttribute<AssemblyInformationalVersionAttribute>()
             ?.InformationalVersion!;
diff --git a/modules/platforms/dotnet/Apache.Ignite/Log/CategoryLogger.cs 
b/modules/platforms/dotnet/Apache.Ignite/Log/CategoryLogger.cs
deleted file mode 100644
index 67acfbc606..0000000000
--- a/modules/platforms/dotnet/Apache.Ignite/Log/CategoryLogger.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Log
-{
-    using System;
-    using Internal.Common;
-
-    /// <summary>
-    /// Wrapping logger with a predefined category.
-    /// <para />
-    /// When <see cref="Log"/> method is called, and <c>category</c> parameter 
is null, predefined category
-    /// will be used.
-    /// </summary>
-    public sealed class CategoryLogger : IIgniteLogger
-    {
-        /** Wrapped logger. */
-        private readonly IIgniteLogger _logger;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CategoryLogger"/> 
class.
-        /// </summary>
-        /// <param name="logger">The logger to wrap.</param>
-        /// <param name="category">The category.</param>
-        public CategoryLogger(IIgniteLogger logger, string category)
-        {
-            IgniteArgumentCheck.NotNull(logger);
-
-            // If logger is already a CategoryLogger, get underlying logger 
instead to avoid unnecessary nesting.
-            _logger = logger is CategoryLogger catLogger ? catLogger._logger : 
logger;
-
-            Category = category;
-        }
-
-        /// <summary>
-        /// Gets the category name.
-        /// </summary>
-        public string Category { get; }
-
-        /// <summary>
-        /// Logs the specified message.
-        /// </summary>
-        /// <param name="level">The level.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments to format <paramref 
name="message" />.
-        /// Can be null (formatting will not occur).</param>
-        /// <param name="formatProvider">The format provider. Can be null if 
<paramref name="args" /> is null.</param>
-        /// <param name="category">The logging category name.</param>
-        /// <param name="nativeErrorInfo">The native error information.</param>
-        /// <param name="ex">The exception. Can be null.</param>
-        public void Log(
-            LogLevel level,
-            string message,
-            object?[]? args,
-            IFormatProvider? formatProvider,
-            string? category,
-            string? nativeErrorInfo,
-            Exception? ex)
-        {
-            _logger.Log(level, message, args, formatProvider, category ?? 
Category, nativeErrorInfo, ex);
-        }
-
-        /// <summary>
-        /// Determines whether the specified log level is enabled.
-        /// </summary>
-        /// <param name="level">The level.</param>
-        /// <returns>
-        /// Value indicating whether the specified log level is enabled.
-        /// </returns>
-        public bool IsEnabled(LogLevel level)
-        {
-            return _logger.IsEnabled(level);
-        }
-
-        /// <inheritdoc />
-        public override string ToString() =>
-            new IgniteToStringBuilder(GetType())
-                .Append(Category)
-                .Build();
-    }
-}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Log/ConsoleLogger.cs 
b/modules/platforms/dotnet/Apache.Ignite/Log/ConsoleLogger.cs
deleted file mode 100644
index 39ff5d2ea3..0000000000
--- a/modules/platforms/dotnet/Apache.Ignite/Log/ConsoleLogger.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Log
-{
-    using System;
-    using System.Globalization;
-    using System.Text;
-    using Internal.Common;
-
-    /// <summary>
-    /// Logs to Console.
-    /// <para />
-    /// Simple logger implementation without dependencies, provided out of the 
box for convenience.
-    /// For anything more complex please use NLog/log4net integrations.
-    /// </summary>
-    public sealed class ConsoleLogger : IIgniteLogger
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ConsoleLogger"/> 
class.
-        /// Uses <see cref="LogLevel.Warn"/> minimum level.
-        /// </summary>
-        public ConsoleLogger()
-        {
-            MinLevel = LogLevel.Warn;
-        }
-
-        /// <summary>
-        /// Gets or sets the minimum level to be logged. Any levels lower than 
that are ignored.
-        /// Default is <see cref="LogLevel.Warn"/>.
-        /// </summary>
-        public LogLevel MinLevel { get; set; }
-
-        /// <summary>
-        /// Gets or sets DateTime provider.
-        /// </summary>
-        public IDateTimeProvider? DateTimeProvider { get; set; }
-
-        /// <summary>
-        /// Logs the specified message.
-        /// </summary>
-        /// <param name="level">The level.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments to format <paramref 
name="message" />.
-        /// Can be null (formatting will not occur).</param>
-        /// <param name="formatProvider">The format provider. Can be null if 
<paramref name="args" /> is null.</param>
-        /// <param name="category">The logging category name.</param>
-        /// <param name="nativeErrorInfo">The native error information.</param>
-        /// <param name="ex">The exception. Can be null.</param>
-        public void Log(
-            LogLevel level,
-            string message,
-            object?[]? args,
-            IFormatProvider? formatProvider,
-            string? category,
-            string? nativeErrorInfo,
-            Exception? ex)
-        {
-            if (!IsEnabled(level))
-            {
-                return;
-            }
-
-            var dateTimeProvider = DateTimeProvider ?? 
LocalDateTimeProvider.Instance;
-
-            var sb = new StringBuilder().AppendFormat(
-                CultureInfo.InvariantCulture,
-                "[{0:HH:mm:ss}] [{1}] [{2}] ",
-                dateTimeProvider.Now(),
-                level,
-                category);
-
-            if (args is { Length: > 0 })
-            {
-                sb.AppendFormat(formatProvider, message, args);
-            }
-            else
-            {
-                sb.Append(message);
-            }
-
-            if (ex != null)
-            {
-                sb.AppendFormat(CultureInfo.InvariantCulture, " (exception: 
{0})", ex);
-            }
-
-            Console.WriteLine(sb.ToString());
-        }
-
-        /// <summary>
-        /// Determines whether the specified log level is enabled.
-        /// </summary>
-        /// <param name="level">The level.</param>
-        /// <returns>Value indicating whether the specified log level is 
enabled.</returns>
-        public bool IsEnabled(LogLevel level)
-        {
-            return level >= MinLevel;
-        }
-
-        /// <inheritdoc />
-        public override string ToString() =>
-            new IgniteToStringBuilder(GetType())
-                .Append(MinLevel)
-                .Build();
-    }
-}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Log/IDateTimeProvider.cs 
b/modules/platforms/dotnet/Apache.Ignite/Log/IDateTimeProvider.cs
deleted file mode 100644
index c7e40407f9..0000000000
--- a/modules/platforms/dotnet/Apache.Ignite/Log/IDateTimeProvider.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Log
-{
-    using System;
-
-    /// <summary>
-    /// <see cref="DateTime"/> abstraction for logging.
-    /// </summary>
-    public interface IDateTimeProvider
-    {
-        /// <summary>
-        /// Gets current <see cref="DateTime"/>.
-        /// </summary>
-        /// <returns>Current DateTime.</returns>
-        DateTime Now();
-    }
-}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Log/IIgniteLogger.cs 
b/modules/platforms/dotnet/Apache.Ignite/Log/IIgniteLogger.cs
deleted file mode 100644
index 134c5664d2..0000000000
--- a/modules/platforms/dotnet/Apache.Ignite/Log/IIgniteLogger.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Log
-{
-    using System;
-
-    /// <summary>
-    /// Defines Ignite logging interface.
-    /// <para />
-    /// This interface only provides essential log methods.
-    /// All convenience overloads are in <see cref="LoggerExtensions"/>.
-    /// </summary>
-    public interface IIgniteLogger
-    {
-        /// <summary>
-        /// Logs the specified message.
-        /// </summary>
-        /// <param name="level">The level.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments to format <paramref 
name="message" />.
-        /// Can be null (formatting will not occur).</param>
-        /// <param name="formatProvider">The format provider. Can be null if 
<paramref name="args" /> is null.</param>
-        /// <param name="category">The logging category name.</param>
-        /// <param name="nativeErrorInfo">The native error information.</param>
-        /// <param name="ex">The exception. Can be null.</param>
-        void Log(
-            LogLevel level,
-            string message,
-            object?[]? args,
-            IFormatProvider? formatProvider,
-            string? category,
-            string? nativeErrorInfo,
-            Exception? ex);
-
-        /// <summary>
-        /// Determines whether the specified log level is enabled.
-        /// </summary>
-        /// <param name="level">The level.</param>
-        /// <returns>Value indicating whether the specified log level is 
enabled.</returns>
-        bool IsEnabled(LogLevel level);
-    }
-}
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Log/LocalDateTimeProvider.cs 
b/modules/platforms/dotnet/Apache.Ignite/Log/LocalDateTimeProvider.cs
deleted file mode 100644
index 7bafd37941..0000000000
--- a/modules/platforms/dotnet/Apache.Ignite/Log/LocalDateTimeProvider.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Log
-{
-    using System;
-    using System.Diagnostics.CodeAnalysis;
-    using Internal.Common;
-
-    /// <summary>
-    /// Returns <see cref="DateTime.Now"/>.
-    /// </summary>
-    public sealed class LocalDateTimeProvider : IDateTimeProvider
-    {
-        /// <summary>
-        /// Default instance.
-        /// </summary>
-        [SuppressMessage(
-            "Microsoft.Security",
-            "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes",
-            Justification = "Type is immutable.")]
-        public static readonly LocalDateTimeProvider Instance = new();
-
-        /// <inheritdoc />
-        public DateTime Now()
-        {
-            return DateTime.Now;
-        }
-
-        /// <inheritdoc />
-        public override string ToString() => 
IgniteToStringBuilder.Build(GetType());
-    }
-}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Log/LogLevel.cs 
b/modules/platforms/dotnet/Apache.Ignite/Log/LogLevel.cs
deleted file mode 100644
index b9a486f96c..0000000000
--- a/modules/platforms/dotnet/Apache.Ignite/Log/LogLevel.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Log
-{
-    using System;
-
-    /// <summary>
-    /// Defines log levels.
-    /// </summary>
-    [Serializable]
-    public enum LogLevel
-    {
-        /// <summary>
-        /// Trace log level.
-        /// </summary>
-        Trace = 0,
-
-        /// <summary>
-        /// Debug log level.
-        /// </summary>
-        Debug = 1,
-
-        /// <summary>
-        /// Info log level.
-        /// </summary>
-        Info = 2,
-
-        /// <summary>
-        /// Warning log level.
-        /// </summary>
-        Warn = 3,
-
-        /// <summary>
-        /// Error log level.
-        /// </summary>
-        Error = 4
-    }
-}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Log/LoggerExtensions.cs 
b/modules/platforms/dotnet/Apache.Ignite/Log/LoggerExtensions.cs
deleted file mode 100644
index d91af1749f..0000000000
--- a/modules/platforms/dotnet/Apache.Ignite/Log/LoggerExtensions.cs
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Log
-{
-    using System;
-    using System.Globalization;
-    using Internal.Common;
-
-    /// <summary>
-    /// Extension methods for <see cref="IIgniteLogger" />.
-    /// </summary>
-    public static class LoggerExtensions
-    {
-        // 4 overloads per level (message, message+args, ex+message, 
ex+message+args)
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Trace"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        public static void Trace(this IIgniteLogger logger, string message)
-        {
-            Log(logger, LogLevel.Trace, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Trace"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Trace(this IIgniteLogger logger, string message, 
params object?[]? args)
-        {
-            Log(logger, LogLevel.Trace, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Trace"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        public static void Trace(this IIgniteLogger logger, Exception? ex, 
string message)
-        {
-            Log(logger, LogLevel.Trace, ex, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Trace"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Trace(this IIgniteLogger logger, Exception? ex, 
string message, params object?[]? args)
-        {
-            Log(logger, LogLevel.Trace, ex, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Debug"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        public static void Debug(this IIgniteLogger logger, string message)
-        {
-            Log(logger, LogLevel.Debug, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Debug"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Debug(this IIgniteLogger logger, string message, 
params object?[]? args)
-        {
-            Log(logger, LogLevel.Debug, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Debug"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        public static void Debug(this IIgniteLogger logger, Exception? ex, 
string message)
-        {
-            Log(logger, LogLevel.Debug, ex, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Debug"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Debug(this IIgniteLogger logger, Exception? ex, 
string message, params object?[]? args)
-        {
-            Log(logger, LogLevel.Debug, ex, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Info"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        public static void Info(this IIgniteLogger logger, string message)
-        {
-            Log(logger, LogLevel.Info, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Info"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Info(this IIgniteLogger logger, string message, 
params object?[]? args)
-        {
-            Log(logger, LogLevel.Info, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Info"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        public static void Info(this IIgniteLogger logger, Exception? ex, 
string message)
-        {
-            Log(logger, LogLevel.Info, ex, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Info"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Info(this IIgniteLogger logger, Exception? ex, 
string message, params object?[]? args)
-        {
-            Log(logger, LogLevel.Info, ex, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Warn"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        public static void Warn(this IIgniteLogger logger, string message)
-        {
-            Log(logger, LogLevel.Warn, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Warn"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Warn(this IIgniteLogger logger, string message, 
params object?[]? args)
-        {
-            Log(logger, LogLevel.Warn, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Warn"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        public static void Warn(this IIgniteLogger logger, Exception? ex, 
string message)
-        {
-            Log(logger, LogLevel.Warn, ex, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Warn"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Warn(this IIgniteLogger logger, Exception? ex, 
string message, params object?[]? args)
-        {
-            Log(logger, LogLevel.Warn, ex, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Error"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        public static void Error(this IIgniteLogger logger, string message)
-        {
-            Log(logger, LogLevel.Error, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Error"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Error(this IIgniteLogger logger, string message, 
params object?[]? args)
-        {
-            Log(logger, LogLevel.Error, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Error"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        public static void Error(this IIgniteLogger logger, Exception? ex, 
string message)
-        {
-            Log(logger, LogLevel.Error, ex, message);
-        }
-
-        /// <summary>
-        /// Logs the message with <see cref="LogLevel.Error"/> level.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Error(this IIgniteLogger logger, Exception? ex, 
string message, params object?[]? args)
-        {
-            Log(logger, LogLevel.Error, ex, message, args);
-        }
-
-        /// <summary>
-        /// Logs the message.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="level">The level.</param>
-        /// <param name="message">The message.</param>
-        public static void Log(this IIgniteLogger logger, LogLevel level, 
string message)
-        {
-            IgniteArgumentCheck.NotNull(logger);
-
-            logger.Log(level, message, null, null, null, null, null);
-        }
-
-        /// <summary>
-        /// Logs the message.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="level">The level.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Log(this IIgniteLogger logger, LogLevel level, 
string message, params object?[]? args)
-        {
-            IgniteArgumentCheck.NotNull(logger);
-
-            logger.Log(level, message, args, CultureInfo.InvariantCulture, 
null, null, null);
-        }
-
-        /// <summary>
-        /// Logs the message.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="level">The level.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        public static void Log(this IIgniteLogger logger, LogLevel level, 
Exception? ex, string message)
-        {
-            IgniteArgumentCheck.NotNull(logger);
-
-            logger.Log(level, message, null, null, null, null, ex);
-        }
-
-        /// <summary>
-        /// Logs the message.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="level">The level.</param>
-        /// <param name="ex">The exception.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="args">The arguments.</param>
-        public static void Log(this IIgniteLogger logger, LogLevel level, 
Exception? ex, string message, params object?[]? args)
-        {
-            IgniteArgumentCheck.NotNull(logger);
-
-            logger.Log(level, message, args, CultureInfo.InvariantCulture, 
null, null, ex);
-        }
-
-        /// <summary>
-        /// Gets the <see cref="CategoryLogger"/> with a specified category 
that wraps provided logger.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="category">The category.</param>
-        /// <returns>Logger that uses specified category when no other 
category is provided.</returns>
-        public static IIgniteLogger? GetLogger(this IIgniteLogger? logger, 
string category)
-        {
-            IgniteArgumentCheck.NotNull(category);
-
-            return logger == null ? null : new CategoryLogger(logger, 
category);
-        }
-
-        /// <summary>
-        /// Gets the <see cref="CategoryLogger"/> with a specified category 
that wraps provided logger.
-        /// </summary>
-        /// <param name="logger">The logger.</param>
-        /// <param name="category">The category as a type.</param>
-        /// <returns>Logger that uses specified category when no other 
category is provided.</returns>
-        public static IIgniteLogger? GetLogger(this IIgniteLogger? logger, 
Type category)
-        {
-            IgniteArgumentCheck.NotNull(category);
-
-            return logger == null ? null : new CategoryLogger(logger, 
category.Name);
-        }
-    }
-}
diff --git a/modules/platforms/dotnet/README.md 
b/modules/platforms/dotnet/README.md
index c48e566963..281884c7fe 100644
--- a/modules/platforms/dotnet/README.md
+++ b/modules/platforms/dotnet/README.md
@@ -79,10 +79,7 @@ var cfg = new IgniteClientConfiguration
     },    
         
     // Retry all read operations in case of network issues.
-    RetryPolicy = new RetryReadPolicy { RetryLimit = 32 },
-
-    // Log to console.
-    Logger = new ConsoleLogger { MinLevel = LogLevel.Debug }
+    RetryPolicy = new RetryReadPolicy { RetryLimit = 32 }
 };
 ```
 
@@ -239,7 +236,29 @@ Ignite client implements a number of features to improve 
reliability and perform
 
 ## Logging
 
-To enable logging, set `IgniteClientConfiguration.Logger` property. 
`ConsoleLogger` is provided out of the box. Other loggers can be integrated by 
implementing `IIgniteLogger` interface.
+To enable logging, set `IgniteClientConfiguration.LoggerFactory` property. It 
uses the standard 
[Microsoft.Extensions.Logging](https://docs.microsoft.com/en-us/dotnet/core/extensions/logging)
 API.
+
+For example, to log to console (requires 
`Microsoft.Extensions.Logging.Console` package):
+
+```cs
+var cfg = new IgniteClientConfiguration
+{
+    LoggerFactory = LoggerFactory.Create(builder => 
builder.AddConsole().SetMinimumLevel(LogLevel.Debug))
+};
+```
+
+Or with Serilog (requires `Serilog.Extensions.Logging` and 
`Serilog.Sinks.Console` packages):
+
+```cs
+var cfg = new IgniteClientConfiguration
+{
+    LoggerFactory = LoggerFactory.Create(builder =>
+        builder.AddSerilog(new LoggerConfiguration()
+            .MinimumLevel.Debug()
+            .WriteTo.Console()
+            .CreateLogger()))
+};
+```
 
 
 ## Metrics

Reply via email to