ジョブが失敗したり、予期せぬ動作をしたりした場合、根本原因を特定するには実行ログが必要です。Simple Log Service を SchedulerX 2.0 と連携させることで、分散ジョブログを含むジョブ実行ログを収集し、SchedulerX コンソールで直接表示できます。トリガーされたジョブからログ収集を開始するには、Log4j 2、Log4j、または Logback アペンダーを追加します。
前提条件
開始する前に、以下を確保してください。
SchedulerX で 名前空間 が作成されていること
SchedulerX で アプリケーショングループ が作成されていること
Simple Log Service がアクティブ化された SchedulerX 2.0 Professional Edition

Simple Log Service はログを最大 2 週間保持します。期限切れのログは自動的に削除されます。
仕組み
ロギングフレームワーク (Log4j 2、Log4j、または Logback) で SchedulerX ログアペンダーを構成します。
ジョブコードで、
schedulerxという名前のロガーを使用してログを書き込みます。ジョブが実行されると、SchedulerX はログを収集し、コンソールに表示します。
ログ収集方法の選択
SchedulerX は 2 つのログ収集方法をサポートしています。アペンダーを構成する前にいずれかを選択してください。
| 方法 | 収集対象 | 最適な用途 | トレードオフ |
|---|---|---|---|
| ジョブログのみ | schedulerx ロガーに書き込まれたログ | 特定のジョブのターゲットを絞ったトラブルシューティング | コードに専用ロガーが必要 |
| すべてのサービスログ | すべてのアプリケーションログ | アプリケーションの完全な可視性 | ジョブログとサービスログが混在し、クエリ効率が低下する |
SchedulerX エージェントの更新
SchedulerX エージェントを最新バージョンに更新します。最新のバージョン番号については、「リリースノート」をご参照ください。
pom.xml ファイルに次の依存関係を追加します (Spring Boot Starter の例):
<dependency>
<groupId>com.aliyun.schedulerx</groupId>
<artifactId>schedulerx2-spring-boot-starter</artifactId>
<version>${Latest version of the SchedulerX client}</version>
</dependency>ログアペンダーの構成
以下からロギングフレームワークを選択してください。各フレームワークは両方のログ収集方法をサポートしています。
Log4j 2
ジョブログのみを収集
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>ジョブクラスで、
schedulerxという名前のロガーを作成し、それを使用してログを書き込みます。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); } }
すべてのサービスログを収集
schedulerxLog アペンダーをルートロガーに追加します。これにより、すべてのアプリケーションログが SchedulerX によって収集されます。
このアプローチでは、サービスログとジョブログが混在するため、トラブルシューティングが困難になり、クエリ効率が低下する可能性があります。
<?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
ジョブログのみを収集
log4j.propertiesファイルにアペンダーと専用ロガーを追加します。log4j.rootLogger = INFO,console log4j.logger.schedulerx=schedulerxLog log4j.appender.schedulerxLog=com.alibaba.schedulerx.worker.log.appender.SchedulerxLog4jAppenderジョブクラスで、
schedulerxという名前のロガーを作成し、それを使用してログを書き込みます。Java コードは上記の Log4j 2 の例と同じです。LoggerFactory.getLogger("schedulerx")を使用してください。
すべてのサービスログを収集
schedulerxLog アペンダーを log4j.properties ファイルのルートロガーに追加します。
log4j.rootLogger = INFO,console,schedulerxLog
log4j.appender.schedulerxLog=com.alibaba.schedulerx.worker.log.appender.SchedulerxLog4jAppenderLogback
SchedulerxLogbackAppender クラスは、schedulerx2-worker.jar パッケージに含まれています。SchedulerX エージェントが最新バージョンに更新されていることを確認してください。最新バージョンについては、「リリースノート」をご参照ください。
ジョブログのみを収集
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>ジョブクラスで、
schedulerxという名前のロガーを作成し、それを使用してログを書き込みます。Java コードは上記の Log4j 2 の例と同じです。LoggerFactory.getLogger("schedulerx")を使用してください。
すべてのサービスログを収集
schedulerxLog アペンダーを 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>ジョブログの表示
MSE SchedulerX コンソールにログインします。
左側のナビゲーションウィンドウで、[タスク管理] をクリックします。
対象のジョブを探し、 を [操作] 列で選択します。
[タスクインスタンスレコード] パネルで、対象のジョブインスタンスを見つけ、[ログ] を [操作] 列でクリックします。
ログフィールド
各ログエントリには次のフィールドが含まれます。
| フィールド | 説明 |
|---|---|
ip | ログを生成したワーカーの IP アドレス |
executionId | 実行 ID、フォーマットは ${jobId}_${jobInstanceId}_${taskId} |
level | ログレベル (例: INFO または ERROR) |
log | ログコンテンツ |
throwable | 例外スタックトレース (エラー発生時のみ存在) |
time | ログが生成されたタイムスタンプ |
履歴ログのクエリ
SchedulerX は、各ジョブインスタンスについて最新の実行レコードのみ 60 件を保持します。古いレコードを検索するには、SchedulerX コンソールの左側のナビゲーションウィンドウで [ログクエリ] をクリックします。[ログクエリ] ページで、ジョブID、キーワード、または期間でフィルター処理します。
トラブルシューティングの例
サービス障害の診断
Simple Log Service を統合した後、SchedulerX はジョブログとサービスログの両方 (例外を含む) を収集します。次の例は、サービス呼び出しにおけるゼロ除算エラーを特定する方法を示しています。
サービスメソッドを呼び出し、
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); } }サービス用のクラスを作成します。
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; } }SchedulerX コンソールでジョブを構成します。たとえば、ジョブパラメーターを
1 0に設定してゼロ除算エラーをトリガーします。
タスクを一度実行してから、 [タスクインスタンスレコード] パネルを開いてログを表示します。 ログには、
TestServiceImplが「ゼロ除算」例外をスローしたため、タスクが失敗したと表示されます。
分散ジョブ障害の診断
SchedulerX 2.0 の分散ジョブは、バッチ処理のために複数のワーカーにサブタスクをディスパッチします。サブタスクが失敗した場合、ログを使用して、どの特定のタスクが失敗したか、およびその原因を特定します。
サブタスクをディスパッチし、
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); } }SchedulerX コンソールでジョブを構成し、トリガーします。

ジョブログの表示で説明されているように、ジョブログを開きます。
キーワード (例:
failedまたはerror) を検索して、失敗したサブタスクとその原因を特定します。