无论是PySpark程序、还是Scala 编写的Spark程序,对于运行中的日志写入与查看的现状都是类似的,大体有两点痛点:
1.特别是一直在线运行的Streaming项目,通过print打印的日志直接进入了stderr,且这个文件不会自动切分、滚动,最后导致stderr巨大,占用节点资源不说,对日志参考、问题排查也是难上加难。
2.现阶段生产环境多数以资源管理YARN、Mesos为主,executor中无法正常通过配置参数以及获取log4j对象来打印日志
尝试解决问题
上传自定义log4j.properties
我们了解到spark程序使用log4j组件来记录日志。
尝试解决日志切分、轮转问题时,尝试过上传自定义log4j配置来达到切分日志的目的,但log4j本身对stdout、stderr支持实在欠佳,我们也无法通过log4j配置来解决这个问题。
添加spark配置
后续尝试通过配置:
spark.executor.logs.rolling.time.interval=minutely
spark.executor.logs.rolling.maxRetainedFiles=5
spark.executor.logs.rolling.strategy=time
但不生效,后来查证这些配置只在standalone部署模式下有效,在YARN集群模式下并无效果。
获取log4J对象
后尝试通过从py4j从jvm获取log4j对象,能够成功从driver打印日志,但executor无法获取log4j对象,进而也无法正常打印。
最终通用解决方案:通过YARN环境变量构造日志记录
通过YARN 容器中的LOG_DIRS环境变量,我们可以获取当前application对应executor的日志记录路径,那么我们只需要借助python的logging包,构造一个日志记录对象,记录到当前这个目录,就完成了自定义日志落地的能力。
参考链接:
https://stackoverflow.com/questions/41740750/how-to-configure-the-log-level-of-a-specific-logger-using-log4j-in-pyspark