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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM