Full Parsing of Log Function in ABP Framework

  • 2021-07-26 07:31:43
  • OfStack

ASP. NET Boilerplate uses the Castle Windsor 's logging facility logging tool and can use different logging class libraries such as Log4Net, NLog, Serilog... and so on. For all log class libraries, Castle provides a common interface to implement, we can easily deal with various special log libraries, and when business needs, it is easy to replace log components.

Translator's Note: What is Castle: Castle is an open source project for. NET platform, from data access framework ORM to IOC container, to MVC framework and AOP of WEB layer, which basically includes everything in the whole development process. The ioc container of ASP. NET Boilerplate is implemented through Castle.

Log4Net is the most popular log library component under asp. net, and the ASP. NET Boilerplate template also uses the Log4Net log library component. However, we only implement dependency injection of Log4Net with one key line of code (detailed in the configuration file below), so if you want to replace it with your own log component, it is also very easy.

Get the logger logger

No matter which log library component you choose, logging through code is all the same. (Here, the Castle 's universal ILogger interface is really awesome).

Let's get down to business: (Translator's Note: The following code is the source code analysis and implementation of Castle. Core of abp framework)

1. First of all, we need to deal with the logger object logger. ASP. NET Boilerplate framework uses dependency injection dependency injection technology, so we can easily use dependency injection to generate the logger object logger.

Next, let's look at how ASP. NET Boilerplate realizes logging function:


using Castle.Core.Logging; //1:  Import the namespace of the log, Castle.Core.Logging

public class TaskAppService : ITaskAppService
{ 
  //2: Gets the logger object through dependency injection. 
   Here we first define 1 A ILogger Type of public Attribute Logger This is the object we use to log. After creating the TaskAppService Object (that is, the task defined in our application) is implemented by attribute injection. 
  public ILogger Logger { get; set; }

  public TaskAppService()
  { 
   //3:  If there is no logger, return the logger 1 Empty instances, do not log. This is the best way to implement dependency injection, 
   //   If you don't define this empty logger, an exception will be generated when we get the object reference and instantiate it. 
   //   By doing so, the object is not empty. So, in other words, if you don't set up the logger, you don't log and return 1 A null Object of. 
   //  NullLogger Objects actually have nothing and are empty. By doing so, we can ensure that the class we defined works normally when instantiating. 
   Logger = NullLogger.Instance;
  }
 
  public void CreateTask(CreateTaskInput input) 
  {
   //4:  Write to log 
   Logger.Info("Creating a new task with description: " + input.Description);

   //TODO: save task to database... 
  } 
} 

After writing the log, we can view the log file in the following format:

INFO 2014-07-13 13:40:23,360 [8 ] SimpleTaskSystem.Tasks.TaskAppService - Creating a new task with description:Remember to drink milk before sleeping!

Using Logger through the base class

The ASP. NET Boilerplate framework provides the base classes of MVC Controllers, Web API Controllers and Application service classes (self-defined controllers and application services must inherit the base classes of ASP. NET Boilerplate, in other words, when your customized Web API controllers, mvc service, Application classes all inherit the base classes corresponding to ASP. NET Boilerplate framework, you can directly use the logger).


public class HomeController : SimpleTaskSystemControllerBase 
{ 
  public ActionResult Index() 
  { 
   Logger.Debug("A sample log message..."); 
   return View(); 
  } 
} 

SimpleTaskSystemControllerBase this base class controller is our own definition of the base class controller, he must inherit from AbpController.

In this way, the logger can work normally. Of course, you can also implement your own base class, so you don't have to use dependency injection.

Configure

If you generate your project through ASP. NET Boilerplate templates on the official website, all configurations of Log4Net are automatically generated.

The default configuration format is as follows:

Log level: There are five logging levels: DEBUG, INFO, WARN, ERROR or FATAL. Date and time: Logging time. Thread number: The thread number at which each log line is written. Logger name: The name of the logger, usually the class name. Log text: The contents of the log you wrote.

Configuration file: log4net. config 1 is generally under the web directory of the project.


<?xml version="1.0" encoding="utf-8" ?>
<log4net>
 <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
  <file value="Logs/Logs.txt" />
  <appendToFile value="true" />
  <rollingStyle value="Size" />
  <maxSizeRollBackups value="10" />
  <maximumFileSize value="10000KB" />
  <staticLogFileName value="true" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
  </layout>
 </appender>
 <root>
  <appender-ref ref="RollingFileAppender" />
  <level value="DEBUG" />
 </root>
 <logger name="NHibernate">
  <level value="WARN" />
 </logger>
</log4net>

