如何停止在 spark 控制台上显示 INFO 消息?
How to stop INFO messages displaying on spark console?
我想停止在 spark shell 上发送的各种消息。
我试图编辑 log4j.properties
文件以阻止这些消息。
这里是log4j.properties
的内容
# Define the root logger with appender file
log4j.rootCategory=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
# Settings to quiet third party logs that are too verbose
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO
但消息仍在控制台上显示。
以下是一些示例消息
15/01/05 15:11:45 INFO SparkEnv: Registering BlockManagerMaster
15/01/05 15:11:45 INFO DiskBlockManager: Created local directory at /tmp/spark-local-20150105151145-b1ba
15/01/05 15:11:45 INFO MemoryStore: MemoryStore started with capacity 0.0 B.
15/01/05 15:11:45 INFO ConnectionManager: Bound socket to port 44728 with id = ConnectionManagerId(192.168.100.85,44728)
15/01/05 15:11:45 INFO BlockManagerMaster: Trying to register BlockManager
15/01/05 15:11:45 INFO BlockManagerMasterActor$BlockManagerInfo: Registering block manager 192.168.100.85:44728 with 0.0 B RAM
15/01/05 15:11:45 INFO BlockManagerMaster: Registered BlockManager
15/01/05 15:11:45 INFO HttpServer: Starting HTTP Server
15/01/05 15:11:45 INFO HttpBroadcast: Broadcast server star
如何阻止这些?
您通过将其级别设置为 OFF 来设置禁用日志,如下所示:
Logger.getLogger("org").setLevel(Level.OFF);
Logger.getLogger("akka").setLevel(Level.OFF);
或编辑日志文件并通过更改以下内容将日志级别设置为关闭 属性:
log4j.rootCategory=OFF, console
编辑您的 conf/log4j.properties
文件并更改以下行:
log4j.rootCategory=INFO, console
至
log4j.rootCategory=ERROR, console
另一种方法是:
启动 spark-shell 并输入以下内容:
import org.apache.log4j.Logger
import org.apache.log4j.Level
Logger.getLogger("org").setLevel(Level.OFF)
Logger.getLogger("akka").setLevel(Level.OFF)
之后您将看不到任何日志。
级别的其他选项包括:all
、debug
、error
、fatal
、info
、off
、trace
、trace_int
、warn
上面的答案是正确的,但并没有完全帮助我,因为我需要更多信息。
我刚刚设置了 Spark,因此 log4j 文件仍然具有“.template”后缀并且未被读取。我相信日志记录会默认为 Spark 核心日志记录 conf。
因此,如果您像我一样发现上面的答案没有帮助,那么也许您也必须从 log4j conf 文件中删除“.template”后缀,然后上面的方法才能完美运行!
http://apache-spark-user-list.1001560.n3.nabble.com/disable-log4j-for-spark-shell-td11278.html
一个有趣的想法是按照此处的建议使用 RollingAppender:http://shzhangji.com/blog/2015/05/31/spark-streaming-logging-configuration/
这样您就不会 "polute" 控制台 space,但仍然能够在 $YOUR_LOG_PATH_HERE/${dm.logging.name}.log.[=13= 下看到结果]
log4j.rootLogger=INFO, rolling
log4j.appender.rolling=org.apache.log4j.RollingFileAppender
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.layout.conversionPattern=[%d] %p %m (%c)%n
log4j.appender.rolling.maxFileSize=50MB
log4j.appender.rolling.maxBackupIndex=5
log4j.appender.rolling.file=$YOUR_LOG_PATH_HERE/${dm.logging.name}.log
log4j.appender.rolling.encoding=UTF-8
另一种解决方法是观察你通常有什么样的日志记录(来自不同的模块和依赖项),并为每个设置日志记录的粒度,同时转向"quiet"第三方过于冗长的日志:
例如,
# Silence akka remoting
log4j.logger.Remoting=ERROR
log4j.logger.akka.event.slf4j=ERROR
log4j.logger.org.spark-project.jetty.server=ERROR
log4j.logger.org.apache.spark=ERROR
log4j.logger.com.anjuke.dm=${dm.logging.level}
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO
感谢@AkhlD 和@Sachin Janani 建议对 .conf
文件进行更改。
以下代码解决了我的问题:
1) 在导入部分添加了 import org.apache.log4j.{Level, Logger}
2) 在创建 spark 上下文对象后添加了以下行,即在 val sc = new SparkContext(conf)
之后:
val rootLogger = Logger.getRootLogger()
rootLogger.setLevel(Level.ERROR)
- 按照其他人的描述调整conf/log4j.properties
log4j.rootCategory=错误,控制台
- 确保在执行你的 spark 作业时你传递了带有 log4j.properties 文件路径的 --file 标志
- 如果它仍然不起作用,您可能有一个包含 log4j.properties 的 jar,它在您的新 log4j.properties 之前被调用。从 jar 中删除 log4j.properties(如果适用)
在Python/Spark中我们可以做:
def quiet_logs( sc ):
logger = sc._jvm.org.apache.log4j
logger.LogManager.getLogger("org"). setLevel( logger.Level.ERROR )
logger.LogManager.getLogger("akka").setLevel( logger.Level.ERROR )
定义Sparkcontext后'sc'
通过以下方式调用此函数:quiet_logs( sc )
开始后立即 spark-shell
输入;
sc.setLogLevel("ERROR")
在 Spark 2.0 (Scala) 中:
spark = SparkSession.builder.getOrCreate()
spark.sparkContext.setLogLevel("ERROR")
API 文档:https://spark.apache.org/docs/2.2.0/api/scala/index.html#org.apache.spark.sql.SparkSession
对于Java:
spark = SparkSession.builder.getOrCreate();
spark.sparkContext().setLogLevel("ERROR");
sparkContext.setLogLevel("OFF")
使用 spark-submit 或 spark-sql:
提交申请时,使用以下命令更改日志级别
spark-submit \
--conf "spark.driver.extraJavaOptions=-Dlog4j.configuration=file:<file path>/log4j.xml" \
--conf "spark.executor.extraJavaOptions=-Dlog4j.configuration=file:<file path>/log4j.xml"
注意:替换存储 log4j
配置文件的 <file path>
。
Log4j.properties:
log4j.rootLogger=ERROR, console
# set the log level for these components
log4j.logger.com.test=DEBUG
log4j.logger.org=ERROR
log4j.logger.org.apache.spark=ERROR
log4j.logger.org.spark-project=ERROR
log4j.logger.org.apache.hadoop=ERROR
log4j.logger.io.netty=ERROR
log4j.logger.org.apache.zookeeper=ERROR
# add a ConsoleAppender to the logger stdout to write to the console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
# use a simple message format
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<logger name="org.apache.spark">
<level value="error" />
</logger>
<logger name="org.spark-project">
<level value="error" />
</logger>
<logger name="org.apache.hadoop">
<level value="error" />
</logger>
<logger name="io.netty">
<level value="error" />
</logger>
<logger name="org.apache.zookeeper">
<level value="error" />
</logger>
<logger name="org">
<level value="error" />
</logger>
<root>
<priority value ="ERROR" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
如果您想将日志写入文件而不是控制台,请切换到 log4j.xml 中的 FileAppender。 LOG_DIR
是日志目录的变量,您可以使用 spark-submit --conf "spark.driver.extraJavaOptions=-D
.
提供该变量
<appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="${LOG_DIR}"/>
<param name="datePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
</layout>
</appender>
这里要理解的另一个重要事情是,当作业以分布式模式启动时(部署模式集群和 master 作为 yarn 或 mesos)log4j 配置文件应该存在于驱动程序和工作程序节点上 (log4j.configuration=file:<file path>/log4j.xml
)否则 log4j init 会抱怨-
log4j:ERROR Could not read configuration file [log4j.properties].
java.io.FileNotFoundException: log4j.properties (No such file or
directory)
解决这个问题的提示-
将 log4j 配置文件保存在分布式文件系统(HDFS 或 mesos)中,并使用 log4j PropertyConfigurator 添加外部配置。
或使用 sparkContext addFile 使其在每个节点上可用,然后使用 log4j PropertyConfigurator 重新加载配置。
tl;博士
For Spark Context you may use:
sc.setLogLevel(<logLevel>)
where loglevel
can be ALL, DEBUG, ERROR, FATAL, INFO, OFF, TRACE or
WARN.
详情-
在内部,setLogLevel
调用 org.apache.log4j.Level.toLevel(logLevel)
,然后使用 org.apache.log4j.LogManager.getRootLogger().setLevel(level)
进行设置。
You may directly set the logging levels to OFF
using:
LogManager.getLogger("org").setLevel(Level.OFF)
您可以在 conf/log4j.properties
中为 Spark shell 设置默认日志记录。使用 conf/log4j.properties.template
作为起点。
在 Spark 应用程序中设置日志级别
在独立的 Spark 应用程序中或在 Spark Shell 会话中,使用以下命令:
import org.apache.log4j.{Level, Logger}
Logger.getLogger(classOf[RackResolver]).getLevel
Logger.getLogger("org").setLevel(Level.OFF)
Logger.getLogger("akka").setLevel(Level.OFF)
禁用日志记录(在 log4j 中):
在 conf/log4j.properties
中使用以下命令完全禁用日志记录:
log4j.logger.org=OFF
参考:Jacek Laskowski 的 Mastering Spark。
在命令行上操作简单...
spark2-submit --driver-java-options="-Droot.logger=ERROR,console"
..其他选项..
除了上述所有帖子外,以下是为我解决问题的方法。
Spark 使用 slf4j 绑定到记录器。如果 log4j 不是找到的第一个绑定,您可以随意编辑 log4j.properties 文件,甚至不使用记录器。例如,这可能是一个可能的 SLF4J 输出:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/~/.m2/repository/org/slf4j/slf4j-simple/1.6.6/slf4j-simple-1.6.6.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/~/.m2/repository/org/slf4j/slf4j-log4j12/1.7.19/slf4j-log4j12-1.7.19.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.SimpleLoggerFactory]
所以这里使用了SimpleLoggerFactory,它不关心log4j的设置。
通过
从我的项目中排除 slf4j-simple 包
<dependency>
...
<exclusions>
...
<exclusion>
<artifactId>slf4j-simple</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
解决了这个问题,因为现在使用了 log4j 记录器绑定并且遵守了 log4j.properties 中的任何设置。
F.Y.I。我的 log4j 属性文件包含(除了正常配置)
log4j.rootLogger=WARN, stdout
...
log4j.category.org.apache.spark = WARN
log4j.category.org.apache.parquet.hadoop.ParquetRecordReader = FATAL
log4j.additivity.org.apache.parquet.hadoop.ParquetRecordReader=false
log4j.logger.org.apache.parquet.hadoop.ParquetRecordReader=OFF
希望对您有所帮助!
我只是将这一行添加到我所有的 pyspark 脚本中,位于导入语句正下方的顶部。
SparkSession.builder.getOrCreate().sparkContext.setLogLevel("ERROR")
我的 pyspark 脚本的示例 header
from pyspark.sql import SparkSession, functions as fs
SparkSession.builder.getOrCreate().sparkContext.setLogLevel("ERROR")
只需将以下参数添加到您的 spark-shell 或 spark-submit 命令
--conf "spark.driver.extraJavaOptions=-Dlog4jspark.root.logger=WARN,console"
检查 log4j.properties 文件中的确切 属性 名称(此处为 log4jspark.root.logger)。
希望这对您有所帮助,干杯!
这个对我有用。
对于仅显示为 stdout
的错误消息,log4j.properties
文件可能如下所示:
# Root logger option
log4j.rootLogger=ERROR, stdout
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
NOTE: Put log4j.properties
file in src/main/resources
folder to be
effective.
And if log4j.properties
doesn't exist (meaning spark
is using log4j-defaults.properties
file) then you can create it by going to SPARK_HOME/conf
and then mv log4j.properties.template log4j.properties
and then proceed with above said changes.
如果您无法编辑 java 代码以插入 .setLogLevel()
语句,并且您不想再部署更多外部文件,则可以使用暴力破解解决这个问题的方法。只需使用 grep 过滤掉 INFO 行。
spark-submit --deploy-mode client --master local <rest-of-cmd> | grep -v -F "INFO"
收集到的所有方法和例子
简介
其实,有很多方法可以做到。
有些比其他的更难,但是哪一个最适合你取决于你。我会尽力展示它们。
#1 在您的应用程序中编程
似乎是最简单的,但您需要重新编译您的应用程序才能更改这些设置。就个人而言,我不喜欢它,但它工作正常。
示例:
import org.apache.log4j.{Level, Logger}
val rootLogger = Logger.getRootLogger()
rootLogger.setLevel(Level.ERROR)
Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
Logger.getLogger("org.spark-project").setLevel(Level.WARN)
你可以用 log4j
API.
实现更多
来源:[Log4J Configuration Docs,配置部分]
#2 在 spark-submit
期间通过 log4j.properties
这个非常棘手,但并非不可能。还有我最喜欢的。
Log4J 在应用程序启动期间总是从类路径中寻找并加载 log4j.properties
文件。
但是,当使用 spark-submit
时,Spark Cluster 的类路径优先于应用程序的类路径!这就是为什么把这个文件放在你的 fat-jar 中不会覆盖集群的设置!
Add -Dlog4j.configuration=<location of configuration file>
to
spark.driver.extraJavaOptions
(for the driver) or
spark.executor.extraJavaOptions
(for executors).
Note that if using a
file, the file:
protocol should be explicitly provided, and the file
needs to exist locally on all the nodes.
为了满足最后一个条件,您可以将文件上传到节点可用的位置(如 hdfs
),或者如果使用 deploy-mode client
,则可以使用驱动程序在本地访问它。否则:
upload a custom log4j.properties
using spark-submit, by adding it to
the --files
list of files to be uploaded with the application.
步骤:
示例log4j.properties
:
# Blacklist all to warn level
log4j.rootCategory=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
# Whitelist our app to info :)
log4j.logger.com.github.atais=INFO
正在执行spark-submit
,集群模式:
spark-submit \
--master yarn \
--deploy-mode cluster \
--conf "spark.driver.extraJavaOptions=-Dlog4j.configuration=file:log4j.properties" \
--conf "spark.executor.extraJavaOptions=-Dlog4j.configuration=file:log4j.properties" \
--files "/absolute/path/to/your/log4j.properties" \
--class com.github.atais.Main \
"SparkApp.jar"
请注意,如果使用 client
模式,则必须使用 --driver-java-options
。 Spark docs, Runtime env
正在执行spark-submit
,对于客户端模式:
spark-submit \
--master yarn \
--deploy-mode client \
--driver-java-options "-Dlog4j.configuration=file:/absolute/path/to/your/log4j.properties" \
--conf "spark.executor.extraJavaOptions=-Dlog4j.configuration=file:log4j.properties" \
--files "/absolute/path/to/your/log4j.properties" \
--class com.github.atais.Main \
"SparkApp.jar"
备注:
- 使用
--files
上传到spark-cluster
的文件将在根目录下可用,因此无需在file:log4j.properties
. 中添加任何路径
--files
中列出的文件必须提供绝对路径!
file:
配置 URI 中的前缀是必需的。
#3 编辑集群的 conf/log4j.properties
这会更改 全局日志记录配置文件。
update the $SPARK_CONF_DIR/log4j.properties
file and it will be
automatically uploaded along with the other configurations.
要找到您的 SPARK_CONF_DIR
,您可以使用 spark-shell
:
atais@cluster:~$ spark-shell
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 2.1.1
/_/
scala> System.getenv("SPARK_CONF_DIR")
res0: String = /var/lib/spark/latest/conf
现在只需编辑 /var/lib/spark/latest/conf/log4j.properties
(以方法 #2 中的示例为例),您的所有应用程序都将共享此配置。
#4 覆盖配置目录
如果您喜欢解决方案 #3,但希望针对每个应用程序对其进行自定义,您实际上可以复制 conf
文件夹,编辑其内容并在 spark-submit
期间指定为根配置。
To specify a different configuration directory other than the default “SPARK_HOME/conf”
, you can set SPARK_CONF_DIR
. Spark will use the configuration files (spark-defaults.conf
, spark-env.sh
, log4j.properties
, etc) from this directory.
步骤:
复制集群的 conf
文件夹(更多信息,方法 #3)
在该文件夹中编辑 log4j.properties
(方法 #2 中的示例)
设置SPARK_CONF_DIR
到这个文件夹,然后执行spark-submit
,
示例:
export SPARK_CONF_DIR=/absolute/path/to/custom/conf
spark-submit \
--master yarn \
--deploy-mode cluster \
--class com.github.atais.Main \
"SparkApp.jar"
结论
我不确定是否还有其他方法,但我希望这涵盖了从头到尾的主题。如果没有,请随时在评论中 ping 我!
尽情享受吧!
如果其他人卡在这个上面,
以上都不适合我。
我不得不删除
implementation group: "ch.qos.logback", name: "logback-classic", version: "1.2.3"
implementation group: 'com.typesafe.scala-logging', name: "scala-logging_$scalaVersion", version: '3.9.2'
来自我的 build.gradle 让日志消失。 TLDR:不要导入任何其他日志记录框架,使用 org.apache.log4j.Logger
应该没问题
另一种完全停止日志的方法是:
import org.apache.log4j.Appender;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.varia.NullAppender;
public class SomeClass {
public static void main(String[] args) {
Appender nullAppender = new NullAppender();
BasicConfigurator.configure(nullAppender);
{...more code here...}
}
}
这对我有用。
NullAppender 是
An Appender that ignores log events. (https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/appender/NullAppender.html)
将以下内容添加到 PySpark 为我完成了工作:
self.spark.sparkContext.setLogLevel("ERROR")
self.spark 是火花 session (self.spark = spark_builder.getOrCreate()
)
我想停止在 spark shell 上发送的各种消息。
我试图编辑 log4j.properties
文件以阻止这些消息。
这里是log4j.properties
# Define the root logger with appender file
log4j.rootCategory=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
# Settings to quiet third party logs that are too verbose
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO
但消息仍在控制台上显示。
以下是一些示例消息
15/01/05 15:11:45 INFO SparkEnv: Registering BlockManagerMaster
15/01/05 15:11:45 INFO DiskBlockManager: Created local directory at /tmp/spark-local-20150105151145-b1ba
15/01/05 15:11:45 INFO MemoryStore: MemoryStore started with capacity 0.0 B.
15/01/05 15:11:45 INFO ConnectionManager: Bound socket to port 44728 with id = ConnectionManagerId(192.168.100.85,44728)
15/01/05 15:11:45 INFO BlockManagerMaster: Trying to register BlockManager
15/01/05 15:11:45 INFO BlockManagerMasterActor$BlockManagerInfo: Registering block manager 192.168.100.85:44728 with 0.0 B RAM
15/01/05 15:11:45 INFO BlockManagerMaster: Registered BlockManager
15/01/05 15:11:45 INFO HttpServer: Starting HTTP Server
15/01/05 15:11:45 INFO HttpBroadcast: Broadcast server star
如何阻止这些?
您通过将其级别设置为 OFF 来设置禁用日志,如下所示:
Logger.getLogger("org").setLevel(Level.OFF);
Logger.getLogger("akka").setLevel(Level.OFF);
或编辑日志文件并通过更改以下内容将日志级别设置为关闭 属性:
log4j.rootCategory=OFF, console
编辑您的 conf/log4j.properties
文件并更改以下行:
log4j.rootCategory=INFO, console
至
log4j.rootCategory=ERROR, console
另一种方法是:
启动 spark-shell 并输入以下内容:
import org.apache.log4j.Logger
import org.apache.log4j.Level
Logger.getLogger("org").setLevel(Level.OFF)
Logger.getLogger("akka").setLevel(Level.OFF)
之后您将看不到任何日志。
级别的其他选项包括:all
、debug
、error
、fatal
、info
、off
、trace
、trace_int
、warn
上面的答案是正确的,但并没有完全帮助我,因为我需要更多信息。
我刚刚设置了 Spark,因此 log4j 文件仍然具有“.template”后缀并且未被读取。我相信日志记录会默认为 Spark 核心日志记录 conf。
因此,如果您像我一样发现上面的答案没有帮助,那么也许您也必须从 log4j conf 文件中删除“.template”后缀,然后上面的方法才能完美运行!
http://apache-spark-user-list.1001560.n3.nabble.com/disable-log4j-for-spark-shell-td11278.html
一个有趣的想法是按照此处的建议使用 RollingAppender:http://shzhangji.com/blog/2015/05/31/spark-streaming-logging-configuration/ 这样您就不会 "polute" 控制台 space,但仍然能够在 $YOUR_LOG_PATH_HERE/${dm.logging.name}.log.[=13= 下看到结果]
log4j.rootLogger=INFO, rolling
log4j.appender.rolling=org.apache.log4j.RollingFileAppender
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.layout.conversionPattern=[%d] %p %m (%c)%n
log4j.appender.rolling.maxFileSize=50MB
log4j.appender.rolling.maxBackupIndex=5
log4j.appender.rolling.file=$YOUR_LOG_PATH_HERE/${dm.logging.name}.log
log4j.appender.rolling.encoding=UTF-8
另一种解决方法是观察你通常有什么样的日志记录(来自不同的模块和依赖项),并为每个设置日志记录的粒度,同时转向"quiet"第三方过于冗长的日志:
例如,
# Silence akka remoting
log4j.logger.Remoting=ERROR
log4j.logger.akka.event.slf4j=ERROR
log4j.logger.org.spark-project.jetty.server=ERROR
log4j.logger.org.apache.spark=ERROR
log4j.logger.com.anjuke.dm=${dm.logging.level}
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO
感谢@AkhlD 和@Sachin Janani 建议对 .conf
文件进行更改。
以下代码解决了我的问题:
1) 在导入部分添加了 import org.apache.log4j.{Level, Logger}
2) 在创建 spark 上下文对象后添加了以下行,即在 val sc = new SparkContext(conf)
之后:
val rootLogger = Logger.getRootLogger()
rootLogger.setLevel(Level.ERROR)
- 按照其他人的描述调整conf/log4j.properties log4j.rootCategory=错误,控制台
- 确保在执行你的 spark 作业时你传递了带有 log4j.properties 文件路径的 --file 标志
- 如果它仍然不起作用,您可能有一个包含 log4j.properties 的 jar,它在您的新 log4j.properties 之前被调用。从 jar 中删除 log4j.properties(如果适用)
在Python/Spark中我们可以做:
def quiet_logs( sc ):
logger = sc._jvm.org.apache.log4j
logger.LogManager.getLogger("org"). setLevel( logger.Level.ERROR )
logger.LogManager.getLogger("akka").setLevel( logger.Level.ERROR )
定义Sparkcontext后'sc' 通过以下方式调用此函数:quiet_logs( sc )
开始后立即 spark-shell
输入;
sc.setLogLevel("ERROR")
在 Spark 2.0 (Scala) 中:
spark = SparkSession.builder.getOrCreate()
spark.sparkContext.setLogLevel("ERROR")
API 文档:https://spark.apache.org/docs/2.2.0/api/scala/index.html#org.apache.spark.sql.SparkSession
对于Java:
spark = SparkSession.builder.getOrCreate();
spark.sparkContext().setLogLevel("ERROR");
sparkContext.setLogLevel("OFF")
使用 spark-submit 或 spark-sql:
提交申请时,使用以下命令更改日志级别spark-submit \
--conf "spark.driver.extraJavaOptions=-Dlog4j.configuration=file:<file path>/log4j.xml" \
--conf "spark.executor.extraJavaOptions=-Dlog4j.configuration=file:<file path>/log4j.xml"
注意:替换存储 log4j
配置文件的 <file path>
。
Log4j.properties:
log4j.rootLogger=ERROR, console
# set the log level for these components
log4j.logger.com.test=DEBUG
log4j.logger.org=ERROR
log4j.logger.org.apache.spark=ERROR
log4j.logger.org.spark-project=ERROR
log4j.logger.org.apache.hadoop=ERROR
log4j.logger.io.netty=ERROR
log4j.logger.org.apache.zookeeper=ERROR
# add a ConsoleAppender to the logger stdout to write to the console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
# use a simple message format
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<logger name="org.apache.spark">
<level value="error" />
</logger>
<logger name="org.spark-project">
<level value="error" />
</logger>
<logger name="org.apache.hadoop">
<level value="error" />
</logger>
<logger name="io.netty">
<level value="error" />
</logger>
<logger name="org.apache.zookeeper">
<level value="error" />
</logger>
<logger name="org">
<level value="error" />
</logger>
<root>
<priority value ="ERROR" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
如果您想将日志写入文件而不是控制台,请切换到 log4j.xml 中的 FileAppender。 LOG_DIR
是日志目录的变量,您可以使用 spark-submit --conf "spark.driver.extraJavaOptions=-D
.
<appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="${LOG_DIR}"/>
<param name="datePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %x - %m%n"/>
</layout>
</appender>
这里要理解的另一个重要事情是,当作业以分布式模式启动时(部署模式集群和 master 作为 yarn 或 mesos)log4j 配置文件应该存在于驱动程序和工作程序节点上 (log4j.configuration=file:<file path>/log4j.xml
)否则 log4j init 会抱怨-
log4j:ERROR Could not read configuration file [log4j.properties]. java.io.FileNotFoundException: log4j.properties (No such file or directory)
解决这个问题的提示-
将 log4j 配置文件保存在分布式文件系统(HDFS 或 mesos)中,并使用 log4j PropertyConfigurator 添加外部配置。 或使用 sparkContext addFile 使其在每个节点上可用,然后使用 log4j PropertyConfigurator 重新加载配置。
tl;博士
For Spark Context you may use:
sc.setLogLevel(<logLevel>)
where
loglevel
can be ALL, DEBUG, ERROR, FATAL, INFO, OFF, TRACE or WARN.
详情-
在内部,setLogLevel
调用 org.apache.log4j.Level.toLevel(logLevel)
,然后使用 org.apache.log4j.LogManager.getRootLogger().setLevel(level)
进行设置。
You may directly set the logging levels to
OFF
using:LogManager.getLogger("org").setLevel(Level.OFF)
您可以在 conf/log4j.properties
中为 Spark shell 设置默认日志记录。使用 conf/log4j.properties.template
作为起点。
在 Spark 应用程序中设置日志级别
在独立的 Spark 应用程序中或在 Spark Shell 会话中,使用以下命令:
import org.apache.log4j.{Level, Logger}
Logger.getLogger(classOf[RackResolver]).getLevel
Logger.getLogger("org").setLevel(Level.OFF)
Logger.getLogger("akka").setLevel(Level.OFF)
禁用日志记录(在 log4j 中):
在 conf/log4j.properties
中使用以下命令完全禁用日志记录:
log4j.logger.org=OFF
参考:Jacek Laskowski 的 Mastering Spark。
在命令行上操作简单...
spark2-submit --driver-java-options="-Droot.logger=ERROR,console"
..其他选项..
除了上述所有帖子外,以下是为我解决问题的方法。
Spark 使用 slf4j 绑定到记录器。如果 log4j 不是找到的第一个绑定,您可以随意编辑 log4j.properties 文件,甚至不使用记录器。例如,这可能是一个可能的 SLF4J 输出:
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/C:/Users/~/.m2/repository/org/slf4j/slf4j-simple/1.6.6/slf4j-simple-1.6.6.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/Users/~/.m2/repository/org/slf4j/slf4j-log4j12/1.7.19/slf4j-log4j12-1.7.19.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.SimpleLoggerFactory]
所以这里使用了SimpleLoggerFactory,它不关心log4j的设置。
通过
从我的项目中排除 slf4j-simple 包<dependency>
...
<exclusions>
...
<exclusion>
<artifactId>slf4j-simple</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
解决了这个问题,因为现在使用了 log4j 记录器绑定并且遵守了 log4j.properties 中的任何设置。 F.Y.I。我的 log4j 属性文件包含(除了正常配置)
log4j.rootLogger=WARN, stdout
...
log4j.category.org.apache.spark = WARN
log4j.category.org.apache.parquet.hadoop.ParquetRecordReader = FATAL
log4j.additivity.org.apache.parquet.hadoop.ParquetRecordReader=false
log4j.logger.org.apache.parquet.hadoop.ParquetRecordReader=OFF
希望对您有所帮助!
我只是将这一行添加到我所有的 pyspark 脚本中,位于导入语句正下方的顶部。
SparkSession.builder.getOrCreate().sparkContext.setLogLevel("ERROR")
我的 pyspark 脚本的示例 header
from pyspark.sql import SparkSession, functions as fs
SparkSession.builder.getOrCreate().sparkContext.setLogLevel("ERROR")
只需将以下参数添加到您的 spark-shell 或 spark-submit 命令
--conf "spark.driver.extraJavaOptions=-Dlog4jspark.root.logger=WARN,console"
检查 log4j.properties 文件中的确切 属性 名称(此处为 log4jspark.root.logger)。 希望这对您有所帮助,干杯!
这个对我有用。
对于仅显示为 stdout
的错误消息,log4j.properties
文件可能如下所示:
# Root logger option
log4j.rootLogger=ERROR, stdout
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
NOTE: Put
log4j.properties
file insrc/main/resources
folder to be effective. And iflog4j.properties
doesn't exist (meaningspark
is usinglog4j-defaults.properties
file) then you can create it by going toSPARK_HOME/conf
and thenmv log4j.properties.template log4j.properties
and then proceed with above said changes.
如果您无法编辑 java 代码以插入 .setLogLevel()
语句,并且您不想再部署更多外部文件,则可以使用暴力破解解决这个问题的方法。只需使用 grep 过滤掉 INFO 行。
spark-submit --deploy-mode client --master local <rest-of-cmd> | grep -v -F "INFO"
收集到的所有方法和例子
简介
其实,有很多方法可以做到。 有些比其他的更难,但是哪一个最适合你取决于你。我会尽力展示它们。
#1 在您的应用程序中编程
似乎是最简单的,但您需要重新编译您的应用程序才能更改这些设置。就个人而言,我不喜欢它,但它工作正常。
示例:
import org.apache.log4j.{Level, Logger}
val rootLogger = Logger.getRootLogger()
rootLogger.setLevel(Level.ERROR)
Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
Logger.getLogger("org.spark-project").setLevel(Level.WARN)
你可以用 log4j
API.
实现更多
来源:[Log4J Configuration Docs,配置部分]
#2 在 spark-submit
期间通过 log4j.properties
这个非常棘手,但并非不可能。还有我最喜欢的。
Log4J 在应用程序启动期间总是从类路径中寻找并加载 log4j.properties
文件。
但是,当使用 spark-submit
时,Spark Cluster 的类路径优先于应用程序的类路径!这就是为什么把这个文件放在你的 fat-jar 中不会覆盖集群的设置!
Add
-Dlog4j.configuration=<location of configuration file>
tospark.driver.extraJavaOptions
(for the driver) or
spark.executor.extraJavaOptions
(for executors).Note that if using a file, the
file:
protocol should be explicitly provided, and the file needs to exist locally on all the nodes.
为了满足最后一个条件,您可以将文件上传到节点可用的位置(如 hdfs
),或者如果使用 deploy-mode client
,则可以使用驱动程序在本地访问它。否则:
upload a custom
log4j.properties
using spark-submit, by adding it to the--files
list of files to be uploaded with the application.
步骤:
示例log4j.properties
:
# Blacklist all to warn level
log4j.rootCategory=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
# Whitelist our app to info :)
log4j.logger.com.github.atais=INFO
正在执行spark-submit
,集群模式:
spark-submit \
--master yarn \
--deploy-mode cluster \
--conf "spark.driver.extraJavaOptions=-Dlog4j.configuration=file:log4j.properties" \
--conf "spark.executor.extraJavaOptions=-Dlog4j.configuration=file:log4j.properties" \
--files "/absolute/path/to/your/log4j.properties" \
--class com.github.atais.Main \
"SparkApp.jar"
请注意,如果使用 client
模式,则必须使用 --driver-java-options
。 Spark docs, Runtime env
正在执行spark-submit
,对于客户端模式:
spark-submit \
--master yarn \
--deploy-mode client \
--driver-java-options "-Dlog4j.configuration=file:/absolute/path/to/your/log4j.properties" \
--conf "spark.executor.extraJavaOptions=-Dlog4j.configuration=file:log4j.properties" \
--files "/absolute/path/to/your/log4j.properties" \
--class com.github.atais.Main \
"SparkApp.jar"
备注:
- 使用
--files
上传到spark-cluster
的文件将在根目录下可用,因此无需在file:log4j.properties
. 中添加任何路径
--files
中列出的文件必须提供绝对路径!file:
配置 URI 中的前缀是必需的。
#3 编辑集群的 conf/log4j.properties
这会更改 全局日志记录配置文件。
update the
$SPARK_CONF_DIR/log4j.properties
file and it will be automatically uploaded along with the other configurations.
要找到您的 SPARK_CONF_DIR
,您可以使用 spark-shell
:
atais@cluster:~$ spark-shell
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 2.1.1
/_/
scala> System.getenv("SPARK_CONF_DIR")
res0: String = /var/lib/spark/latest/conf
现在只需编辑 /var/lib/spark/latest/conf/log4j.properties
(以方法 #2 中的示例为例),您的所有应用程序都将共享此配置。
#4 覆盖配置目录
如果您喜欢解决方案 #3,但希望针对每个应用程序对其进行自定义,您实际上可以复制 conf
文件夹,编辑其内容并在 spark-submit
期间指定为根配置。
To specify a different configuration directory other than the default
“SPARK_HOME/conf”
, you can setSPARK_CONF_DIR
. Spark will use the configuration files (spark-defaults.conf
,spark-env.sh
,log4j.properties
, etc) from this directory.
步骤:
复制集群的
conf
文件夹(更多信息,方法 #3)在该文件夹中编辑
log4j.properties
(方法 #2 中的示例)设置
SPARK_CONF_DIR
到这个文件夹,然后执行spark-submit
,
示例:export SPARK_CONF_DIR=/absolute/path/to/custom/conf spark-submit \ --master yarn \ --deploy-mode cluster \ --class com.github.atais.Main \ "SparkApp.jar"
结论
我不确定是否还有其他方法,但我希望这涵盖了从头到尾的主题。如果没有,请随时在评论中 ping 我!
尽情享受吧!
如果其他人卡在这个上面,
以上都不适合我。 我不得不删除
implementation group: "ch.qos.logback", name: "logback-classic", version: "1.2.3"
implementation group: 'com.typesafe.scala-logging', name: "scala-logging_$scalaVersion", version: '3.9.2'
来自我的 build.gradle 让日志消失。 TLDR:不要导入任何其他日志记录框架,使用 org.apache.log4j.Logger
另一种完全停止日志的方法是:
import org.apache.log4j.Appender;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.varia.NullAppender;
public class SomeClass {
public static void main(String[] args) {
Appender nullAppender = new NullAppender();
BasicConfigurator.configure(nullAppender);
{...more code here...}
}
}
这对我有用。 NullAppender 是
An Appender that ignores log events. (https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/appender/NullAppender.html)
将以下内容添加到 PySpark 为我完成了工作:
self.spark.sparkContext.setLogLevel("ERROR")
self.spark 是火花 session (self.spark = spark_builder.getOrCreate()
)