将 Logback 中的应用程序日志与 log4j 中的 Spark 日志分开

     2023-03-17     38

关键词:

【中文标题】将 Logback 中的应用程序日志与 log4j 中的 Spark 日志分开【英文标题】:Separating application logs in Logback from Spark Logs in log4j 【发布时间】:2017-06-26 20:05:54 【问题描述】:

我有一个使用 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>

提交我的 Spark 应用程序时,我在命令行上打印出 slf4j 绑定。如果我使用 java 执行 jars 代码,则绑定到 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)

产量

Logger Instance: org.slf4j.impl.Log4jLoggerFactory@a64e035
Logger Class Type: org.slf4j.impl.Log4jLoggerFactory

我知道 log4j-1.2.17.jarslf4j-log4j12-1.7.16.jar 都在 /usr/local/spark/jars 中,尽管我的 pom.xml 中排除了这些 jars,但 Spark 很可能引用了这些 jars,因为如果我删除它们,我就是在 spark-submit 运行时给出 ClassNotFoundException。

我的问题是:有没有办法使用 Logback 在我的应用程序中实现本机日志记录,同时保留 Spark 的内部日志记录功能。理想情况下,我想将我的 Logback 应用程序日志写入文件并允许 Spark 日志仍显示在 STDOUT 中。

【问题讨论】:

【参考方案1】:

我遇到了同样的问题:我试图使用 logback 配置文件。我尝试了很多排列,但我没有让它工作。

我正在使用这个 SBT 依赖项通过 grizzled-slf4j 访问 logback:

"org.clapper" %% "grizzled-slf4j" % "1.3.0",

一旦我添加了 log4j 配置文件:

src/main/resources/log4j.properties/log4j.properties files.

我的日志记录工作正常。

【讨论】:

最终使用了相同的方法,不幸的是这仍然使用 log4j 作为底层框架。仍然想知道是否有人能够配置 Logback。 我浪费了很多时间寻找。但我想了解自己。【参考方案2】:

我遇到了一个非常相似的问题。

我们的构建与您的相似(但我们使用了sbt)并在此处详细描述:https://***.com/a/45479379/1549135

在本地运行此解决方案可以正常工作,但随后 spark-submit忽略所有排除项和新的日志记录框架 (logback),因为 spark 的类路径优先于部署的罐子。由于它包含log4j 1.2.xx,它会简单地加载它并忽略我们的设置。

解决方案

我使用了几个来源。但是引用Spark 1.6.1 docs(也适用于Spark latest / 2.2.0):

spark.driver.extraClassPath

附加到驱动程序的类路径前面的类路径条目。 注意:在客户端模式下,这个配置不能直接在你的应用程序中通过 SparkConf 设置,因为此时驱动程序 JVM 已经启动。相反,请通过 --driver-class-path 命令行选项或在您的默认属性文件中进行设置。

spark.executor.extraClassPath

附加到执行器的类路径之前的类路径条目。这主要是为了向后兼容旧版本的 Spark。用户通常不需要设置此选项。

这里没有写,不过extraClassPath 优先于默认Spark的类路径!

所以现在解决方案应该很明显了。

1。下载这些罐子:

- log4j-over-slf4j-1.7.25.jar
- logback-classic-1.2.3.jar
- logback-core-1.2.3.jar

2。运行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

我只是不确定您是否可以将这些 jar 放在 HDFS 上。我们将它们放在本地应用程序 jar 旁边。

userClassPathFirst

奇怪的是,使用Spark 1.6.1 我也在文档中找到了这个选项:

spark.driver.userClassPathFirstspark.executor.userClassPathFirst

(实验性)在驱动程序中加载类时,是否让用户添加的 jar 优先于 Spark 自己的 jar。此功能可用于缓解 Spark 的依赖项和用户依赖项之间的冲突。它目前是一个实验性功能。这仅用于集群模式。

但只是设置:

--conf "spark.driver.userClassPathFirst=true" \
--conf "spark.executor.userClassPathFirst=true" \

对我不起作用。所以我很乐意使用extraClassPath

干杯!


加载中logback.xml

如果您在将logback.xml 加载到 Spark 时遇到任何问题,我的问题可能会帮助您: Pass system property to spark-submit and read file from classpath or custom path

【讨论】:

