需求:
最近公司做一个任务调度项目,其中一个小任务需要调度kettle,现有一需求,就是kettle产生的日志,不管正确与否,都要写入日志文件中
问题分析:
目前java调入job 代码如下(简化)
-
//设定kettle文件地址
-
JobMeta
jobMeta
=
new
JobMeta(kjbPath,
null);
-
-
Job
job
=
new
Job(
null, jobMeta);
-
// 配置作业参数
-
for (String key : parmap.keySet()) {
-
job.setVariable(key, parmap.get(key));
-
}
-
// 启动作业
-
job.start();
-
// 等待作业执行完毕
-
job.waitUntilFinished();
kettle日志是输出到console 控制台的,网上有日志入数据库表的办法,但不能解决本次需求;日志输出到文件解决思路有两个,第一个思路:截获控制台System.out标准输出流,重定向到文件; 第二个思路:寻找kettle API,监听kettle日志然后进行处理。
解决步骤
第一步:截获System.out 输出到文件 代码如下(简化)
-
//设定kettle文件地址
-
JobMeta
jobMeta
=
new
JobMeta(kjbPath,
null);
-
-
Job
job
=
new
Job(
null, jobMeta);
-
// 配置作业参数
-
for (String key : parmap.keySet()) {
-
job.setVariable(key, parmap.get(key));
-
}
-
-
-
//将标准输出重定向到文件
-
PrintStream
out
= System.out;
-
String
logFileName
=
'd:\\logfile.log'
//此处根据业务动态获取日志文件
-
System.setOut(
new
PrintStream(logFileName));
-
-
// 启动作业
-
job.start();
-
// 等待作业执行完毕
-
job.waitUntilFinished();
-
-
//恢复标准输出
-
System.setOut(out);
第一步完成后发现实际效果与预期不符,日志文件里记录了部分日志,不是全部日志,查看kettle源码后发现,kettle 执行任务时,里边的转换是多线程调用的,所以,在main中改变标准输出后,其他线程还是照样输出到控制台,只有main线程乖乖输出到文件。所以,采取第二步行动。
第二步:监听kettle日志,代码如下
-
//设定kettle文件地址
-
JobMeta jobMeta =
new
JobMeta(kjbPath,
null);
-
-
Job job =
new
Job(
null, jobMeta);
-
// 配置作业参数
-
for (
String key : parmap.
keySet()) {
-
job.
setVariable(key, parmap.
get(key));
-
}
-
-
-
//监听kettle日志
-
KettleLogStore.
getAppender().
addLoggingEventListener(
new
KettleLoggingEventListener() {
-
@Override
-
public
void
eventAdded(
KettleLoggingEvent logs) {
-
//logs为kettle运行时输出的日志。
-
System.
out.
println(logs.
getMessage());
-
}
-
});
-
-
// 启动作业
-
job.
start();
-
// 等待作业执行完毕
-
job.
waitUntilFinished();
至此,圆满完成老板需求。