Как я могу найти, какое Quartz-задание работает в Java? - PullRequest
1 голос
/ 25 мая 2011

Я использую дискриминатор для входа в другой файл.На основании имени потока.Обычно это дает хороший результат, за исключением кварцевых заданий, которые все записываются в файл с именем вроде:

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

Я бынапример, иметь файл с именем кварцевого задания (на его основе), чтобы можно было быстро найти, какой файл содержит журналы задания.Есть ли способ спросить у кварца, связан ли текущий поток с заданием?

Спасибо

Ответы [ 3 ]

1 голос
/ 03 апреля 2015

Ваш подход подразумевает, что вы должны изменить код для всех классов заданий (или наследовать от базового класса заданий). Однако существует альтернативный подход, который совместим с заданиями, код которых недоступен для изменения.

Вы можете создать прослушиватель задания, который меняет имя потока во время выполнения (как в моем примере ниже) или устанавливает 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";
    }

}
1 голос
/ 20 сентября 2016

Ответ Александра Павлова работает для меня (хотя я настроил его, чтобы превратить его в файл Groovy). Чего мне не хватало, так это регистрации JobListener в планировщике.

Я зарегистрировал единичный экземпляр класса Александра RenameThreadWhenJobRunning как bean-компонент 'renameThreadJobListener'. Bean-компонент quartzScheduler уже существовал в контексте моего приложения.

Поскольку я использую 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»!

1 голос
/ 06 июня 2011

Наконец, я разрешаю это вручную, указав в slf4j MDC

в начале задания я делаю

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

и в конце

    }
    finally {
        MDC.remove(MDC_KEY);
    }

Так что мне просто нужно проверить ключ в MDC, чтобы узнать, нахожусь ли я внутри задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...