功能简介
在当前微服务和容器化越来越流行的情况下,机器数量太多、没有权限登录容器,成为了业务同学无法快速定位业务失败的痛点。可视化白屏日志工具,越来越成为了企业的刚需。
阿里巴巴分布式任务调度系统SchedulerX2.0的日志服务,可以让业务方不需要修改一行代码,只需要增加一个log4j/logback的配置,即可在控制台看到每次任务调度(包括分布式任务)的业务日志,方便排查问题。
使用限制
开通专业版
需要开通专业版,在应用管理里,高级配置下,改成专业版,开启日志服务,如下图
日志保存时间
当前日志最多保留2周,超过2周的日志会被清理
接入配置
升级schedulerx客户端版本
将schedulerx客户端版本升级到1.4.1.1以上版本,以springboot starter为例
配置Log Appender采集日志服务
Log4j2 Appender
log4j2.xml增加一个名为SchedulerxLog4j2Appender的appender
<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; public class HelloWorldJob3 extends JavaProcessor { private static final Logger LOGGER = LogManager.getLogger("schedulerx"); 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如下
- 新建任务代码和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; public class HelloWorldJob extends JavaProcessor { //使用schedulerx收集日志 private static final Logger LOGGER = LogManager.getLogger("schedulerx"); private TestService testService; 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; "testService") (public class TestServiceImpl implements TestService { //使用schedulerx收集日志 private static final Logger LOGGER = LogManager.getLogger("schedulerx"); 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; } }
- 控制台配置任务如下,根据代码来看,1除以0肯定会抛异常
- 运行一次后,通过任务实例列表,查看日志
如上图所以,我们可以看到失败的原因是在TestServiceImpl抛出了除0的异常
查询分布式任务失败原因
SchedulerX2.0的分布式任务用来跑批,某个批次跑批失败了,想查询具体是哪个子任务失败了,demo如下
- 新建任务代码如下
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"); 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); } }
- 配置任务如下
- 运行一次后,查看日志
- 搜索关键字,快速定位失败的机器和原因
根据关键字查询历史日志
任务实例历史记录,只保留最近60条,如果想排查历史上任务失败的原因,可以通过左边栏日志查询。支持根据任务id和关键字搜索,支持查询时间区间搜索