Lorsque des tâches échouent ou se comportent de manière inattendue, les journaux d'exécution sont indispensables pour identifier la cause première. En intégrant Simple Log Service à SchedulerX 2.0, vous pouvez collecter les journaux d'exécution des tâches, y compris ceux des tâches distribuées, et les consulter directement dans la console SchedulerX. Ajoutez un appender Log4j 2, Log4j ou Logback pour commencer à collecter les journaux des tâches déclenchées.
Prérequis
Avant de commencer, assurez-vous d'avoir :
Un namespace créé dans SchedulerX
Un application group créé dans SchedulerX
SchedulerX 2.0 Édition Professionnelle avec Simple Log Service activé

Simple Log Service conserve les journaux pendant deux semaines maximum. Les journaux expirés sont automatiquement supprimés.
Fonctionnement
Configurez un appender SchedulerX dans votre framework de journalisation (Log4j 2, Log4j ou Logback).
Dans le code de votre tâche, écrivez les journaux en utilisant un logger nommé
schedulerx.Lorsqu'une tâche s'exécute, SchedulerX collecte les journaux et les affiche dans la console.
Choisir une méthode de collecte des journaux
SchedulerX prend en charge deux méthodes de collecte des journaux. Choisissez-en une avant de configurer l'appender.
| Méthode | Collecte | Idéal pour | Compromis |
|---|---|---|---|
| Journaux de tâches uniquement | Journaux écrits dans le logger schedulerx |
Dépannage ciblé de tâches spécifiques | Nécessite un logger dédié dans votre code |
| Tous les journaux de service | Tous les journaux de l'application | Visibilité complète sur l'application | Mélange les journaux de tâches et de service, réduisant l'efficacité des requêtes |
Mettre à jour l'agent SchedulerX
Mettez à jour l'agent SchedulerX vers la dernière version. Pour connaître le numéro de la dernière version, consultez les Notes de version.
Ajoutez la dépendance suivante à votre fichier pom.xml (exemple Spring Boot Starter) :
<dependency>
<groupId>com.aliyun.schedulerx</groupId>
<artifactId>schedulerx2-spring-boot-starter</artifactId>
<version>${Latest version of the SchedulerX client}</version>
</dependency>
Configurer un appender de journalisation
Sélectionnez votre framework de journalisation ci-dessous. Chaque framework prend en charge les deux méthodes de collecte des journaux.
Log4j 2
Collecter uniquement les journaux de tâches
-
Ajoutez un appender et un logger dédié à votre fichier de configuration Log4j 2 :
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="off"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n" /> </Console> <SchedulerxLog4j2Appender name="schedulerxLog" timeFormat="yyyy-MM-dd'T'HH:mmZ" timeZone="UTC" ignoreExceptions="true"> <PatternLayout pattern="%d %-5level [%thread] %logger{0}: %msg"/> </SchedulerxLog4j2Appender> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console" /> </Root> <Logger name="schedulerx" level="info" additivity="false"> <AppenderRef ref="schedulerxLog" /> </Logger> </Loggers> </Configuration> -
Dans votre classe de tâche, créez un logger nommé
schedulerxet utilisez-le pour écrire les journaux :package com.hxm.test.processor; import com.alibaba.schedulerx.worker.domain.JobContext; import com.alibaba.schedulerx.worker.processor.JavaProcessor; import com.alibaba.schedulerx.worker.processor.ProcessResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class HelloWorldJob3 extends JavaProcessor { // Use "schedulerx" as the logger name private static final Logger logger = LoggerFactory.getLogger("schedulerx"); @Override public ProcessResult process(JobContext context) throws Exception { logger.info("hello HelloWorldJob3"); return new ProcessResult(true); } }
Collecter tous les journaux de service
Ajoutez l'appender schedulerxLog au logger root. Tous les journaux de l'application sont alors collectés par SchedulerX.
Cette approche mélange les journaux de service et les journaux de tâches, ce qui peut rendre le dépannage plus difficile et réduire l'efficacité des requêtes.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="off">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n" />
</Console>
<SchedulerxLog4j2Appender name="schedulerxLog"
timeFormat="yyyy-MM-dd'T'HH:mmZ"
timeZone="UTC"
ignoreExceptions="true">
<PatternLayout pattern="%d %-5level [%thread] %logger{0}: %msg"/>
</SchedulerxLog4j2Appender>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="schedulerxLog" />
</Root>
</Loggers>
</Configuration>
Log4j
Collecter uniquement les journaux de tâches
-
Ajoutez un appender et un logger dédié à votre fichier
log4j.properties:log4j.rootLogger = INFO,console log4j.logger.schedulerx=schedulerxLog log4j.appender.schedulerxLog=com.alibaba.schedulerx.worker.log.appender.SchedulerxLog4jAppender Dans votre classe de tâche, créez un logger nommé
schedulerxet utilisez-le pour écrire les journaux. Le code Java est identique à l'exemple Log4j 2 ci-dessus : utilisezLoggerFactory.getLogger("schedulerx").
Collecter tous les journaux de service
Ajoutez l'appender schedulerxLog au logger root dans log4j.properties :
log4j.rootLogger = INFO,console,schedulerxLog
log4j.appender.schedulerxLog=com.alibaba.schedulerx.worker.log.appender.SchedulerxLog4jAppender
Logback
La classe SchedulerxLogbackAppender se trouve dans le package schedulerx2-worker.jar. Assurez-vous que l'agent SchedulerX est mis à jour vers la dernière version. Pour obtenir la dernière version, consultez les Notes de version.
Collecter uniquement les journaux de tâches
-
Ajoutez un appender et un logger dédié à votre fichier
logback.xml:<appender name="schedulerxLog" class="com.alibaba.schedulerx.worker.log.appender.SchedulerxLogbackAppender"> <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat> <timeZone>UTC</timeZone> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> <logger name="schedulerx" level="INFO"> <appender-ref ref="schedulerxLog"/> </logger> Dans votre classe de tâche, créez un logger nommé
schedulerxet utilisez-le pour écrire les journaux. Le code Java est identique à l'exemple Log4j 2 ci-dessus : utilisezLoggerFactory.getLogger("schedulerx").
Collecter tous les journaux de service
Ajoutez l'appender schedulerxLog au logger root dans logback.xml :
<appender name="schedulerxLog" class="com.alibaba.schedulerx.worker.log.appender.SchedulerxLogbackAppender">
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
<timeZone>UTC</timeZone>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="schedulerxLog"/>
</root>
Consulter les journaux des tâches
Connectez-vous à la console MSE SchedulerX.
Dans le volet de navigation de gauche, cliquez sur Task Management.
Recherchez la tâche cible et choisissez dans la colonne Operation.
-
Dans le panneau Task instance records, recherchez l'instance de tâche cible et cliquez sur Log dans la colonne Operation.
Champs de journalisation
Chaque entrée de journal contient les champs suivants :
| Champ | Description |
|---|---|
ip |
Adresse IP du worker qui a généré le journal |
executionId |
ID d'exécution au format ${jobId}_${jobInstanceId}_${taskId} |
level |
Niveau de journalisation (par exemple, INFO ou ERROR) |
log |
Contenu du journal |
throwable |
Trace de la pile d'exceptions (présente uniquement en cas d'erreur) |
time |
Horodatage de la génération du journal |
Interroger les journaux historiques
SchedulerX ne conserve que les 60 derniers enregistrements d'exécution par instance de tâche. Pour rechercher des enregistrements plus anciens, cliquez sur Log Query dans le volet de navigation de gauche de la console SchedulerX. Sur la page Log Query, filtrez par ID de tâche, mot-clé ou plage de temps.
Exemples de dépannage
Diagnostiquer une défaillance de service
Après l'intégration de Simple Log Service, SchedulerX collecte à la fois les journaux de tâches et les journaux de service, y compris les exceptions. L'exemple suivant montre comment identifier une erreur de division par zéro dans un appel de service.
-
Créez une tâche qui appelle une méthode de service et consigne les journaux avec le logger
schedulerx:package com.hxm.test.processor; import com.alibaba.schedulerx.test.service.TestService; import com.alibaba.schedulerx.worker.domain.JobContext; import com.alibaba.schedulerx.worker.processor.JavaProcessor; import com.alibaba.schedulerx.worker.processor.ProcessResult; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class HelloWorldJob extends JavaProcessor { // Use the schedulerx logger to collect logs private static final Logger LOGGER = LogManager.getLogger("schedulerx"); @Autowired private TestService testService; @Override public ProcessResult process(JobContext context) throws Exception { String parameters = context.getJobParameters(); String tokens[] = parameters.split(" "); int a = Integer.valueOf(tokens[0]); int b = Integer.valueOf(tokens[1]); int c = testService.doDivision(a, b); LOGGER.info("testService.doDivision finished, a={}, b={}, c={}", a, b, c); if (c < 0) { return new ProcessResult(false, "result=" + c); } return new ProcessResult(true); } } -
Créez la classe de service :
package com.hxm.test.service; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Service; @Service("testService") public class TestServiceImpl implements TestService { // Use the schedulerx logger to collect logs private static final Logger LOGGER = LogManager.getLogger("schedulerx"); @Override public int doDivision(int a, int b) { try { LOGGER.info("start to do division c = " + a + "/" + b); int c = a/b; LOGGER.info("c=" + c); return c; } catch (Exception e) { LOGGER.error("", e); } return -1; } } -
Configurez la tâche dans la console SchedulerX. Par exemple, définissez les paramètres de la tâche sur
1 0pour déclencher une erreur de division par zéro.
-
Exécutez la tâche une fois, puis ouvrez le panneau Task instance records et consultez les journaux. Le journal indique que la tâche a échoué car
TestServiceImpla levé une exception « by zero ».
Diagnostiquer l'échec d'une tâche distribuée
Les tâches distribuées dans SchedulerX 2.0 distribuent des sous-tâches sur plusieurs workers pour un traitement par lots. Si une sous-tâche échoue, utilisez les journaux pour identifier quelle tâche spécifique a échoué et pourquoi.
-
Créez une tâche distribuée qui distribue des sous-tâches et consigne les journaux avec le logger
schedulerx:package com.hxm.test.processor; import java.util.ArrayList; import java.util.List; import com.alibaba.schedulerx.worker.domain.JobContext; import com.alibaba.schedulerx.worker.processor.MapJobProcessor; import com.alibaba.schedulerx.worker.processor.ProcessResult; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class TestMapJobProcessor extends MapJobProcessor { private static final Logger LOGGER = LogManager.getLogger("schedulerx"); @Override public ProcessResult process(JobContext context) throws Exception { String taskName = context.getTaskName(); String parameter = context.getJobParameters(); int dispatchNum = Integer.valueOf(parameter); if (isRootTask(context)) { LOGGER.info("start root task"); List<String> msgList = new ArrayList<>(); for (int i = 0; i <= dispatchNum; i++) { msgList.add("msg_" + i); } return map(msgList, "Level1Dispatch"); } else if (taskName.equals("Level1Dispatch")) { String task = (String)context.getTask(); if (task.equals("msg_23")) { LOGGER.error("msg={}, failed", task); return new ProcessResult(false); } else { LOGGER.info("msg={}, success", task); } return new ProcessResult(true); } return new ProcessResult(false); } } -
Configurez la tâche dans la console SchedulerX et déclenchez-la.

Ouvrez les journaux de la tâche comme décrit dans la section Consulter les journaux des tâches.
-
Recherchez des mots-clés (tels que
failedouerror) pour localiser la sous-tâche ayant échoué et sa cause première.