Log4Net is a very powerful and easy to use log library component, you can write a variety of logs, such as write to txt files, write to the database and so on. You can set the minimum log level, just like the above configuration for NHibernate. Different loggers write different logs, and so on.

For specific usage, please refer to: http://logging.apache.org/log4net/release/config-examples.html

Finally, in the project's Global. asax file, define the configuration file for Log4Net:


public class MvcApplication : AbpWebApplication
{
  protected override void Application_Start(object sender, EventArgs e)
  {
    IocManager.Instance.IocContainer.AddFacility<LoggingFacility>(f => f.UseLog4Net().WithConfig("log4net.config"));
    base.Application_Start(sender, e);
  }
}

The logging component Log4Net is called in a few lines of code. The Log4Net library in the project is in the nuget package package. You can also replace it with other logging component libraries, but the code does not need to be changed. Because, our framework implements the logger through dependency injection!

Client side (Client)

Last but not least, you can also call the logger on the client side. On the client side, the ASP. NET Boilerplate framework has the corresponding javascript log API, which means that you can log the browser. The implementation code is as follows:


abp.log.warn('a sample log message...'); 

Attached: Client javascript api, here to explain is that you can use console. log in the client output log, but this API does not support all browsers, and may cause your script to appear abnormal, you can use our api, ours is safe, you can even overload or extend these api.


abp.log.debug('...');
abp.log.info('...');
abp.log.warn('...');
abp.log.error('...'); 
abp.log.fatal('...');


Audit Trace Log
ABP provides an infrastructure that automatically logs application interactions, recording caller information and parameter information for the methods you invoke. Essentially, the storage area contains:

tenant id (related tenant Id), user id (request user Id), server name (the service name of the request "the class corresponding to the call method"), method name (calling method name), parameters (method parameter "JSON format"), execution time (execution time), duration (execution time is "usually milliseconds"), IP address (client IP address), computer name (client name), exception (exception "if the method throws an exception").

With this information, we can not only know who did the operation, but also estimate the performance of the application and the exceptions thrown. Even more, you can get statistics about the usage of applications.

The audit system uses the IAbpSession interface to obtain the current user Id and the tenant ID.

Note: About the IAuditingStore interface

The audit system uses IAuditingStore interface to save audit information. The module-zero project is the complete implementation of this interface, but you can also implement this interface in your own way. If you don't want to implement this interface yourself, the SimpleLogAuditingStore class can be used directly by writing audit information to the log.

Configuration:
The Configuration. Auditing attribute can be used in your module initialization method (PreInitialize) to configure auditing, and the Auditing attribute is enabled by default (that is, true). You can disable it, as shown in the following figure:


public class MyModule : AbpModule
{
  public override void PreInitialize()
  {
    Configuration.Auditing.IsEnabled = false;
  }

  //...
}

The following are the properties of the audit configuration:


IsEnabled:  Used to set the audit system to be fully enabled or disabled. Default value: true.
IsEnabledForAnonymousUsers: If set to ture The audit logs of unlogged users are also saved. Default value : false.
MvcControllers:  In ASP.NET MVC  Use audit logs in controllers 
IsEnabled:  In ASP.NET MVC Enable in ( true ) or disable ( false ) Audit log .  Default value : true.
IsEnabledForChildActions:  For MVC actions Enable ( true ) or disable ( false ) Audit log .  Default value : false.
Selectors:  Select to use another class to handle the storage of audit logs. 

As you can see, the audit system separately provides an audit configuration for the mvc controller so that it can use it in different ways.

Selectors is a list of assertion (inferred type) selectors for choosing which way to save audit logs. Every selector contains 1 only 1 name and 1 assertion. Assert the default selector in the list, using the application service class. As shown in the following figure:


Configuration.Auditing.Selectors.Add(
  new NamedTypeSelector(
    "Abp.ApplicationServices",
    type => typeof (IApplicationService).IsAssignableFrom(type)
  )
);

You can add your own assertion selector to your module initialization method (PreInitialize). Similarly, if you don't like to use application services to save audit logs, you can also remove the assertion selector by name (name), which is why the name of the assertion selector must be only 1 (you can also find the selector by Linq to remove it).

Enable and disable audit logs through properties:
When you use configuration items to configure assertion selectors, you can enable and disable the audit system by using the Audited and DisableAuditing attributes to tag a single class or a single method. For example:


[Audited]
public class MyClass
{
  public void MyMethod1(int a)
  {
    //...
  }

  [DisableAuditing]
  public void MyMethod2(string b)
  {
    //...
  }

  public void MyMethod3(int a, int b)
  {
    //...
  }
}

In the above column, all methods in the MyClass class are audited except that the MyMethod2 explicitly tag does not need to be audited. Audited features can help you only want to save audit log methods, audit log saving.


Related articles: