Quartz.net 通过 log4net 的调度程序日志未进入正确的记录器文件
Quartz.net scheduler logs via log4net not coming in correct logger file
我正在开发一项 windows 服务,该服务有五个不同的作业,同时有一个 运行 作业,因为有一个调度程序使用 Quarts.Net 和 TopShelf 库在特定时间间隔安排这些作业。问题在于每个作业的日志记录,log4Net 库用于将每个作业记录到一个单独的文件中,并且 app.config 文件中的每个记录器都有正确的配置,但仍然在 运行 时间记录不是在正确的日志文件上完成,当所有作业同时 运行ning 时。以下是这些作业的代码示例:
factory = new StdSchedulerFactory();
scheduler = factory.GetScheduler();
scheduler.JobFactory = new LoggerEnabledJobFactory() { AppLogger = LogManager.GetLogger("Job1") }; // in case of another job it will be "Job2"
scheduler.ListenerManager.AddJobListener(new JobListener() { Name = "Job1Listener" });
IJobDetail jobDetails = JobBuilder.Create<ServiceJob1>().SetJobData(map).Build();
ITrigger trigger = TriggerBuilder.Create()
.WithSimpleSchedule(x =>
x.WithIntervalInSeconds(interval)
.RepeatForever().WithMisfireHandlingInstructionIgnoreMisfires()
)
.StartNow()
.WithIdentity("Job1TriggerGroup")
.Build();
scheduler.ScheduleJob(jobDetails, trigger);
scheduler.Start();
下面是自定义 JobFactory 代码:(代码中已有)
public interface IloggerEnabledJob : IJob
{
ILog AppLogger{ get; set; }
}
public class LoggerEnabledJobFactory : IJobFactory
{
public ILog AppLogger { get; set; }
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var job = Activator.CreateInstance(bundle.JobDetail.JobType);
((IloggerEnabledJob)job).AppLogger = AppLogger ;
return (IJob)job;
}
public void ReturnJob(IJob job)
{
}
}
下面是"ServiceJob1"class代码:
public class ServiceJob1 : IloggerEnabledJob
{
public ILog AppLogger { get; set; }
public void Execute(IJobExecutionContext context)
{
try
{
// do something
}
catch (Exception ex)
{
Logger.Log(AppLogger, Logger.LogType.Error, "Exception : " + ex);
}
}
}
App.config :
<log4net>
<root>
<level value="INFO"/>
<appender-ref ref="Job1FileAppender"/>
<appender-ref ref="Job2FileAppender"/>
</root>
<appender name="Job1FileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString">
<conversionPattern value="\Logs\Job1\Job1_Log_%date{yyyy.MM.dd.HH.mm.ss}-%processid.txt"/>
</file>
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="Job1"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="25MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<appender name="Job2FileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString">
<conversionPattern value="\Logs\Job2\Job2_Log_%date{yyyy.MM.dd.HH.mm.ss}-%processid.txt"/>
</file>
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="Job2"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="25MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<logger name="Job1" additivity="true">
<level value="ALL" />
<appender-ref ref="Job1FileAppender" />
</logger>
<logger name="Job2" additivity="true">
<level value="ALL" />
<appender-ref ref="Job2FileAppender" />
</logger>
</log4net>
我需要将 Job1 和 Job2 的日志记录到它们各自的日志文件中,即使所有五个作业同时 运行ning 也是如此。任何 help/suggestions 将不胜感激!
从您的代码看来,您可能每次都从 JobFactory
传递相同的 LogManager.GetLogger("Job1")
。
我通常会自定义 JobFactory
在内部使用 IoC 容器。如果我不得不将不同的记录器传递给不同的作业,我只需在 IoC 容器设置中配置它们并让容器为我解决。
如果 IoC 容器不是您创建作业的方式,那么您可以在 NewJob
方法中注入记录器,就像这样
public class CustomJobFactory : IJobFactory
{
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var newJob = // Create job somehow
((ILoggerEnabledJob)newJob).AppLogger = LogManager.GetLogger(bundle.JobDetail.JobType.Name);
return newJob;
}
public void ReturnJob(IJob job)
{
// ...
}
}
要考虑的另一个选择是在每个作业中只使用静态记录器。
我正在开发一项 windows 服务,该服务有五个不同的作业,同时有一个 运行 作业,因为有一个调度程序使用 Quarts.Net 和 TopShelf 库在特定时间间隔安排这些作业。问题在于每个作业的日志记录,log4Net 库用于将每个作业记录到一个单独的文件中,并且 app.config 文件中的每个记录器都有正确的配置,但仍然在 运行 时间记录不是在正确的日志文件上完成,当所有作业同时 运行ning 时。以下是这些作业的代码示例:
factory = new StdSchedulerFactory();
scheduler = factory.GetScheduler();
scheduler.JobFactory = new LoggerEnabledJobFactory() { AppLogger = LogManager.GetLogger("Job1") }; // in case of another job it will be "Job2"
scheduler.ListenerManager.AddJobListener(new JobListener() { Name = "Job1Listener" });
IJobDetail jobDetails = JobBuilder.Create<ServiceJob1>().SetJobData(map).Build();
ITrigger trigger = TriggerBuilder.Create()
.WithSimpleSchedule(x =>
x.WithIntervalInSeconds(interval)
.RepeatForever().WithMisfireHandlingInstructionIgnoreMisfires()
)
.StartNow()
.WithIdentity("Job1TriggerGroup")
.Build();
scheduler.ScheduleJob(jobDetails, trigger);
scheduler.Start();
下面是自定义 JobFactory 代码:(代码中已有)
public interface IloggerEnabledJob : IJob
{
ILog AppLogger{ get; set; }
}
public class LoggerEnabledJobFactory : IJobFactory
{
public ILog AppLogger { get; set; }
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var job = Activator.CreateInstance(bundle.JobDetail.JobType);
((IloggerEnabledJob)job).AppLogger = AppLogger ;
return (IJob)job;
}
public void ReturnJob(IJob job)
{
}
}
下面是"ServiceJob1"class代码:
public class ServiceJob1 : IloggerEnabledJob
{
public ILog AppLogger { get; set; }
public void Execute(IJobExecutionContext context)
{
try
{
// do something
}
catch (Exception ex)
{
Logger.Log(AppLogger, Logger.LogType.Error, "Exception : " + ex);
}
}
}
App.config :
<log4net>
<root>
<level value="INFO"/>
<appender-ref ref="Job1FileAppender"/>
<appender-ref ref="Job2FileAppender"/>
</root>
<appender name="Job1FileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString">
<conversionPattern value="\Logs\Job1\Job1_Log_%date{yyyy.MM.dd.HH.mm.ss}-%processid.txt"/>
</file>
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="Job1"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="25MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<appender name="Job2FileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString">
<conversionPattern value="\Logs\Job2\Job2_Log_%date{yyyy.MM.dd.HH.mm.ss}-%processid.txt"/>
</file>
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="Job2"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="25MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<logger name="Job1" additivity="true">
<level value="ALL" />
<appender-ref ref="Job1FileAppender" />
</logger>
<logger name="Job2" additivity="true">
<level value="ALL" />
<appender-ref ref="Job2FileAppender" />
</logger>
</log4net>
我需要将 Job1 和 Job2 的日志记录到它们各自的日志文件中,即使所有五个作业同时 运行ning 也是如此。任何 help/suggestions 将不胜感激!
从您的代码看来,您可能每次都从 JobFactory
传递相同的 LogManager.GetLogger("Job1")
。
我通常会自定义 JobFactory
在内部使用 IoC 容器。如果我不得不将不同的记录器传递给不同的作业,我只需在 IoC 容器设置中配置它们并让容器为我解决。
如果 IoC 容器不是您创建作业的方式,那么您可以在 NewJob
方法中注入记录器,就像这样
public class CustomJobFactory : IJobFactory
{
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var newJob = // Create job somehow
((ILoggerEnabledJob)newJob).AppLogger = LogManager.GetLogger(bundle.JobDetail.JobType.Name);
return newJob;
}
public void ReturnJob(IJob job)
{
// ...
}
}
要考虑的另一个选择是在每个作业中只使用静态记录器。