欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Windows服务使用log4net记录日志

程序员文章站 2022-04-08 23:49:39
该文章是系列文章 "基于.NetCore和ABP框架如何让Windows服务执行Quartz定时作业" 的其中一篇。 比较流行的日志组件有以下四种,Topshelf都有相应的组件提供 "log4net" "NLog" "serilog" "Elmah" 本篇文章主要介绍log4net的使用。 在 " ......

该文章是系列文章 基于.netcore和abp框架如何让windows服务执行quartz定时作业 的其中一篇。

比较流行的日志组件有以下四种,topshelf都有相应的组件提供

本篇文章主要介绍log4net的使用。
使用topshelf创建windows服务中提到了当我们调试的时候console会打印出如下的类似日志

configuration result:
[success] name demo.myjob
[success] description demo.myjob service
[success] servicename demo.myjob
topshelf v4.2.0.194, .net framework v4.0.30319.42000
the demo.myjob service is now running, press control+c to exit.

该日志是如何打印出来的呢?
访问topshelf github的源码,在hostfactory.cs查看run执行逻辑,日志打印是通过调用hostlogger.get(type type) 方法获取了logwriter,logwriter是写日志接口。查看hostlogger.cs,可以看到logwriter的默认实现,该实现包含有三个类tracehostloggerconfigurator.cs 继承接口hostloggerconfiguratortracelogwriterfactory.cs 继承接口logwriterfactorytracelogwriter.cs 继承接口logwriter
如果我们需要实现log4net的日志访问,则需要实现三个类log4netloggerconfigurator、log4netloggerconfigurator、log4netlogwriter。我们可以自己实现,也可以使用topshelf提供的实现,需要引用nuget包topshelf.log4net。在run执行逻辑添加uselog4net,如下所示。

        public override void postinitialize()
        {
            hostfactory.run(configure =>
            {
                //定义服务描述
                configure.setdescription("demo.myjob service");
                configure.setdisplayname("demo.myjob");
                configure.setservicename("demo.myjob");

                configure.runaslocalsystem();

                //使用log4net记录日志
                configure.uselog4net("app.config");

                //定义操作
                configure.service<myjobservice>(service =>
                {
                    service.constructusing(_ => new myjobservice());
                    service.whenstarted(async _ => await _.startasync());
                    service.whenstopped(async _ => await _.stopasync());
                    service.whencontinued(async _ => await _.continueasync());
                    service.whenpaused(async _ => await _.pauseasync());
                });
            });
        }

在上述代码中可知,我们需要添加自己的配置文件,对log4net进行配置。注意:需将添加的配置文件的属性配置为如果较新则复制。因为uselog4net关于加载配置文件的逻辑,是加载当前应用目录下的指定名称的文件。
更多关于log4net的配置请访问:

未使用log4net打印日志时,打印出来的日志是黑底白字,我们可以通过log4net配置改变打印字体的颜色,使用managedcoloredconsoleappender,也可以通过rollingfileappender在本地机器生成log日志文件。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <log4net>
    <appender name="managedcoloredconsoleappender" type="log4net.appender.managedcoloredconsoleappender">
      <mapping>
        <level value="error" />
        <forecolor value="red" />
      </mapping>
      <mapping>
        <level value="info" />
        <forecolor value="green" />
      </mapping>
      <mapping>
        <level value="debug" />
        <forecolor value="blue" />
      </mapping>
      <mapping>
        <level value="warn" />
        <forecolor value="yellow" />
      </mapping>
      <layout type="log4net.layout.patternlayout">
        <conversionpattern value="%d{absolute} [%thread] %-5p %c{1}:%l - %m%n" />
      </layout>
      <filter type="log4net.filter.levelrangefilter">
        <param name="levelmin" value="debug" />
        <param name="levelmax" value="fatal" />
      </filter>
    </appender>
    <appender name="rollingfile" type="log4net.appender.rollingfileappender">
      <lockingmodel type="log4net.appender.fileappender+minimallock" />
      <file value=".\logs\" />
      <datepattern value="'my-windows-service-'dd.mm.yyyy'.log'" />
      <staticlogfilename value="false" />
      <appendtofile value="true" />
      <rollingstyle value="composite" />
      <maxsizerollbackups value="10" />
      <maximumfilesize value="5mb" />
      <layout type="log4net.layout.patternlayout">
        <conversionpattern value="%d [%t] %-5p %c - %m%n" />
      </layout>
    </appender>
    <root>
      <level value="debug" />
      <appender-ref ref="managedcoloredconsoleappender" />
      <appender-ref ref="rollingfile" />
    </root>
  </log4net>
</configuration>

在配置文件中使用了<file value=".\logs\" />指定了文件生成相对路径,该相对路径应指向的是应用程序当前目录下,该目录下确实生成了日志文件,但是很不爽的是在c:\windows\system32路径下也生成了文件。怎么解决该问题?通过log4net属性指定目录。
修改<file type="log4net.util.patternstring" value="%property{logsdirectory}\logs\" />,并需要添加一行配置代码log4net.globalcontext.properties["logsdirectory"] = appdomain.currentdomain.basedirectory;,如下所示。问题解决。

        public override void postinitialize()
        {
            log4net.globalcontext.properties["logsdirectory"] = appdomain.currentdomain.basedirectory;

            hostfactory.run(configure =>
            {
                //定义服务描述
                configure.setdescription("demo.myjob service");
                configure.setdisplayname("demo.myjob");
                configure.setservicename("demo.myjob");

                configure.runaslocalsystem();

                //使用log4net记录日志
                configure.uselog4net("app.config");

                //定义操作
                configure.service<myjobservice>(service =>
                {
                    service.constructusing(_ => new myjobservice());
                    service.whenstarted(async _ => await _.startasync());
                    service.whenstopped(async _ => await _.stopasync());
                    service.whencontinued(async _ => await _.continueasync());
                    service.whenpaused(async _ => await _.pauseasync());
                });
            });
        }