偶然机会发现了log4net(原谅我的闭门造车),发现是一款好用但是有点复杂的log开源库,好用是她提供了非常强大的记录log方式:Trace、Console、file、DB(我只用了这个几个orz)等等,复杂的是因为太丰富了,导致想要了解大部分功能的话需要花费很长时间去查看资料和测试(这是病得治,在使用log4net之前就花费很多时间去了解,也许真的是我太闲)。后来发现要是兼容公司现在的log系统,log4net提供的格式不符合要求,于是就想是不是自己写一个扩展的库去兼容不同的logger,于是又花了很多时间去了解log4net结构(log4net结构这是够复杂的,智商不够用呀)。嗯,后来因为我的懒惰,想法停滞不前了。。
最近优化别人的代码时,又发现了一个开源软件Quartz(再次原谅我吧)。这也是一款功能非常强大的开源库,可以轻松处理各种定时任务。到这里我仿佛有种醍醐灌顶的赶脚,以后要多些精力放在开源库上。一来使用开源库简化部分开发和后期维护工作,二来研究开源代码会让你成长很快。
使用Quartz时,发现她依赖于Common.Logging库,google一番后,发现原来这个就是一个兼容不同log库的开源库,且支持扩展。
在搜索各种开源软件时,发现了nuget。啥是nuget?nuget是一个开源的.net包管理器,总之就是好用。在vs2012及以上中已经集成了nuget工具。
在使用nuget安装需要的库时,如果库存在依赖nuget会自动帮你引用,所以依赖的库,这点非常好用,但也会导致错误出现 可以参考我写的这篇文章nuget 陷阱。
好了,下面开始测试。
1、修改app.config文件
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!--<section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=2.2.3.400,Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4" />-->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
</configSections>
<common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1211">
<arg key="configType" value="FILE-WATCH" />
<arg key="configFile" value="log4net.config" />
</factoryAdapter>
</logging>
</common>
<!--
<quartz>
</quartz>
-->
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.13.0" newVersion="1.2.13.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
对于common.logging的设置这里不做解释,具体可以查看官方文档Common.Logging,内容不是很多。
2、添加log4net.config
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<appSettings>
<!-- To enable internal log4net logging specify the following appSettings key -->
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<!-- This section contains the log4net configuration settings -->
<log4net>
<!-- Define some output appenders -->
<!-- RollingFileAppender to log the messages that their level are DEBUG and INFO -->
<appender name="RollingFileAppender_Info" type="log4net.Appender.RollingFileAppender">
<file value="log/info/" />
<appendToFile value="true" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100KB" />
<rollingStyle value="Composite" />
<datePattern value="yyyy-MM/yyyy-MM-dd".log"" />
<staticLogFileName value="false" />
<!-- Set filter,LevelRangeFilter -->
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="INFO" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<header value="[Header]
" />
<footer value="[Footer]
" />
<conversionPattern value="%date [%thread] %-5level <%logger> - %message%newline" />
</layout>
</appender>
<!-- RollingFileAppender to log the messages that their level are WARN or higher -->
<appender name="RollingFileAppender_Error" type="log4net.Appender.RollingFileAppender">
<file value="log/error/" />
<appendToFile value="true" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100KB" />
<rollingStyle value="Composite" />
<datePattern value="yyyy-MM/yyyy-MM-dd".log"" />
<staticLogFileName value="false" />
<!-- Set filter,LevelRangeFilter -->
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<header value="[Header]
" />
<footer value="[Footer]
" />
<conversionPattern value="%date [%thread] %-5level <%logger> - %message%newline" />
</layout>
</appender>
<!-- AdoNetAppender for Firebird database -->
<appender name="AdoNetAppender_Firebird" type="log4net.Appender.AdoNetAppender">
<bufferSize value="100"/>
<connectionType value="FirebirdSql.Data.FirebirdClient.FbConnection, FirebirdSql.Data.FirebirdClient, Version=4.2.0.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c"/>
<connectionString value="User=SYSDBA;Password=masterkey;Database=TEST.fdb;DataSource=localhost;Port=3050;Dialect=3;Charset=GB_2312;ServerType=1;"/>
<commandText value="INSERT INTO LOG(DATETIME,THREAD_NAME,LOG_LEVEL,LOGGER,MESSAGE,EXCEPTION) VALUES (@dateTime,@thread,@log_Level,@logger,@message,@exception)" />
<parameter>
<parameterName value="@dateTime"/>
<dbType value="DateTime"/>
<layout type="log4net.Layout.RawTimeStampLayout"></layout>
</parameter>
<parameter>
<parameterName value="@thread"/>
<dbType value="String"/>
<size value="36"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread"/>
</layout>
</parameter>
<parameter>
<parameterName value="@log_Level"/>
<dbType value="String"/>
<size value="36"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level"/>
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="64" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%.64logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message"/>
<dbType value="String"/>
<size value="1024"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message"/>
</layout>
</parameter>
<parameter>
<parameterName value="@exception"/>
<dbType value="String"/>
<size value="4048"/>
<layout type="log4net.Layout.ExceptionLayout"></layout>
</parameter>
</appender>
<!-- TraceAppender -->
<appender name ="TraceAppender" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<!-- Setup the root category, add the appenders and set the default level -->
<root>
<level value="INFO" />
<appender-ref ref="RollingFileAppender_Info" />
<appender-ref ref="RollingFileAppender_Error" />
</root>
<!--<logger name="">
<level value="ALL" />
<appender-ref value="AdoNetAppender_Firebird" />
</logger>-->
</log4net>
</configuration>
这个配置文件可以作为通用的log4net的配置文件,这样在其他项目中便可以直接使用了。
对于如何设置log4net的配置文件我倒没有发现好的文章,只好参考官方文档 Apache log4net。
如何设置layout可以参考log4net源码中PatternLayout.cs文件中的注释,解释的非常详细。
3、添加quartz.config文件
# You can configure your scheduler in either <quartz> configuration section
# or in quartz properties file
# Configuration section has precedence
quartz.scheduler.instanceName = ServerScheduler
# configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal
# job initialization plugin handles our xml reading, without it defaults are used
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml
quartz.jobStore.misfireThreshold = 60000
quartz.jobStore.type = Quartz.Simpl.RAMJobStore, Quartz
我不确定这部分配置是否起了作用orz(对quartz的了解还不够)。
4、添加quartz_jobs.xml文件
<?xml version="1.0" encoding="utf-8" ?>
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives>
<schedule>
<job>
<name>jobName1</name>
<group>jobGroup1</group>
<description>jobDesciption1</description>
<job-type>QuartzTest.TestJob, QuartzTest</job-type>
<durable>true</durable>
<recover>false</recover>
<job-data-map>
<entry>
<key>key0</key>
<value>value0</value>
</entry>
<entry>
<key>key1</key>
<value>value1</value>
</entry>
<entry>
<key>key2</key>
<value>value2</value>
</entry>
</job-data-map>
</job>
<trigger>
<simple>
<name>simpleName</name>
<group>simpleGroup</group>
<description>SimpleTriggerDescription</description>
<job-name>jobName1</job-name>
<job-group>jobGroup1</job-group>
<start-time>1982-06-28T18:15:00.0Z</start-time>
<end-time>2020-05-04T18:13:51.0Z</end-time>
<misfire-instruction>SmartPolicy</misfire-instruction>
<repeat-count>100</repeat-count>
<repeat-interval>3000</repeat-interval>
</simple>
</trigger>
</schedule>
</job-scheduling-data>
设置quartz如何工作,关于这部分设置可以参考这篇文章
通过配置文件实现任务调度。
5、继承IJob,实现Execute方法,设置scheduler,quartz和log4net就可以正常工作了,关于代码的编写这里就不再赘述,相关的文章介绍特别多。
orz我好像啥也没做吗,我不生产文章,我只是文章的搬运工。。。。