• Spark Executor端日志打印的方法


    一、问题背景

    大数据平台采用yarn client模式提交spark 任务,并且多个离线Spark作业共用一个Driver,好处便在于——节省提交任务的时间。但同时也加大了运维工作的难度,因为任务日志打印到同一个文件中。

    为了区分开各个业务流程的日志,平台引入了log4j2 RoutingAppender,配置如下所示:

    1. "1.0" encoding="UTF-8"?>
    2. <Configuration status="info">
    3. <Appenders>
    4. <Console name="std" target="SYSTEM_OUT">
    5. <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t [%C:%L] - %m%n" />
    6. Console>
    7. <Routing name="myAppender">
    8. <Routes pattern="${ctx:logfile}">
    9. <Route>
    10. <File name="log-${ctx:logfile}" fileName="${ctx:logfile}">
    11. <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t [%C:%L] - %m%n" />
    12. File>
    13. Route>
    14. Routes>
    15. <IdlePurgePolicy timeToLive="5" timeUnit="minutes"/>
    16. Routing>
    17. Appenders>
    18. <Loggers>
    19. <Logger name="my" level="INFO" additivity="false">
    20. <AppenderRef ref="myAppender"/>
    21. Logger>
    22. <Root level="INFO">
    23. <AppenderRef ref="std"/>
    24. Root>
    25. Loggers>
    26. Configuration>

    最近数据开发部门在使用大数据平台的二次开发算子时,反馈说平台提供的Logger对象打印不出日志,抱着好奇的心态,研究了一下平台使用的日志框架。其实平台提供的Logger对象打印在executor端打印不出日志很正常,因为上述的log4j2.xml文件并没有分发到executor端,更没有定义名称为my的Logger。那么,executor端的日志该如何打印、收集呢?

    注:

    本文基于华为fusioninsight平台。在fusioninsight平台客户端下,默认提供了executor端的log4j-executor.properties文件,其内容如下:

    1. log4j.logger.org.sparkproject.jetty = WARN
    2. log4j.appender.sparklog = org.apache.log4j.RollingFileAppender
    3. log4j.rootCategory = INFO,sparklog
    4. spark.executor.log.level = INFO
    5. log4j.appender.sparklog.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss,SSS} | %-5p | [%t] | %m | %l%n
    6. log4j.appender.sparklog.Append = true
    7. log4j.appender.sparklog.layout = org.apache.log4j.PatternLayout
    8. log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper = INFO
    9. log4j.appender.sparklog.MaxBackupIndex = 10
    10. log4j.appender.sparklog.File = ${spark.yarn.app.container.log.dir}/stdout
    11. log4j.logger.org.sparkproject.jetty.util.component.AbstractLifeCycle = ERROR
    12. log4j.logger.com.huawei.hadoop.dynalogger.DynaLog4jWatcher = OFF
    13. log4j.appender.sparklog.MaxFileSize = 50MB
    14. log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter = INFO

    那么,executor侧的日志,该如何打印呢?

    二、解决方法

    2.1 使用scala.Console

    scala.Console提供的println和java 中的System.out.println效果是一样的。样例代码形如:

    1. scala.Console.println(s"info zipName is : ${zipName}")
    2. scala.Console.err.println(s"error zipName is : ${zipName}")

    这便是目前大数据平台中输出executor端日志的方式。

    优势

    • 日志打印到stdout中,可使用yarn logs命令汇聚日志。

    • 简单,无需额外的类继承,不需要修改log4j配置。

    缺点

    • 没有日志级别,有些DEBUG用的日志去掉的话,到了生产环境下真出现问题时,难以定位问题;若不去掉,那就会导致yarn上日志过多,看起来较费劲。

    2.2 将driver 端用的log4j2.xml logger配置移到log4j-executor.properties中

    在问题描述部分,我们已经知道driver的logger在executor端打印不了日志,是因为在log4j配置文件中没有相应的logger,于是尝试将driver端配置改造到log4j-executor.properties中。如下所示:

    1. log4j.rootCategory = INFO,sparklog,my
    2. log4j.appender.my = org.apache.log4j.RollingFileAppender
    3. log4j.appender.my.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss,SSS} | %-5p | [%t] | %m | %l%n
    4. log4j.appender.my.Append = true
    5. log4j.appender.my.layout = org.apache.log4j.PatternLayout
    6. log4j.appender.my.MaxBackupIndex = 10
    7. log4j.appender.my.File = ${spark.yarn.app.container.log.dir}/stdout
    8. log4j.appender.my.MaxFileSize = 50MB

    优势

    • 有日志级别,定位问题时可以修改日志级别。

    缺点:

    • 虽然该logger是模仿sparklog来写的,但是在实际测试过程中发现${spark.yarn.app.container.log.dir}并没有完成“宏参”替换,导致appender my打印的日志直接放到了应用启动的目录,即spark CoarseGrainedExecutorBackend进程启动路径下。这带来的弊端就是使用yarn logs命令去汇聚yarn上日志时,汇聚不了,后期定位问题不方便。(当container kill或exit时,日志文件也就被删除了)

    2.3 继承org.apache.spark.internal.Logging

    这是Spark内部打印日志的方式,使用方式形如:

    1. class Operator(@transient bean: Bean) extends Serializable with Logging
    2. {
    3. dataFrame.foreachPartition(partition => {
    4. partition.foreach {
    5. logInfo(s"info org.apache.spark.internal.Logging print content")
    6. logError(s"error org.apache.spark.internal.Logging print content")
    7. }
    8. }
    9. )
    10. }

    优势

    • 定位问题时可以修改日志级别

    • 可以通过yarn logs命令进行汇聚日志

    缺点

    • 需要额外继承org.apache.spark.internal.Logging类

    扩展:

    Spark - Logging 具体用法参考:Spark - Logging 简单使用

    三、总结

    1、推荐使用继承org.apache.spark.internal.Logging类的方式,去输出executor端日志。

    2、log4j2提供的RoutingAppender,可以实现每个业务日志输出到不同的文件中,方便问题定位。

  • 相关阅读:
    Nginx启用Geoip2模块实现国家城市识别 —— 筑梦之路
    网站建设关键程序和知识点相关介绍
    JS语法杂记
    万字血书Vue—Vue语法
    面试官问:如何判断一个元素是否在可视区域?
    【DevOps】Git 图文详解(三):常用的 Git GUI
    计算机基本知识2
    Ei & Scopus检索 | 2024年第三届能源与环境工程国际会议(CFEEE 2024)
    心理咨询预约微信小程序开发制作步骤
    python基础语法(八)
  • 原文地址:https://blog.csdn.net/u011487470/article/details/127402911