功能简介
在当前微服务和容器化越来越流行的情况下,机器数量太多、没有权限登录容器,成为了业务同学无法快速定位业务失败的痛点。可视化白屏日志工具,越来越成为了企业的刚需。
阿里巴巴分布式任务调度系统SchedulerX2.0的日志服务,可以让业务方不需要修改一行代码,只需要增加一个log4j/logback的配置,即可在控制台看到每次任务调度(包括分布式任务)的业务日志,方便排查问题。
使用限制
开通专业版
需要开通专业版,在应用管理里,高级配置下,改成专业版,开启日志服务,如下图
日志保存时间
当前日志最多保留2周,超过2周的日志会被清理
接入配置
升级schedulerx客户端版本
将schedulerx客户端版本升级到1.4.1.1以上版本,以springboot starter为例
<dependency>
<groupId>com.aliyun.schedulerx</groupId>
<artifactId>schedulerx2-spring-boot-starter</artifactId>
<version>1.4.1.1</version>
</dependency>
配置Log Appender采集日志服务
Log4j2 Appender
log4j2.xml增加一个名为SchedulerxLog4j2Appender的appender
<?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>
业务代码使用原生log4j2打印日志
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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
@Component
public class HelloWorldJob3 extends JavaProcessor {
private static final Logger LOGGER = LogManager.getLogger("schedulerx");
@Override
public ProcessResult process(JobContext context) throws Exception {
LOGGER.info("hello HelloWorldJob3");
return new ProcessResult(true);
}
}
Log4j Appender
log4j.properties增加一个Appender
log4j.appender.schedulerxLog=com.alibaba.schedulerx.worker.log.appender.SchedulerxLog4jAppender
Logback Appender
logback.xml增加一个Appender
<appender name="schedulerxLog" class="com.alibaba.schedulerx.worker.log.appender.SchedulerxLogbackAppender">
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
<timeZone>UTC</timeZone>
</appender>
日志输出
日志输出样例如下:
- ip: 打印该日志的执行机器
- executionId: 本次任务实例的执行id,格式为${jobId}_${jobInstanceId}_${taskId}
- level: 日志级别
- log:日志的信息
- throwable: 如果抛异常,会打印该字段
应用场景及演示
查询业务失败的原因
SchedulerX2.0的日志服务,可以搜集任务的执行日志和异常,包括service的日志都可以收集,demo如下
1. 新建任务代码和service业务代码,配置使用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 {
//使用schedulerx收集日志
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 {
//使用schedulerx收集日志
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;
}
}
2. 控制台配置任务如下,根据代码来看,1除以0肯定会抛异常
3. 运行一次后,通过任务实例列表,查看日志
如上图所以,我们可以看到失败的原因是在TestServiceImpl抛出了除0的异常
查询分布式任务失败原因
SchedulerX2.0的分布式任务用来跑批,某个批次跑批失败了,想查询具体是哪个子任务失败了,demo如下
1. 新建任务代码如下
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);
}
}
2. 配置任务如下
3. 运行一次后,查看日志
4. 搜索关键字,快速定位失败的机器和原因
根据关键字查询历史日志
任务实例历史记录,只保留最近60条,如果想排查历史上任务失败的原因,可以通过左边栏日志查询。支持根据任务id和关键字搜索,支持查询时间区间搜索
原文链接:阿里巴巴任务调度SchedulerX支持日志服务-阿里云开发者社区