我正在尝试遵循这个,因为我有同样的问题,我实际上希望 spark-submit 将日志发送到 loggy,所以我使用 logback 和 loggly appender。我使用 maven 和一个 uber jar,其中包含要在 spark-submit 中发送的所有文件。但是那里的类路径是什么?我没有看到任何可行的绝对路径。你能澄清那部分吗? 我不明白这个问题:“但是那里的类路径是什么?”我认为你最好提出你的问题并描述你在那里做了什么。 k,添加问题***.com/questions/64250847/… 发现了我的问题。我无法让它与你上面所说的一起工作,但我可以通过对 org.slf4j 进行着色(如@matemaciek 的回答中所述)。将在我上面发布的票中详细说明我的整个解决方案。 这是因为你不能将 logback 打包在 fat jar 中。它们必须在我的解决方案中从外部提供。这是由于 spark 中的类路径优先级。【参考方案3】:

经过一番努力,我找到了另一个解决方案:库阴影

在我为 org.slf4j 着色后,我的应用程序日志与 spark 日志分离。此外,我的应用程序 jar 中的 logback.xml 很荣幸。

Here you can find information on library shading in sbt,在这种情况下归结为:

assemblyShadeRules in assembly += ShadeRule.rename("org.slf4j.**" -> "your_favourite_prefix.@0").inAll

在您的build.sbt 设置中。


旁注:如果您不确定是否真的发生了阴影,请在某个存档浏览器中打开您的 jar,并检查目录结构是否反映了阴影,在这种情况下,您的 jar 应该包含路径/your_favourite_prefix/org/slf4j,但不是/org/slf4j

【讨论】:

我的意图是使用我选择的框架:应用程序和火花,我的解决方案允许它。但是是的,如果你想要单独的配置阴影很好 这是在我的案例中唯一有效的解决方案。所有其他提到的选项(以及它们的各种组合)都不成功 我在 maven 中成功着色 slf4j,但收到错误:SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder"。 SLF4J:默认为无操作 (NOP) 记录器实现 SLF4J:有关详细信息,请参阅 slf4j.org/codes.html#StaticLoggerBinder。还有什么你没有提到的需要设置的吗?【参考方案4】:

我将 logback 和 log4j-to-slf4j 以及我的其他依赖项和 src/main/resources/logback.xml 打包在一个胖 jar 中。

当我运行 spark-submit 时

--conf "spark.driver.userClassPathFirst=true" \
--conf "spark.executor.userClassPathFirst=true"

所有日志记录都由 logback 处理。

【讨论】:

我在尝试时收到以下错误:线程“主”java.lang.LinkageError 中的异常:加载程序约束违规:解析方法时“org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg /slf4j/ILoggerFactory;"当前类 org/slf4j/LoggerFactory 的类加载器(org/apache/spark/util/ChildFirstURLClassLoader 的实例)和方法定义类 org 的类加载器(sun/misc/Launcher$AppClassLoader 的实例) /slf4 j/impl/StaticLoggerBinder,对于签名中使用的类型 org/slf4j/ILoggerFactory 有不同的 Class 对象【参考方案5】:

我不得不修改 Atais 提供的解决方案,使其在集群模式下工作。 这对我有用:

libs="/absolute/path/to/libs/*"

spark-submit \
--master yarn \
--deploy-mode cluster \
... \
--jars $libs \
--conf spark.driver.extraClassPath=log4j-over-slf4j-1.7.25.jar:logback-classic-1.2.3.jar:logback-core-1.2.3.jar:logstash-logback-encoder-6.4.jar \
--conf spark.executor.extraClassPath=log4j-over-slf4j-1.7.25.jar:logback-classic-1.2.3.jar:logback-core-1.2.3.jar:logstash-logback-encoder-6.4.jar \
/my/application/application-fat.jar \
param1 param2

根本原因是 jars 并非对所有节点都可用,必须明确提供(即使在使用 --jars 提交之后)。

更新:进一步完善了解决方案。您还可以将罐子作为 url 列表传递,即--jars url1,url2,url3。这些 jar 仍然必须添加到类路径中才能优先于 log4j。

【讨论】:

logback日志的配置使用

参考技术Alogback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback-classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个改良版本。此外logback-classic完整实现slf4japi... 查看详情

springboot2中的默认日志管理与logback配置详解(代码片段)

...是开放的。在SpringBoot生态中,为JavaUtilLogging、Log4J2和Logback这些常见的日志框架都提供了自动化配置组件,每种Logger都可以通过配置在控制台或者文件中输出日志内容。默认情况下,当我们使用各种Starter的时候,... 查看详情

将spark默认日志log4j替换为logback

1.将jars文件夹下apache-log4j-extras-1.2.17.jar,commons-logging-1.1.3.jar,log4j-1.2.17.jar,slf4j-log4j12-1.7.16.jar替换成log4j-over-slf4j-1.7.23.jar,logback-access-1.2.1.jar,logback-classic-1.2.1.jar,logback-c 查看详情

slf4j与logback日志配置详解

