title: Redirecting Quartz Net Scheduler Logging Into Nlog
body: <p>I have the following scenario,</p>
  
  <ul>
  <li>A Windows Service running a self hosted Quartz Scheduler service.</li>
  <li>I have a class library with a number of classes that are 'jobs' that will run when triggered by the Quartz Scheduler Service.</li>
  <li>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.</li>
  <li>I have configured the Quartz Scheduler to log the start-up information into a scheduler log.</li>
  </ul>
  
  <p>This is all working without any problems.</p>
  
  <p>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.</p>
  
  <p>Here is a cut down version of my NLog config-</p>
  
  <pre class="lang-xml prettyprint-override"><code>?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        autoReload="true"&gt;
    &lt;targets  async="True" xsi:type="AsyncWrapper" queueLimit="20000"&gt;
  &lt;!--Scheduler Logging Section--&gt;
      &lt;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"/&gt;
      &lt;/targets&gt;
      &lt;rules&gt;
      &lt;/rules&gt;
    &lt;/nlog&gt;
  </code></pre>
  
  <p>I have this declared in the scheduler class,</p>
  
  <pre><code>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
  </code></pre>
  
  <p>In the Quartz Scheduler start up process I call a method that runs this code,</p>
  
  <pre><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()
  </code></pre>
  
  <p>I am configuring the Quartz Scheduler like this,</p>
  
  <pre><code>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 &amp; "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()
  </code></pre>
  
  <p>I can then write to that particular log file like this,</p>
  
  <pre><code>Logger.Trace("[Scheduler configuration has completed.]")
  Logger.Info("[Starting Scheduler System.]")
  </code></pre>
  
  <p>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.</p>
  
  <p>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.</p>