服务器端
ABP使用Castle Windsor的日志设施。它可以使用不同的日志库:Log4Net、NLog、Serilog等等。Castle为所有日志程序库提供了一个公共接口,这样,我们可以独立的使用某个日志库,并且随时可以变成另外的日志库。
Log4Net是.NET最流行的日志库之一,ABP模板附带了可以使用的Log4Net,Log4Net依赖项只有一行代码(如配置部分所示),因此可以轻松地将其更改为其他想使用的库。
获取日志记录器
不管你使用哪个日志库,,写日志的代码是一样的(多亏了Castle的通用ILogger接口)。
首先我们需要获得一个Logger对象来编写日志,由于ABP强烈的使用依赖注入,所以我们可以使用属性注入(或构造函数注入)模式轻松地注入一个Logger对象。下面是一个写日志行的示例类:
using Castle.Core.Logging; //1: Import Logging namespace public class TaskAppService : ITaskAppService { //2: Getting a logger using property injection public ILogger Logger { get; set; } public TaskAppService() { //3: Do not write logs if no Logger supplied. Logger = NullLogger.Instance; } public void CreateTask(CreateTaskInput input) { //4: Write logs Logger.Info("Creating a new task with description: " + input.Description); //TODO: save task to database... } }
首先,我们导入了Castle的ILogger接口的名称空间;
其次,我们定义了一个名为Logger的公共ILogger对象。这是我们用来写日志的对象。依赖项注入系统将在创建TaskAppService对象后设置(注入)此属性。这就是所谓的属性注入模式;
第三,我们将Logger设置为NullLogger.Instance。没有这条线,系统可以很好地工作,但是使用属性注入模式是最佳实践。如果没有人设置日志程序,它将是null,当我们想要使用它时,我们将得到一个“object reference…”异常。这保证了它不是null。因此,如果没有人设置日志记录器,它将是NullLogger。这就是所谓的空对象模式。NullLogger实际上什么也不做。它不写任何日志。这样,我们的类可以使用或不使用实际的日志记录器。
最后,我们正在编写一个info级别的日志文本。有不同的级别(请参阅配置部分)。
如果我们调用CreateTask方法并检查日志文件,我们会看到如下所示的日志行:
INFO 2014-07-13 13:40:23,360 [8 ] SimpleTaskSystem.Tasks.TaskAppService - Creating a new task with description: Remember to drink milk before sleeping!
ABP为MVC控制器、WebAPI控制器、应用程序服务类等提供基类。它们声明一个Logger属性。这样,就可以直接使用这个日志程序来编写日志,而不需要注入。例如:
public class HomeController : SimpleTaskSystemControllerBase { public ActionResult Index() { Logger.Debug("A sample log message..."); return View(); } }
注意,SimpleTaskSystemControllerBase是我们的应用程序特定的基控制器,它继承了AbpController。这样,它就可以直接使用日志程序。还可以为其他类编写自己的公共基类。这样您就不必每次都注入一个logger。
配置
当从ABP模板创建应用程序时,就会为Log4Net完成所有配置。
默认配置的日志格式如下所示(每一行):
日志级别:调试、信息、警告、错误或致命。
日期和时间:日志行被写入的时间。
线程号:写日志行的线程号。
记录器名称:这通常是写日志行的类名称。
日志文本:您编写的实际日志文本。
它被定义在应用程序的log4net.config文件中,如下所示:
"1.0" encoding="utf-8" ?>"RollingFileAppender" type="log4net.Appender.RollingFileAppender" > "Logs/Logs.txt" /> "true" /> "Size" /> "10" /> "10000KB" /> "true" /> "log4net.Layout.PatternLayout"> "%-5level %date [%-5.5thread] %-40.40logger - %message%newline" /> ref ref="RollingFileAppender" /> "DEBUG" /> "NHibernate"> "WARN" />
Log4Net是高度可配置的,是一个强大的日志库。您可以将日志以不同的格式写入不同的目标(文本文件、数据库……)。您可以设置最低日志级别(在此配置中为NHibernate设置)。您可以将不同的日志记录器写入不同的日志文件。当日志文件达到特定大小时,它可以自动备份并创建一个新的日志文件(在这个配置中,每个文件的RollingFileAppender大小为10000 KB),等等……阅读它自己的配置文档以获得更多信息。
最后在Global.asax文件中,我们声明使用Log4Net与log4net.config文件:
public class MvcApplication : AbpWebApplication { protected override void Application_Start(object sender, EventArgs e) { IocManager.Instance.IocContainer.AddFacility(f => f.UseLog4Net().WithConfig("log4net.config")); base.Application_Start(sender, e); } }
这是log4net中唯一直接依赖的代码行。只有web项目依赖于log4net库的nuget包。可以轻松地更改到另一个库,而无需更改日志代码。
Abp.Castle.Log4Net 包
ABP使用Castle日志工具进行日志记录,它不直接依赖于log4net,如上所述。然而,Castle的Log4Net集成存在一个问题……它不支持最新的log4net。我们创建了一个NuGet包,app . castle。Log4Net,来解决这个问题。将这个包添加到我们的解决方案后,我们所要做的就是像这样更改应用程序启动方法中的代码:
public class MvcApplication : AbpWebApplication { protected override void Application_Start(object sender, EventArgs e) { IocManager.Instance.IocContainer.AddFacility(f => f.UseAbpLog4Net().WithConfig("log4net.config")); base.Application_Start(sender, e); } }
唯一的区别是我们使用了“UseAbpLog4Net()”方法(在Abp.Castle.Logging.Log4Net中定义)替代了 “UseLog4Net()”,当我们使用Abp.Castle.Log4Net包,不需要使用Castle.Windsor-log4net 和Castle.Core-log4net包.
如果你需要在运行时更改你的log4Net配置文件,并希望在不重启应用程序的情况下使更改立即生效,你可以使用以下方法:
public class MvcApplication : AbpWebApplication { protected override void Application_Start(object sender, EventArgs e) { options.IocManager.IocContainer.AddFacility( f => f.LogUsing(new Log4NetLoggerFactory("log4net.config", reloadOnChange:true)) ); base.Application_Start(sender, e); } }
客户端
ABP为客户端定义了一个简单的JavaScript日志API。它默认登录到浏览器的控制台。这里有一些JavaScript代码来写日志:
abp.log.warn('a sample log message...');
更多信息, 请看 logging API documentation.