Quartz任务调度 服务日志+log4net打印日志+制作windows服务

引言

  现在许多的项目都需要定时的服务进行支撑,而我们经常用到的定时服务就是Quartz任务调度了。不过我们在使用定时Job进行获取的时候,有时候我们就需要记录一下自定义的日志,甚至我们还会对执行定时Job脚本中,本身的线程启动和触发器等相关信息进行记录,这就用到了Common.Logging.log4net了,但同时它在控制台上输出相应信息的同时,并不能对这些信息进行日志文件的记录与存储。

  有关log4net的相关使用,详情请看之前的博文:http://www.cnblogs.com/huanghzm/p/4754890.html

 

  而本文的主要目的就是处理Quartz系统日志与log4net的相互结合,最后附带说明了利用Topshlef坐直windows服务。

准备

  1、安装指定的程序包

  Install-Package Quartz

  Install-Package Common.Logging.Log4Net1211(安装这个的时候会自定安装其依赖项,即Log4Net)

  Install-Package Topshelf

  2、配置文件设置

<configSections>
    <sectionGroup name="common">
      <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
    </sectionGroup>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  </configSections>


<common>
    <logging>
      <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1211">
        <arg key="configType" value="INLINE" />
      </factoryAdapter>
    </logging>
  </common>

  <log4net>
    <!--错误日志-->
    <!--自定义错误异常-->
    <appender name="CustomExAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Log\\LogCustomEx\\" />
      <param name="AppendToFile" value="true" />
      <param name="MaxFileSize" value="10240" />
      <param name="MaxSizeRollBackups" value="100" />
      <param name="StaticLogFileName" value="false" />
      <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
      <param name="RollingStyle" value="Date" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n日志描述:%message%newline %n" />
      </layout>
    </appender>

    <appender name="ErrorExAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Log\\LogErrorEx\\" />
      <param name="AppendToFile" value="true" />
      <param name="MaxFileSize" value="10240" />
      <param name="MaxSizeRollBackups" value="100" />
      <param name="StaticLogFileName" value="false" />
      <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
      <param name="RollingStyle" value="Date" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n日志描述:%message%newline %n" />
      </layout>
    </appender>

    <!--CustomEx日志-->
    <logger name="LogCustomEx">
      <level value="INFO" />
      <appender-ref ref="CustomExAppender" />
    </logger>
    <!--Error日志-->
    <logger name="LogErrorEx">
      <level value="ERROR" />
      <appender-ref ref="ErrorExAppender" />
    </logger>

    <!--服务执行日志-->
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Log\\ServerLog\\" />
      <param name="AppendToFile" value="true" />
      <param name="MaxFileSize" value="10240" />
      <param name="MaxSizeRollBackups" value="100" />
      <param name="StaticLogFileName" value="false" />
      <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
      <param name="RollingStyle" value="Date" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
      </layout>
    </appender>

    <!-- 控制台前台显示日志 -->
    <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <mapping>
        <level value="ERROR" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
      <mapping>
        <level value="Info" />
        <foreColor value="Green" />
      </mapping>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="Info" />
        <param name="LevelMax" value="Fatal" />
      </filter>
    </appender>

    <root>
      <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) -->
      <level value="all" />
      <appender-ref ref="ColoredConsoleAppender"/>
      <appender-ref ref="RollingLogFileAppender"/>
    </root>

  </log4net>
App.Config

让世界跑起来

  1、配置相关Job类(JobInfo[对象]、JobType[类型]、JobInfoList[触发器、时间]) 名称、触发器、群组、类型(根据不同的类型执行不同的Job内容)

public class JobInfo
    {
        public JobInfo(string jobName, string group, string trigger, JobType jobType)
        {
            if (jobName == null || trigger == null || group == null)
            {
                throw new ArgumentNullException("jobName");
            }
            this.JobName = jobName;
            this.Trigger = trigger;
            this.Group = group;
            this.JobType = jobType;
        }

        /// <summary>
        /// 名称
        /// </summary>
        public string JobName { get; set; }

        /// <summary>
        /// Job的触发器  cron表达式
        /// </summary>
        public string Trigger { get; set; }

        /// <summary>
        /// 群组
        /// </summary>
        public string Group { get; set; }

        /// <summary>
        /// Job类型
        /// </summary>
        public JobType JobType { get; set; }
    }

    /// <summary>
    /// Job类型枚举
    /// </summary>
    public enum JobType
    {
        /// <summary>
        /// 任务1
        /// </summary>
        Job1 = 1,
        /// <summary>
        /// 任务2
        /// </summary>
        Job2 = 2
    }
