我正在使用DynamicFrame的map
方法(或者等效地,Map.apply
方法)。我注意到,我传递给这些函数的函数中的任何错误都会被忽略,导致返回的DynamicFrame为空。
说我有这样的工作脚本:
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.transforms import *
glueContext = GlueContext(SparkContext.getOrCreate())
dyF = glueContext.create_dynamic_frame.from_catalog(database="radixdemo", table_name="census_csv")
def my_mapper(rec):
import logging
logging.error("[RADIX] An error-log from in the mapper!")
print "[RADIX] from in the mapper!"
raise Exception("[RADIX] A bug!")
dyF = dyF.map(my_mapper, 'my_mapper')
print "Count: ", dyF.count()
dyF.printSchema()
dyF.toDF().show()
如果我使用gluepython
在我的Glue Dev Endpoint中运行此脚本,我会得到如下输出:
[glue@ip-172-31-83-196 ~]$ gluepython gluejob.py
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/share/aws/glue/etl/jars/glue-assembly.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/lib/spark/jars/slf4j-log4j12-1.7.16.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
18/05/23 20:56:46 WARN Client: Neither spark.yarn.jars nor spark.yarn.archive is set, falling back to uploading libraries under SPARK_HOME.
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
Count: 0
root
++
||
++
++
关于此输出的说明:
print
声明或logging.error
声明的结果。my_mapper
引发了例外。printSchema
调用显示生成的DynamicFrame show
方法也没有产生任何输出,表明所有行都消失了。同样,当我将此脚本保存为AWS Glue控制台中的作业并运行它时,作业不会指示发生任何错误 - 作业状态为“成功”。值得注意的是,我做将print
语句和logging.error
调用输出到作业日志,但仅限于常规“日志”,而不是“错误日志”。
我想要的是能够指示我的工作失败,并能够轻松找到这些错误日志。最重要的是表明它已经失败了。
有没有办法在映射函数中记录错误,以便Glue将其作为“错误日志”(并将其放在单独的AWS CloudWatch Logs路径中)?如果发生这种情况,它会自动将整个作业标记为失败吗?或者是否有其他方法可以在映射函数中明确地使作业失败?
(我的计划是,如果有办法记录错误和/或将作业标记为失败,那就是创建一个装饰器或其他实用程序函数,它将自动捕获映射函数中的异常,并确保它们被记录和放大。标记为失败)。
答案 0 :(得分:2)
我发现使胶水作业显示为“失败”的唯一方法是从主脚本(在映射器或过滤器函数内的 not 中引发异常),因为这些似乎得到了旋转到数据处理单元)。
幸运的是,有一种 方法可以使用DynamicFrame.stageErrorsCount()
方法来检测是否在map或filter函数内部发生了异常。它将返回一个数字,指示在运行最新转换时引发了多少个异常。
所以解决所有问题的正确方法是
try/except
语句。stageErrorsCount()
方法并检查它是否大于0。如果要中止该作业,只需引发一个异常。例如:
import logging
def log_errors(inner):
def wrapper(*args, **kwargs):
try:
inner(*args, **kwargs)
except Exception as e:
logging.exception('Error in function: {}'.format(inner))
raise
return wrapper
@log_errors
def foo(record):
1 / 0
然后,在您的工作中,您将执行以下操作:
df = df.map(foo, "foo")
if df.stageErrorsCount() > 0:
raise Exception("Error in job! See the log!")
请注意,由于某种原因,即使从mapper函数内部调用logging.exception
仍不会将日志写入AWS CloudWatch Logs中的 error 日志。它被写入常规成功日志。但是,使用这种技术,您至少会看到作业失败,并且能够在日志中找到信息。另一个警告:Dev Endpoints似乎没有显示来自映射器或过滤器功能的任何日志。