I have the following scenario,
- A Windows Service running a self hosted Quartz Scheduler service.
- I have a class library with a number of classes that are 'jobs' that will run when triggered by the Quartz Scheduler Service.
- I have NLog configured in each 'job' class such that it logs the activity of that job to a specific folder and file. This gives me a logical separation of all logging for each 'job' and I can turn logging on and off for each individual 'job' at run time using an xml configuration file.
- I have configured the Quartz Scheduler to log the start-up information into a scheduler log.
This is all working without any problems.
What I would like to do now is to log the default information output of the Quartz Scheduler into another separate NLog log but I cannot figure out how to 'pipe' this into NLog, from the common logging framework used by Quartz. All of my logging configuration is done programmatically, so that I can switch logging on and off for each individual 'job' log at run time.
Here is a cut down version of my NLog config-
?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>
I have this declared in the scheduler class,
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
In the Quartz Scheduler start up process I call a method that runs this code,
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()
I am configuring the Quartz Scheduler like this,
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()
I can then write to that particular log file like this,
Logger.Trace("[Scheduler configuration has completed.]")
Logger.Info("[Starting Scheduler System.]")
This may seem strange but the reason behind all of this is that once a job completes I write the next trigger time for that job in that particular job log, but if I change the trigger time in the scheduler, I have no record anywhere of that change, it just looks like the trigger for that job did not fire on time - I would ideally like to just log the Quartz Scheduler output as it reads in the new schedule, but I guess that is a leap too far.
My plan B, if this is not possible is to have a job configured to run every 60 seconds or so and to log the current scheduler settings, that would work, but I am like a dog with a bone on this and would like to see if it is possible to get Plan A to work, I just don't have the knowledge and skills to get the job done.