📜 ⬆️ ⬇️

Logging of all queries to the Database in Asp.Net Boilerplate 4.3 .Net Core 2.1

Often in the project there is an incomprehensible error for which you need maximum logging of all queries to the Database. The article will help those who write (deploy on the server) one of their first projects on the Asp.Net Boilerplate .

The article is written for newcomers to Asp.Net Boilerplate technology, who have any strange error related to the Database. When using PostgreSQL, this may be, for example, the first project. The motivation for writing the article was that the solution to this issue is not so easy to find on the Internet even in English, not to mention the fact that the solutions found do not fully answer all questions on this issue.

Product Version: Asp.Net Boilerplate 4.3, .NET Core 2.1

In the case of performing these steps : In your main log file you will see all the queries to the Database logged.
')

Step 1


You need to create a logger. On the Boilerplate platform, there is already a configured internal logger. This may be Log4Net as standard. There is no need to make any manipulations with him. Instead, it is enough to create a logger class, which is registered as a handler for all log messages from the Database.

Step 1.1


Project * .EntityFrameworkCore. Here we need to create 2 classes. On the one hand, a logger that will do only one thing is to output all messages from the database to the system log. Let's call it MyLogger. And the provider of this logger, who will create MyLogger. The provider is called MyLoggerProvider.

We create one file with the following code (one file for simplification, although, of course, there must be one class in each file):

public class MyLoggerProvider : ILoggerProvider { private Castle.Core.Logging.ILogger _logger; public MyLoggerProvider(Castle.Core.Logging.ILogger logger) { _logger = logger; } public ILogger CreateLogger(string categoryName) { return new MyLogger(_logger); } public void Dispose() { } } public class MyLogger : ILogger { private Castle.Core.Logging.ILogger _logger; public MyLogger(Castle.Core.Logging.ILogger logger) { _logger = logger; } public IDisposable BeginScope<TState>(TState state) { return null; } public bool IsEnabled(LogLevel logLevel) { return true; } public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { if (IsEnabled(logLevel)) { var msg = formatter(state, exception); _logger.Info("DB-REQUEST: " + msg); } } } 

If you look closely, you can see how in the parameters MyLoggerProvider, and then some other logger is forwarded to MyLogger. It turns out the third! The bottom line is that this third is the class of the logging infrastructure level, which must be obtained from the depths of the Boilerplate by means of which the messages will be stored in the log. See below.

Step 2


In the framework of the same project *. EntityFrameworkCore, go to the file * DbContextConfigurer.cs and make the following changes in both Configure () methods:

2.1) Add a loggerfactory parameter of type LoggerFactory

2.2) Add two lines to the method body:

 builder.UseLoggerFactory(loggerFactory); builder.EnableSensitiveDataLogging(true); 

The point of UseLoggerFactory is to enable the use of loggerFactory, which is passed in parameters for database logging. It is very important to remember that here we enable database logging.

The meaning of EnableSensitiveDataLogging is to enable not only logging of database requests, but also to capture all data in these requests. Without this setting, you will not be able to see the data in the requests - they will be replaced with question marks.

Step 3


In the framework of the same project *. EntityFrameworkCore, go to the file * DbContextFactory.cs.

3.1) Add a new method:

 private LoggerFactory GetDbLoggerFactory() { return new LoggerFactory(new[] { new MyLoggerProvider(NullLogger.Instance) }); } 

3.2) In the CreateDbContext () method:
Since we previously added a new parameter to both implementations of Configure (), then an error should be displayed here. The time has come to specify this new parameter - register with GetDbLoggerFactory () comma. Those. the value of the new parameter loggerFactory should be returned by the new method from p. 3.1.

Step 4


In the framework of the same project *. EntityFrameworkCore, go to the file * EntityFrameworkModule.cs.

4.1) Add a new method:

 private LoggerFactory GetDbLoggerFactory() { return new LoggerFactory(new[] { new MyLoggerProvider(Logger) }); } 

4.2) In the PreInitialize () method:

Since we previously added a new parameter to both implementations of Configure (), then an error should also be output here. We specify the new parameter in the same way as in p. 3.2 - we specify comma separated GetDbLoggerFactory (). Those. the value of the new parameter loggerFactory should be returned by the new method from clause 4.1.

Result


In the main log file (Logs.txt by default), you will see all the queries preceded by a sequence of DB-REQUEST characters (just by this you can search for the data in the log).

General understanding of the solution


So now I will explain what we did. The explanation is at the end of the article, because it's often interesting for readers to start doing something specific.

In the class * DbContextFactory, as well as * EntityFrameworkModule, we create our LoggerFactory, in the parameters of which we specify the created MyLoggerProvider. But as an infrastructure class that will directly perform logging in the first case (* DbContextFactory), we pass the NullLogger.Instance stub so that there are no records. In the second case (* EntityFrameworkModule) we pass the logger, which is already in the Abp-module. This is a logger field. It is already initialized and can be logged with it. Accordingly, our MyLogger will be able to write to the Logs.txt file using this class.

The whole logic is that this factory loggerFactory is set as a log factory for the processes of working with the Database. As soon as a logger is needed, it is created by the factory. And this is our MyLogger, which, in turn, logs everything that comes in Logs.txt (or to the source to which your main logs are configured).

As you can see, not everything is so simple and the levels of abstractions sometimes freeze, especially beginners! Ask your questions in the comments.

Note:

- The solution is created in order to enable the logger, understand what the error is and turn it off. It is not designed for long-term use.

Source: https://habr.com/ru/post/444660/


All Articles