我有以下情况,
- 运行自托管 Quartz Scheduler 服务的 Windows 服务。
- 我有一个类库,其中包含许多“作业”类,这些类在由 Quartz 调度程序服务触发时将运行。
- 我在每个“作业”类中配置了 NLog,以便将该作业的活动记录到特定的文件夹和文件中。这给了我每个“作业”的所有日志记录的逻辑分离,我可以在运行时使用 xml 配置文件为每个单独的“作业”打开和关闭日志记录。
- 我已经配置 Quartz 调度器将启动信息记录到调度器日志中。
这一切都正常工作,没有任何问题。
我现在想做的是将 Quartz 调度程序的默认信息输出记录到另一个单独的 NLog 日志中,但我无法从 Quartz 使用的通用日志框架中弄清楚如何将它“管道”到 NLog 中。我的所有日志配置都是以编程方式完成的,因此我可以在运行时为每个单独的“作业”日志打开和关闭日志。
这是我的 NLog 配置的精简版本-
?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true">
<targets async="True" xsi:type="AsyncWrapper" queueLimit="20000">
<!--Scheduler Logging Section-->
<target name="sInfo" xsi:type="File"
fileName="${basedir}/logs/Scheduler/SchedulerInfolog.txt"
layout="[${date:format=dd-MM-yyy HH\:mm\:ss}] ${message}"
keepFileOpen="false"
archiveFileName="${basedir}/logs/archive/Scheduler/SchedulerInfoLog{#}.txt"
archiveEvery="Month"
archiveNumbering="Rolling"
maxArchiveFiles="10"
archiveAboveSize="10485760"/>
</targets>
<rules>
</rules>
</nlog>
我在调度程序类中声明了这个,
Private Shared Logger As NLog.Logger = LogManager.GetLogger("Scheduler")
Private xlc As LoggingConfiguration = LogManager.Configuration
Private sInfoRule As New LoggingRule
Private sTraceRule As New LoggingRule
Private sErrorRule As New LoggingRule
Private sfileTarget As New FileTarget
在 Quartz Scheduler 启动过程中,我调用了一个运行此代码的方法,
If infoEnabled Then
sInfoRule = New LoggingRule("Scheduler", LogLevel.Info, xlc.FindTargetByName("sInfo"))
xlc.LoggingRules.Add(sInfoRule)
sInfoRule.DisableLoggingForLevel(LogLevel.Fatal)
sInfoRule.DisableLoggingForLevel(LogLevel.Error)
sInfoRule.DisableLoggingForLevel(LogLevel.Warn)
End If
LogManager.Configuration = xlc
LogManager.ReconfigExistingLoggers()
我正在像这样配置 Quartz Scheduler,
Dim properties = New NameValueCollection()
properties("quartz.scheduler.instanceName") = "SRCTaskScheduler"
properties("quartz.threadPool.type") = "Quartz.Simpl.SimpleThreadPool, Quartz"
properties("quartz.threadPool.threadCount") = "20"
properties("quartz.threadPool.threadPriority")
= "Normal"
properties("quartz.plugin.jobInitializer.type") = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz"
properties("quartz.plugin.jobInitializer.fileNames") = path & "ScheduledTasks.xml"
properties("quartz.plugin.jobInitializer.failOnFileNotFound")
= "true"
properties("quartz.plugin.jobInitializer.scanInterval") = "60"
properties("quartz.plugin.triggerHistory.type") = "Quartz.Plugin.History.LoggingTriggerHistoryPlugin, Quartz"
properties("quartz.plugin.triggerHistory.triggerFiredMessage") = "Trigger
[{1}.{0}] fired job [{6}.{5}] scheduled at: [{2:dd/MM/yyyy HH:mm:ss]}, next scheduled at: [{3:dd/MM/yyyy HH:mm:ss}]"
properties("quartz.plugin.triggerHistory.triggerCompleteMessage") = "Trigger [{1}.{0}] completed firing job [{6}.{5}] with resulting trigger
instruction code: {9}. Next scheduled at: {3:dd/MM/yyyy HH:mm:ss}"
properties("quartz.plugin.triggerHistory.triggerMisfiredMessage") = "Trigger [{1}.{0}] misfired job [{6}.{5}]. Should have fired at: {3:dd/MM/yyyy HH:mm:ss}"
properties("quartz.plugin.jobHistory.type")
= "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz"
properties("quartz.plugin.jobHistory.jobToBeFiredMessage") = "Job [{1}.{0}] to be fired by trigger [{4}.{3}] at: [{5:dd/MM/yyyy HH:mm:ss}] with re-fire: {7}"
properties("quartz.plugin.jobHistory.jobSuccessMessage")
= "Job [{1}.{0}] execution complete, next Schedule at: [{6:dd/MM/yyyy HH:mm:ss}] and reports: [{8}] "
properties("quartz.plugin.jobHistory.jobFailedMessage") = "Job [{1}.{0}] execution failed with exception: [{8}]"
properties("quartz.plugin.jobHistory.jobWasVetoedMessage")
= "Job [{1}.{0}] was vetoed. It was to be fired by trigger [{4}.{3}] at: [{2:dd-MM-yyyy HH:mm:ss.SSS}]"
properties("quartz.plugin.ShutdownHook.type") = "Quartz.Plugin.Management.ShutdownHookPlugin, Quartz"
properties("quartz.plugin.ShutdownHook.CleanShutdown")
= "false"
Dim sf As ISchedulerFactory = New StdSchedulerFactory(properties)
_scheduler = sf.GetScheduler()
然后我可以像这样写入那个特定的日志文件,
Logger.Trace("[Scheduler configuration has completed.]")
Logger.Info("[Starting Scheduler System.]")
这可能看起来很奇怪,但所有这一切背后的原因是,一旦作业完成,我会在该特定作业日志中写入该作业的下一个触发时间,但是如果我在调度程序中更改触发时间,我没有任何记录更改,看起来该作业的触发器没有按时触发-理想情况下,我只想记录 Quartz Scheduler 输出,因为它在新计划中读取,但我想这是一个飞跃太远了。
我的计划 B,如果这不可能,则将作业配置为每 60 秒左右运行一次并记录当前的调度程序设置,这会起作用,但我就像一条有骨头的狗,想看看如果有可能让 A 计划发挥作用,我只是没有完成工作的知识和技能。