sbr*_*non 10 logging scala jar maven apache-spark
我有一个使用Spark的Scala Maven项目,我正在尝试使用Logback实现日志记录.我正在将我的应用程序编译到jar,并部署到安装了Spark发行版的EC2实例.我的pom.xml包含Spark和Logback的依赖项,如下所示:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Run Code Online (Sandbox Code Playgroud)
提交我的Spark应用程序时,我会在命令行上打印出slf4j绑定.如果我使用java执行jar代码,则绑定是Logback.但是,如果我使用Spark(即spark-submit),则绑定到log4j.
val logger: Logger = LoggerFactory.getLogger(this.getClass)
val sc: SparkContext = new SparkContext()
val rdd = sc.textFile("myFile.txt")
val slb: StaticLoggerBinder = StaticLoggerBinder.getSingleton
System.out.println("Logger Instance: " + slb.getLoggerFactory)
System.out.println("Logger Class Type: " + slb.getLoggerFactoryClassStr)
Run Code Online (Sandbox Code Playgroud)
产量
Logger Instance: org.slf4j.impl.Log4jLoggerFactory@a64e035
Logger Class Type: org.slf4j.impl.Log4jLoggerFactory
Run Code Online (Sandbox Code Playgroud)
据我了解,双方log4j-1.2.17.jar
并slf4j-log4j12-1.7.16.jar
都在/ usr /本地/火花/罐,而火花,尽管在我的pom.xml排除最有可能引用这些罐子,因为如果我删除,我给在运行时一个ClassNotFoundException火花提交.
我的问题是:有没有办法使用Logback在我的应用程序中实现本机日志记录,同时保留Spark的内部日志记录功能.理想情况下,我想将Logback应用程序日志写入文件,并允许Spark日志仍显示在STDOUT.
Ata*_*ais 10
我遇到了非常类似的问题。
我们的构建类似于您的构建(但我们使用sbt
),并在此处进行了详细说明:https : //stackoverflow.com/a/45479379/1549135
在本地运行此解决方案效果很好,但随后spark-submit
将忽略所有排除项和新的日志记录框架(logback
),因为spark的类路径优先于已部署的jar。而且由于它包含log4j 1.2.xx
它,因此只需加载它,而忽略我们的设置。
我已经使用了几种来源。但引用Spark 1.6.1文档(同样适用于Spark最新版本/ 2.2.0):
spark.driver.extraClassPath
额外的类路径条目,以前置于驱动程序的类路径。注意:在客户端模式下,不得直接在应用程序中通过SparkConf设置此配置,因为此时驱动程序JVM已经启动。相反,请通过--driver-class-path命令行选项或在默认属性文件中进行设置。
spark.executor.extraClassPath
额外的类路径条目,以附加到执行者的类路径。主要是为了与旧版本的Spark向后兼容。用户通常不需要设置此选项。
此处未写的是,extraClassPath
它优先于默认Spark的类路径!
因此,现在的解决方案应该非常明显。
- log4j-over-slf4j-1.7.25.jar
- logback-classic-1.2.3.jar
- logback-core-1.2.3.jar
Run Code Online (Sandbox Code Playgroud)
spark-submit
:libs="/absolute/path/to/libs/*"
spark-submit \
...
--master yarn \
--conf "spark.driver.extraClassPath=$libs" \
--conf "spark.executor.extraClassPath=$libs" \
...
/my/application/application-fat.jar \
param1 param2
Run Code Online (Sandbox Code Playgroud)
我还不确定是否可以将这些罐子放在HDFS上。我们将它们放在应用程序jar的本地。
奇怪的是,使用Spark 1.6.1
docs我也在文档中找到了这个选项:
spark.driver.userClassPathFirst,spark.executor.userClassPathFirst
(实验性的)在驱动程序中加载类时,是否使用户添加的jar优先于Spark自己的jar。此功能可用于缓解Spark依赖项和用户依赖项之间的冲突。目前,这是一项实验功能。仅在群集模式下使用。
但只需设置:
--conf "spark.driver.userClassPathFirst=true" \
--conf "spark.executor.userClassPathFirst=true" \
Run Code Online (Sandbox Code Playgroud)
没有为我工作。所以我很高兴使用extraClassPath
!
干杯!
logback.xml
如果您在加载logback.xml
到Spark时遇到任何问题,我在这里的问题可能会帮助您:将
系统属性传递给spark-submit并从类路径或自定义路径读取文件
我遇到了同样的问题:我试图使用 logback 配置文件。我尝试了很多排列,但没有成功。
我使用以下 SBT 依赖项通过 grizzled-slf4j 访问 logback:
"org.clapper" %% "grizzled-slf4j" % "1.3.0",
Run Code Online (Sandbox Code Playgroud)
添加 log4j 配置文件后:
src/main/resources/log4j.properties/log4j.properties files.
Run Code Online (Sandbox Code Playgroud)
我的日志记录工作正常。