How can I find which Quartz job a thread is running in java?

筅森魡賤 提交于 2020-01-05 11:40:13

问题


I am using a discriminator for logging in different file. Based on the thread name. It usually give good result, except for the quartz job that are all logger in file with name like :

org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1.log

I would like to have a file that is the name of the quartz job (on something base on it) to be able to quickly find which file contains the logs for a job. Is there a way ask quartz if the current thread is associated with a job?

Thanks


回答1:


Finally, I resolve it by manually indicating with slf4j MDC

at the beginning of the task, I do

try {
    MDC.put(MDC_KEY, getTaskName());

and at the end

    }
    finally {
        MDC.remove(MDC_KEY);
    }

So I just need to check the key in MDC to know if I am inside a task.




回答2:


Your approach implies you have to change code for all job classes (or inherit from base job class). However, there is alternative approach which is compatible with jobs whose code is not available for changing.

You can create job listener which changes thread name during execution (as at my example below) or sets MDC (as at your example) and register it via Scheduler.addJobListener() or configure via 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";
    }

}



回答3:


Alexander Pavlov's answer works for me (although I tweaked it to make it into a Groovy file). What was missing for me was the registration of the JobListener to the scheduler.

I registered a singleton instance of the Alexander's RenameThreadWhenJobRunning class as the bean 'renameThreadJobListener'. The 'quartzScheduler' bean already existed in my application context.

Since I'm using Grails, here is the block from my resources.groovy, which can be ported into an XML configuration or Annotation-based approach:

quartzSchedulerInitializer(QuartzSchedulerInitializer) { bean ->
    bean.dependsOn = ['quartzScheduler', 'renameThreadJobListener'] as String[]
    quartzScheduler = ref('quartzScheduler')
    renameThreadJobListener = ref('renameThreadJobListener')
}

renameThreadJobListener(RenameThreadWhenJobRunning)

Then I created the following Groovy class:

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)
    }
}

Outcome is my Worker thread names now look like "com.example.MyJob-Qz1"!



来源:https://stackoverflow.com/questions/6128155/how-can-i-find-which-quartz-job-a-thread-is-running-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!