基于感兴趣的日期范围作为参数输入限制在 Pig Latin 中加载日志文件

Posted

技术标签:

【中文标题】基于感兴趣的日期范围作为参数输入限制在 Pig Latin 中加载日志文件【英文标题】:Restricting loading of log files in Pig Latin based on interested date range as parameter input 【发布时间】:2013-02-14 22:34:22 【问题描述】:

我在根据参数输入加载日志文件时遇到问题,我想知道是否有人能够提供一些指导。有问题的日志是 Omniture 日志,存储在基于年、月和日的子目录中(例如 /year=2013/month=02/day=14),并在文件名中带有日期戳。对于任何一天,都可能存在多个日志,每个日志有数百 MB。

我有一个 Pig 脚本,它当前处理整个月的日志,并将月份和年份指定为脚本参数(例如 /year=$year/month=$month/day=*)。它运行良好,我们对此非常满意。也就是说,我们希望切换到每周处理日志,这意味着以前的 LOAD 路径 glob 将不起作用(几周可以包含几个月和几年)。为了解决这个问题,我有一个 Python UDF,它需要一个开始日期并为一周的日志吐出必要的 glob,例如:

>>> log_path_regex(2013, 1, 28)
'year=2013/month=01/day=28,year=2013/month=01/day=29,year=2013/month=01/day=30,year=2013/month=01/day=31,year=2013/month=02/day=01,year=2013/month=02/day=02,year=2013/month=02/day=03'

然后这个 glob 将被插入到适当的路径中:

> %declare omniture_log_path 's3://foo/bar/$week_path/*.tsv.gz';
> data = LOAD '$omniture_log_path' USING OmnitureTextLoader(); // See http://github.com/msukmanowsky/OmnitureTextLoader

不幸的是,我一生都无法弄清楚如何根据 $year、$month 和 $day 脚本参数填充 $week_path。我尝试使用 %declare 但 grunt 抱怨说它的日志记录但从不这样做:

> %declare week_path util.log_path_regex(year, month, day);
2013-02-14 16:54:02,648 [main] INFO  org.apache.pig.Main - Apache Pig version 0.10.1 (r1426677) compiled Dec 28 2012, 16:46:13
2013-02-1416:54:02,648 [main] INFO  org.apache.pig.Main - Logging error messages to: /tmp/pig_1360878842643.log % ls  /tmp/pig_1360878842643.log
ls: cannot access /tmp/pig_1360878842643.log: No such file or directory

如果我在参数前面加上美元符号或在前缀参数前面加上引号,也会产生同样的错误。

如果我尝试使用 define(我相信它只适用于静态 Java 函数),我会得到以下信息:

> define week_path util.log_path_regex(year, month, day);
2013-02-14 17:00:42,392 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1200: <file script.pig, line 11, column 37>  mismatched input 'year' expecting RIGHT_PAREN

与 %declare 一样,如果我在参数前面加上美元符号或用引号包围前缀参数,我会得到同样的错误。

我已经四处寻找并没有提出解决方案。我可能正在寻找错误的东西。调用 shell 命令可能会起作用,但会很困难,因为它会使我们的脚本部署复杂化,并且可能不可行,因为我们正在从 S3 而不是挂载的目录中检索日志。同样,将生成的 glob 作为单个参数传递可能会使实例化 MapReduce 集群上的自动化作业复杂化。

除了使用 glob 之外,还可能有一种很好的 Pig 友好方式来限制 LOAD。也就是说,我仍然必须使用我的 UDF,这似乎是问题的根源。

这真的归结为我想在我的 LOAD 语句中包含一个内置于 Pig 中的动态路径 glob。猪似乎没那么容易。

我需要将我的 UDF 转换为静态 Java 方法吗?或者我会遇到同样的问题吗? (如果它会起作用,我会犹豫不决。它是一个 8 行 Python 函数,与等效的 Java 代码相比,它易于部署并且更易于其他人维护。)

自定义 LoadFunc 是答案吗?有了这个,我大概必须指定 /year=/month=/day=* 并强制 Pig 测试每个文件名的日期戳,该日期戳位于两个日期之间。这似乎是一个巨大的黑客攻击和资源浪费。

有什么想法吗?

【问题讨论】:

【参考方案1】:

我posted this question to the Pig user list。我的理解是,在构建 DAG 之前,Pig 将首先预处理其脚本以替换参数、导入和宏。这使得基于现有变量构建新变量变得有些不可能,并解释了我未能构建 UDF 来构建路径 glob。

如果您是 Pig 开发人员,需要基于现有参数构建新变量,您可以使用另一个脚本来构建这些变量并将它们作为参数传递给您的 Pig 脚本,或者您可以探索需要在哪里使用这些变量新变量并根据您的需要在单独的构造中构建它们。

就我而言,我不情愿地选择创建a custom LoadFunc as described by Cheolsoo Park。此LoadFunc 在其构造函数中接受报告期间开始的日期、月份和年份,并构建pathGlob 属性以匹配该期间的路径。然后将pathGlob 插入setLocation() 中的位置。例如。

/**
 * Limit data to a week starting at given day. If day is 0, month is assumed.
 */
public WeeklyOrMonthlyTextLoader(String year, String month, String day) 
    super();
    pathGlob = getPathGlob(
        Integer.parseInt(year),
        Integer.parseInt(month),
        Integer.parseInt(day)
    );


/**
 * Replace DATE_PATH in location with glob required for reading in this
 * month or week of data. This assumes the following directory structure:
 *
 * <code>/year=&gt;year&lt;/month=&gt;month&lt;/day=&gt;day&lt;/*</code>
 */
@Override
public void setLocation(String location, Job job) throws IOException 
    location = location.replace(GLOB_PLACEHOLDER, pathGlob);
    super.setLocation(location, job);

然后从 Pig 脚本中调用它,如下所示:

DEFINE TextLoader com.foo.WeeklyOrMonthlyTextLoader('$year', '$month', '$day');

请注意,构造函数接受String,而不是int。这是因为 Pig 中的参数是字符串,不能在 Pig 脚本中强制转换或转换为其他类型(用于 MR 任务时除外)。

虽然与包装脚本相比,创建自定义 LoadFunc 可能看起来有点矫枉过正,但我​​希望解决方案是纯 Pig 以避免迫使分析师在使用他们的脚本之前执行设置任务。在为计划作业创建 Amazon MapReduce 集群时,我还想在不同时期轻松使用股票 Pig 脚本。

【讨论】:

以上是关于基于感兴趣的日期范围作为参数输入限制在 Pig Latin 中加载日志文件的主要内容,如果未能解决你的问题,请参考以下文章

apache pig - 基于日期列存储文件

ElementUI日期选择器时间选择范围限制

ElementUI日期选择器时间选择范围限制

基于国家/地区的Mysql排除和包含

日期输入限制 iPad

base 64 编码的有效字符范围