背景javaweb下有好几种日志框架,比如:logback,log4j,log4j2(slj4f并不是一种日志框架,它相当于定义了规范,实现了这个规范的日志框架就能够用slj4f调用)。其中性能最高的应该使logback了,而且springboot默认使用的也是logback日... 查看详情

java日志框架学习--logback和log4j2--下

Java日志框架学习--LogBack和Log4j2--下LogbackLogback中的组件Logback配置文件日志输出格式使用演示配置文件输出到控制台输出到控制台和文件输出到控制台,文件和html日志拆分过滤器异步日志自定义LoggerLog4jLog4j2简介Log4j2特征应用演示... 查看详情

日志组件之debug动态开关(代码片段)

日志组件之debug动态开关一、应用场景二、logback简介三、logback应用debug动态开关 一、应用场景生产环境,系统日志记录级别一般高于或等于INFO,不会开启DEBUG级别的日志打印。但如果生产环境系统出现问题,需要在... 查看详情

Logback SyslogAppender stacktrace 日志记录前缀

】LogbackSyslogAppenderstacktrace日志记录前缀【英文标题】:LogbackSyslogAppenderstacktraceloggingprefix【发布时间】:2012-04-0210:37:57【问题描述】:我们最近从Log4J切换到Logback。除了SyslogAppender中的堆栈跟踪之外,日志记录似乎运行良好。它... 查看详情

log4j/log4j2/logback混用问题

...了解标题提到的几个日志框架,建议了解一下log4j/log4j2/logback简单使用说明,本节中pom依赖前面的内容;log4jdemolog4j2demologbackdemologdemojava项目一般会选择一种日志框架,但很难保证当前项目依赖的三方组件会选用和当前项目相同... 查看详情

最全的springboot+logback日志配置教程

...志系统是必不可少的,目前比较流行的日志框架有log4j、logback等,可能大家还不知道,这两个框架的作者是同一个人,Logback旨在作为流行的log4j项目的后续版本,从而恢复log4j离开的位置。另外slf4j(SimpleLoggingFacadeforJava)则是一个... 查看详情

java应用在java中使用log4j/logback进行日志记录和调试

...g4j是什么?Log4j是一个Java日志框架,它允许开发人员记录应用程序中发生的事件。它具有非常灵活的配置选项,可以将日志消息发送到不同的目标(如文件、控制台、数据库、syslog等)并使用各种格式进行格式化。Log4j是ApacheSoft... 查看详情

springbootlogback配置详解(代码片段)

一.了解简单地说,Logback是一个Java领域的日志框架。它被认为是Log4J的继承人。Logback主要由三个模块组成:logback-corelogback-classiclogback-accesslogback-core是其它模块的基础设施,其它模块基于它构建,显然,logback-core提供了一些关键... 查看详情

logback使用

logback简介   Slf4j是TheSimpleLoggingFacadeforJava的简称,是一个简单日志门面抽象框架,它本身只提供了日志FacadeAPI和一个简单的日志类实现,一般常配合Log4j,LogBack,java.util.logging使用。Slf4j作为应用层的Log接入时,程序可... 查看详情

logback日志打印怎么实现换行

logback类似于log日志体系,可以将一些日志信息输出到tomcat文件夹内,示例如下:logback.xml里面的内容配置:UTF-8$logbase%dyyyy-MM-dd.log.html$logbase.%dyyyy-MM-dd.log.html.zip使用的时候可以这样定义变量:Loggerlogger=Lo...参考技术A/n单个斜杠紧... 查看详情

读书笔记为什么阿里巴巴禁止直接使用日志系统(log4jlogback)中的api

...从log4j变为logback),只需要修改配置文件,而应用程序本身是无感知的。使用skf4j的目的就是为了解耦。为什么阿里巴巴禁止直接使用日志系统(Log4j、Logback)中的API原文 查看详情

利用logback+slf4j日志采集整合到sba

...;可以按包名控制日志级别,只输出某些包打的日志......logback是一个日志采集系统的实现;slf4j是日志系统的接口,如同jdbc一样定义了一套接口,是一个日志门面可实现多个日志系统间快速切换。logback基础功能包含三个组成部... 查看详情

logback日志

参考技术ALogback继承自log4j。Logback的架构非常的通用,适用不同的使用场景。Logback被分成三个不同的模块:logback-core,logback-classic,logback-access。logback-core是其它两个模块的基础。logback-classic模块可以看作是log4j的一个优化版本... 查看详情

日志框架logback相对于log4j的优势

日志框架logback相对于log4j的优势。更快的实现 Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。 非常充分的测试 Logback经过了几年,数不清小时的... 查看详情

springboot配置logback日志

Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback-classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个改良版本。此外logback-classic完整实现SLF4JAPI使你可以... 查看详情