合并MapReduce日志

时间:2013-08-29 18:57:28

标签: logging hadoop mapreduce

调试Hadoop map-reduce作业很痛苦。我可以打印到stdout,但这些日志显示在运行MR作业的所有不同机器上。我可以去找工作跟踪器,找到我的工作,然后点击每个单独的映射器来访问它的任务日志,但是当你有20多个mapper / reducer时,这非常麻烦。

我原本以为我可能要编写一个脚本来查看作业跟踪器,找出每个映射器/缩减器运行的机器,然后将日志记录回一个可能是猫的中心位置一起来。在我浪费时间做这件事之前,是否有人知道更好的方法来获得一个,整合stdout日志以获得作业的映射器和缩减器?

3 个答案:

答案 0 :(得分:1)

我这样做的方式如下:

对于一般调试(即测试作业是否有效),我在本地计算机上以独立模式运行hadoop,并使用少量数据样本。这种方式hadoop可以像任何其他Java应用程序一样工作,并在控制台中显示映射器或缩减器的标准输出。

对于特定的错误(即作业在我的本地机器上正常运行,但在生产中死机)我只是调整代码以作为作业的输出,我通常在调试时发送到stdout。这样,您可以检查作业的结果以调试见解。这不是很好,但它工作正常。

另一种选择是检查jobtracker中的节点日志。他们有stdout和stderr。但是,由于几个原因,我发现上述解决方案要复杂得多(一段时间后删除日志,要查找几个节点等)

答案 1 :(得分:1)

所以我最后只是创建了一个Python脚本来执行此操作。这并不可怕。这是脚本,以防其他人想要使用它。显然它需要更多的错误检查,而不是硬编码的网址等,但你明白了。请注意,您需要下载Beautiful Soup

#!/usr/bin/python
import sys
from bs4 import BeautifulSoup as BS
from urllib2 import urlopen
import re

TRACKER_BASE_URL = 'http://my.tracker.com:50030/'
trackerURLformat = TRACKER_BASE_URL + 'jobtasks.jsp?jobid=%s&type=%s&pagenum=1' # use map or reduce for the type

def findLogs(url):
    finalLog = ""

    print "Looking for Job: " + url
    html = urlopen(url).read()
    trackerSoup = BS(html)
    taskURLs = [h.get('href') for h in trackerSoup.find_all(href=re.compile('taskdetails'))]

    # Now that we know where all the tasks are, go find their logs
    logURLs = []
    for taskURL in taskURLs:
        taskHTML = urlopen(TRACKER_BASE_URL + taskURL).read()
        taskSoup = BS(taskHTML)
        allLogURL = taskSoup.find(href=re.compile('all=true')).get('href')
        logURLs.append(allLogURL)

    # Now fetch the stdout log from each
    for logURL in logURLs:
        logHTML = urlopen(logURL).read()
        logSoup = BS(logHTML)
        stdoutText = logSoup.body.pre.text.lstrip()
        finalLog += stdoutText

    return finalLog


def main(argv):
    with open(argv[1] + "-map-stdout.log", "w") as f:
        f.write(findLogs(trackerURLformat % (argv[1], "map")))
        print "Wrote mapers stdouts to " + f.name

    with open(argv[1] + "-reduce-stdout.log", "w") as f:
        f.write(findLogs(trackerURLformat % (argv[1], "reduce")))
        print "Wrote reducer stdouts to " + f.name

if __name__ == "__main__":
    main(sys.argv)

答案 2 :(得分:0)

我的经验是,当您确切知道哪些地图/减少尝试导致您要通过日志检查问题时,您不需要点击20多个地图/减少输出链接。这就是为什么我总是使用Context.setStatus("在这里发出警告消息")当我抛出异常或增加计数器以引起怀疑时。

有关setStatus的更多信息:http://hadoop.apache.org/docs/r1.1.1/api/org/apache/hadoop/mapreduce/TaskInputOutputContext.html#setStatus(java.lang.String)

https://www.inkling.com/read/hadoop-definitive-guide-tom-white-3rd/chapter-5/running-on-a-cluster(调试作业部分)