Python 解析 DataX 日志并持久化至数据库的实现方案
本文介绍如何利用 Python 脚本解析 DataX 作业生成的日志文件,提取任务启动与结束时间、耗时、流量及记录数等关键指标,并将结构化数据写入 MySQL 数据库。通过自定义 Shell 脚本在日志中添加标记,结合 Python 的正则表达式与 SQLAlchemy 库,实现 ETL 任务执行结果的自动化监控与持久化存储,适用于定期同步任务的运维管理。
配置 DataX 定时执行脚本
首先配置 DataX 作业的执行环境,创建相应的执行脚本,并通过 crontab 设置定时任务,例如每天凌晨 1 点自动执行该脚本。
在生成的日志文件中,特意添加了 job_start 和 job_finish 两行记录,其主要目的是便于后续快速识别和定位具体是哪张数据表的同步任务。
#!/bin/bash
source /etc/profile
user1="root"
pass1="pwd"
user2="root"
pass2="pwd"
job_path="/opt/datax/job/"
jobfile=(
job_table_a.json
job_table_b.json
)
for filename in ${jobfile[@]}
do
echo "job_start: "`date "+%Y-%m-%d %H:%M:%S"`" ${filename}"
python /opt/datax/bin/datax.py -p "-Duser1=${user1} -Dpass1=${pass1} -Duser2=${user2} -Dpass2=${pass2}" ${job_path}${filename}
echo "job_finish: "`date "+%Y-%m-%d %H:%M:%S"`" ${filename}"
done
# 0 1 * * * /opt/datax/job/dc_to_ods_incr.sh >> /opt/datax/job/log/dc_to_ods_incr_$(date +\%Y\%m\%d_\%H\%M\%S).log 2>&1
# egrep '任务|速度|总数|job_start|job_finish' /opt/datax/job/log/
解析 DataX 日志文件
DataX 执行完毕后,会生成包含详细运行信息的日志文件,内容涵盖任务起止时间、耗时、流量及读写记录数等。
job_start: 2018-08-08 01:13:28 job_table_a.json
任务启动时刻 : 2018-08-08 01:13:28
任务结束时刻 : 2018-08-08 01:14:49
任务总计耗时 : 81s
任务平均流量 : 192.82KB/s
记录写入速度 : 1998rec/s
读出记录总数 : 159916
读写失败总数 : 0
job_finish: 2018-08-08 01:14:49 job_table_a.json
job_start: 2018-08-08 01:14:49 job_table_b.json
任务启动时刻 : 2018-08-08 01:14:50
任务结束时刻 : 2018-08-08 01:15:01
任务总计耗时 : 11s
任务平均流量 : 0B/s
记录写入速度 : 0rec/s
读出记录总数 : 0
读写失败总数 : 0
job_finish: 2018-08-08 01:15:01 job_table_b.json
创建数据库存储表结构
为了将上述日志信息结构化并存储,需要在数据库中预先创建对应的数据表,用于保存解析后的各项指标。
CREATE TABLE `datax_job_result` (
`log_file` varchar(200) DEFAULT NULL,
`job_file` varchar(200) DEFAULT NULL,
`start_time` datetime DEFAULT NULL,
`end_time` datetime DEFAULT NULL,
`seconds` int(11) DEFAULT NULL,
`traffic` varchar(50) DEFAULT NULL,
`write_speed` varchar(50) DEFAULT NULL,
`read_record` int(11) DEFAULT NULL,
`failed_record` int(11) DEFAULT NULL,
`job_start` varchar(200) DEFAULT NULL,
`job_finish` varchar(200) DEFAULT NULL,
`insert_time` datetime DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Python 脚本实现日志解析与入库
编写并定时运行 Python 脚本,由于 DataX 作业通常在凌晨 1 点执行,该脚本旨在获取过去一天内最新的日志文件。脚本逻辑中设定时间窗口为 82800 秒(即 23 小时),确保无论何时运行脚本,都能捕获到当天生成的最新日志。此脚本同样配置为定时执行,并在判断 DataX 作业完成后触发。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 0 5 * * * source /etc/profile && /usr/bin/python2.7 /opt/datax/job/save_log_to_db.py > /dev/null 2>&1
import re
import os
import sqlalchemy
import pandas as pd
import datetime as dt
def save_to_db(df):
engine = sqlalchemy.create_engine("mysql+pymysql://root:pwd@localhost:3306/test", encoding="utf-8")
df.to_sql("datax_job_result", engine, index=False, if_exists='append')
def get_the_latest_file(path):
t0 = dt.datetime.utcfromtimestamp(0)
d2 = (dt.datetime.now() - t0).total_seconds()
d1 = d2 - 82800
for (dirpath, dirnames, filenames) in os.walk(path):
for filename in sorted(filenames, reverse = True):
if filename.endswith(".log"):
f = os.path.join(dirpath,filename)
ctime = os.stat(f)[-1]
if ctime>=d1 and ctime <=d2:
return f
def get_job_result_from_logfile(path):
result = pd.DataFrame(columns=['log_file','job_file','start_time','end_time','seconds','traffic','write_speed','read_record','failed_record','job_start','job_finish'])
log_file = get_the_latest_file(path)
index = 0
content = open(log_file, "r")
for line in content:
result.loc[index, 'log_file'] = log_file
if re.compile(r'job_start').match(line):
result.loc[index, 'job_file'] = line.split(' ')[4].strip()
result.loc[index, 'job_start'] = line,
elif re.compile(r'任务启动时刻').match(line):
result.loc[index, 'start_time'] = line.split('刻')[1].strip().split(' ')[1].strip() + ' ' + line.split('刻')[1].strip().split(' ')[2].strip()
elif re.compile(r'任务结束时刻').match(line):
result.loc[index, 'end_time'] = line.split('刻')[1].strip().split(' ')[1].strip() + ' ' + line.split('刻')[1].strip().split(' ')[2].strip()
elif re.compile(r'任务总计耗时').match(line):
result.loc[index, 'seconds'] = line.split(':')[1].strip().replace('s','')
elif re.compile(r'任务平均流量').match(line):
result.loc[index, 'traffic'] = line.split(':')[1].strip()
elif re.compile(r'记录写入速度').match(line):
result.loc[index, 'write_speed'] = line.split(':')[1].strip()
elif re.compile(r'读出记录总数').match(line):
result.loc[index, 'read_record'] = line.split(':')[1].strip()
elif re.compile(r'读写失败总数').match(line):
result.loc[index, 'failed_record'] = line.split(':')[1].strip()
elif re.compile(r'job_finish').match(line):
result.loc[index, 'job_finish'] = line,
index = index + 1
else:
pass
save_to_db(result)
get_job_result_from_logfile("/opt/datax/job/log")
以上即为利用 Python 获取 DataX 执行结果并保存至数据库的完整实现方法,希望能为相关开发者提供有价值的参考。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













