我使用鉴别器登录不同的文件。基于线程名称。它通常会得到很好的结果,除了石英作业都是文件记录器,名称如下:
org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1.登录
我希望有一个文件,即石英作业的名称(基于它的东西),以便能够快速找到包含作业日志的文件。如果当前线程与作业相关,有没有办法询问quartz?
由于
答案 0 :(得分:1)
最后,我通过手动指示slf4j MDC来解决它
在任务开始时,我做
try {
MDC.put(MDC_KEY, getTaskName());
并在最后
}
finally {
MDC.remove(MDC_KEY);
}
所以我只需要检查MDC中的密钥以了解我是否在任务中。
答案 1 :(得分:1)
您的方法意味着您必须更改所有作业类的代码(或从基础作业类继承)。但是,有一种替代方法可以兼容其代码无法更改的作业。
您可以创建在执行期间更改线程名称的作业侦听器(如下面的示例所示)或设置MDC(如您的示例所示)并通过Scheduler.addJobListener()注册或通过Spring进行配置。
public class RenameThreadWhenJobRunning extends JobListenerSupport {
/**
* Must provide two groups - for name and for number
*/
private String parsingPattern = "^(.+)_Worker-(\\d+)$";
/**
* {0} - Original full name (e.q. XXX_Worker-NN)
* {1} - XXX - original thread name
* {2} - NN - original worker number
* {3} - Job key (e.g. JobGroup.JobName)
* {4} - Job group
* {5} - Job name
*/
private String format = "{5}-Qz{2}";
public void setParsingPattern(String parsingPattern) {
this.parsingPattern = parsingPattern;
}
public void setFormat(String format) {
this.format = format;
}
@Override
public String getName() {
return RenameThreadWhenJobRunning.class.getSimpleName();
}
@Override
public void jobToBeExecuted(JobExecutionContext context) {
final String originalThreadName = currentThread().getName();
final Matcher matcher = Pattern.compile(parsingPattern).matcher(originalThreadName);
if (matcher.matches()) {
final JobKey key = context.getJobDetail().getKey();
currentThread().setName(format(format,
originalThreadName,
matcher.group(1),
matcher.group(2),
key.toString(),
key.getGroup(),
key.getName()
));
context.put(getOriginalThreadNameContextParameter(), originalThreadName);
}
}
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
Object originalThreadName = context.get(getOriginalThreadNameContextParameter());
if (originalThreadName instanceof String) {
currentThread().setName((String)originalThreadName);
}
}
String getOriginalThreadNameContextParameter() {
return getName()+".originalThreadName";
}
}
答案 2 :(得分:1)
Alexander Pavlov的回答对我有用(虽然我将其调整为Groovy文件)。我缺少的是将JobListener注册到调度程序。
我将Alexander的RenameThreadWhenJobRunning类的单例实例注册为bean'renameThreadJobListener'。 'quartzScheduler'bean已经存在于我的应用程序环境中。
由于我使用的是Grails,这里是我的resources.groovy中的块,可以移植到XML配置或基于注释的方法中:
quartzSchedulerInitializer(QuartzSchedulerInitializer) { bean ->
bean.dependsOn = ['quartzScheduler', 'renameThreadJobListener'] as String[]
quartzScheduler = ref('quartzScheduler')
renameThreadJobListener = ref('renameThreadJobListener')
}
renameThreadJobListener(RenameThreadWhenJobRunning)
然后我创建了以下Groovy类:
import org.quartz.impl.matchers.EverythingMatcher
import org.springframework.beans.factory.InitializingBean
/**
* At application startup, register job listeners on the QuartzScheduler bean.
*/
class QuartzSchedulerInitializer implements InitializingBean {
def quartzScheduler
def renameThreadJobListener
@Override
void afterPropertiesSet() throws Exception {
def matcher = EverythingMatcher.allJobs()
quartzScheduler.listenerManager.addJobListener(renameThreadJobListener, matcher)
}
}
结果是我的工作线程名称现在看起来像“com.example.MyJob-Qz1”!