AWS EMR Spark Python 日志记录

AWS EMR Spark Python Logging

我运行在 AWS EMR 上执行一个非常简单的 Spark 作业,似乎无法从我的脚本中获取任何日志输出。

我试过打印到 stderr:

from pyspark import SparkContext
import sys

if __name__ == '__main__':
    sc = SparkContext(appName="HelloWorld")
    print('Hello, world!', file=sys.stderr)
    sc.stop()

并使用如图所示的火花记录器here:

from pyspark import SparkContext

if __name__ == '__main__':
    sc = SparkContext(appName="HelloWorld")

    log4jLogger = sc._jvm.org.apache.log4j
    logger = log4jLogger.LogManager.getLogger(__name__)
    logger.error('Hello, world!')

    sc.stop()

EMR 在作业 运行s 后给了我两个日志文件:controllerstderr。两个日志都不包含 "Hello, world!" 字符串。我的理解是 stdout 在 spark 中被重定向到 stderrstderr 日志显示作业已被接受,运行,并已成功完成。

所以我的问题是,在哪里可以查看脚本的日志输出?或者我应该在我的脚本中更改什么才能正确记录?

编辑:我使用此命令提交步骤:

aws emr add-steps --region us-west-2 --cluster-id x-XXXXXXXXXXXXX --steps Type=spark,Name=HelloWorld,Args=[--deploy-mode,cluster,--master,yarn,--conf,spark.yarn.submit.waitAppCompletion=true,s3a://path/to/simplejob.py],ActionOnFailure=CONTINUE

我发现 EMR 对特定步骤的日志记录几乎永远不会出现在控制器或 stderr 日志中,这些日志与 AWS 控制台中的步骤一起被拉出。

通常我会在 作业的 容器日志中找到我想要的(通常它在标准输出中)。

这些通常位于 s3://mybucket/logs/emr/spark/j-XXXXXX/containers/application‌​_XXXXXXXXX/container‌​_XXXXXXX/... 之类的路径中。您可能需要在 containers.

中的各种 application_...container_... 目录中四处寻找

最后一个容器目录应该有 stdout.logstderr.log

要捕获脚本的输出,您也可以尝试如下操作

/usr/bin/spark-submit --master yarn --num-executors 300 myjob.py param1 > s3://databucket/log.out 2>&1 &

这会将脚本输出写入 s3 位置的日志文件。

物有所值。设 j-XXX 为 EMR 集群的 ID,并假设它配置为使用 logs_bucket 在 S3 上持久化日志。如果您想查找您的代码发出的日志,请执行以下操作:

  1. 在 AWS 控制台中,找到您要查看的步骤
  2. 转到 stderr 并搜索 application_。记下您找到的全名,它应该类似于 application_15489xx175355_0yy5.
  3. 转到 s3://logs_bucket/j-XXX/containers 并找到文件夹 application_15489xx175355_0yy5
  4. 在此文件夹中,您将找到至少一个名为 application_15489xx175355_0yy5_ww_vvvv 的文件夹。在这些文件夹中,您会找到名为 stderr.gz 的文件,其中包含您的代码发出的日志。

我在 YARN 客户端模式下使用 emr-5.30.1 运行 并使用 Python logging 库让它工作。

我不喜欢在 Spark 中使用 JVM 私有方法的解决方案。除了作为私有方法之外,这些方法还导致我的应用程序日志出现在 Spark 日志中(已经很冗长了),而且还迫使我使用 Spark 的日志记录格式。

示例代码使用 logging:

import logging

logging.basicConfig(
    format="""%(asctime)s,%(msecs)d %(levelname)-8s[%(filename)s:%(funcName)s:%(lineno)d] %(message)s""",
    datefmt="%Y-%m-%d %H:%M:%S",
    level=logging.INFO,
)

if __name__ == '__main__':
    logging.info('test')
    ...

创建集群时,我通过控制台/CLI/boto 指定LogUri='s3://mybucket/emr/'

日志输出出现在相关步骤的 stdout.gz 中,可以使用以下任一选项找到。

  1. 在 EMR 控制台中选择您的集群。在“摘要”选项卡上,单击“日志 URI”旁边的小文件夹图标。在弹出窗口中,导航到步骤,选择您的步骤 ID,然后打开 stdout.gz

  2. 在 S3 中直接导航到日志。它们位于 mybucket 中的 emr/j-<cluster-id>/steps/s-<step-id>/stdout.gz