JobInfo
public class JobInfoList
    {
        /// <summary>
        /// 脚本服务组
        /// </summary>
        public static List<JobInfo> JobList_ZhongShanHos = new List<JobInfo>
        {
            new JobInfo("任务1", "测试脚本", "*/5 * * * * ?", JobType.Job1),
            new JobInfo("任务2", "测试脚本", "*/7 * * * * ?", JobType.Job2)
            
        };
    }
JobInfoList

  2、配置具体的Job内容与需要输出的自定义日志,这里的日志使用log4net作为记录 (TestJob.cs)

public class TestJob : IJob
    {
        private static readonly log4net.ILog LogInfo = log4net.LogManager.GetLogger("LogCustomEx");
        private static readonly log4net.ILog LogError = log4net.LogManager.GetLogger("LogError");

        public void Execute(IJobExecutionContext context)
        {
            var map = context.JobDetail.JobDataMap;
            var jobInfo = map["KEY"] as JobInfo;
            if (jobInfo == null) { return; }

            //记录日志
            LogInfo.Info("\n【服务已启动】" + "\n【启动组】:" + jobInfo.Group + "\n【启动名称】:" + jobInfo.JobName + "\n【启动时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

            try
            {
                switch (jobInfo.JobType)
                {
                    //基础信息
                    case JobType.Job1: LogInfo.Info("这是任务1"); break;
                    case JobType.Job2: LogInfo.Info("这是任务2"); break;

                    default: break;
                }
            }
            catch (Exception ex)
            {
                //记录日志
                LogError.Error("\n【服务执行出错】" +
                              "\n【启动组】:" + jobInfo.Group +
                              "\n【启动名称】:" + jobInfo.JobName +
                              "\n【时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") +
                              "\n【错误信息】:" + ex.Message);
                return;
            }
        }
    }
TestJob

  3、配置Job执行方法

public sealed class ServerRunner : ServiceControl, ServiceSuspend
    {
        private readonly IScheduler scheduler;

        public ServerRunner()
        {
            scheduler = StdSchedulerFactory.GetDefaultScheduler();
        }

        public bool Start(HostControl hostControl)
        {
            var jobList = new List<JobInfo>();

            //配置JobList任务
            jobList.AddRange(JobInfoList.JobList_ZhongShanHos);

            jobList.ForEach(
                x =>
                {
                    var dic = new Dictionary<string, JobInfo> { { "KEY", x } };
                    var map = new JobDataMap(dic);
                    var job =
                        JobBuilder.Create<TestJob>()
                            .WithIdentity(x.JobName, x.Group)
                            .UsingJobData(map)
                            .RequestRecovery()
                            .Build();
                    var trigger =
                        TriggerBuilder.Create()
                            .WithIdentity(x.JobName, x.Group)
                            .WithCronSchedule(x.Trigger)
                            .Build();
                    scheduler.ScheduleJob(job, trigger);
                });
            scheduler.Start();
            return true;
        }

        public bool Stop(HostControl hostControl)
        {
            scheduler.Shutdown(false);
            return true;
        }

        public bool Continue(HostControl hostControl)
        {
            scheduler.ResumeAll();
            return true;
        }

        public bool Pause(HostControl hostControl)
        {
            scheduler.PauseAll();
            return true;
        }
    }
ServerRunner

  4、配置入口文件

class Program
    {
        static void Main(string[] args)
        {
            //配置Log4日志
            log4net.Config.XmlConfigurator.Configure();

            //Windows服务
            HostFactory.Run(x =>
            {
                x.UseLog4Net();

                x.Service<ServerRunner>();

                x.SetDescription("Quartz日志记录服务");
                x.SetDisplayName("Quartz");
                x.SetServiceName("QuartzLog");

                x.EnablePauseAndContinue();
            });
        }
    }
Program

  至此,基本的所有配置就这样完成了,只要运行,就可以看到对应的服务的信息了。

  

  日志信息也记录在对应的(前面说设计的文档中)按照相面的代码选定的地址是根目录文件,如图所示:

windows服务

  制作windows服务,非常简单,只要调出cmd命令行,cd到指定文件的目录,输入应用程序名+install就可以,卸载的话就输入uninstall就可以了。如图所示:

 

源代码地址:GitHub

链接:https://github.com/JaminHuang/QuartzLog.git

 

posted @ 2016-09-21 15:11  JaminHuang  阅读(4461)  评论(3编辑  收藏  举报