Spark如何将日志级别设为ERROR?设置后仍有INFO/WARN日志的原因
你在代码里调用spark.sparkContext.setLogLevel("ERROR")后,仍然看到INFO和WARN级别的日志,说明你并没有完全实现全局日志只输出ERROR级别的目标,主要原因有以下几点:
1. 日志设置的时机太晚
SparkSession和SparkContext的初始化过程会产生大量启动日志,比如Spark上下文加载、Hadoop配置读取、集群连接等环节的INFO/WARN日志,这些日志都是在你调用setLogLevel之前就已经输出了。你的代码是先创建SparkSession,再设置日志级别,这时候启动阶段的日志已经打出来了,这个设置只能影响后续代码执行过程中的日志。
2. Log4j配置的优先级更高
你的代码里引入了org.apache.log4j.Logger,如果你的项目中存在log4j的配置文件(比如log4j.properties或log4j.xml),这个文件的配置优先级会高于spark.sparkContext.setLogLevel的设置。如果配置文件里的根日志级别还是INFO,或者针对Spark相关包(如org.apache.spark、org.hadoop)的级别是INFO,那这些日志会无视你的代码设置继续输出。
3. Spark默认日志配置的影响
Spark安装目录下的conf/log4j.properties(或log4j2对应配置)是默认的日志配置文件,如果这个文件里的级别是INFO,那么Spark启动时会优先遵循这个配置,直到你的代码中的setLogLevel生效,但启动阶段的日志已经无法被抑制了。
解决办法
针对这些问题,你可以尝试以下几种方案:
提前在代码中设置Log4j级别:在创建SparkSession之前就直接配置Log4j的日志级别,这样能覆盖启动阶段的日志:
import org.apache.log4j.{Level, Logger} def main(args: Array[String]): Unit = { // 先设置日志级别,再初始化SparkSession Logger.getRootLogger.setLevel(Level.ERROR) // 可以针对特定包更精准地设置,避免影响其他日志 Logger.getLogger("org.apache.spark").setLevel(Level.ERROR) Logger.getLogger("org.apache.hadoop").setLevel(Level.ERROR) val spark = SparkSession.builder().appName("Spark Example") .config("spark.sql.warehouse.dir", "/user/hive/warehouse") .getOrCreate() // 后续代码... }通过spark-submit参数指定日志级别:在提交命令中直接传入日志配置参数,无需修改代码:
$ ~/programs/spark/spark-2.4.5-bin-hadoop2.7/bin/spark-submit \ --class com.databricks.example.DataFrameExample \ --master local \ --conf "spark.driver.extraJavaOptions=-Dlog4j.rootCategory=ERROR,console" \ --conf "spark.executor.extraJavaOptions=-Dlog4j.rootCategory=ERROR,console" \ target/scala-2.11/example_2.11-0.1-SNAPSHOT.jar /tmp/test/检查并修改项目的Log4j配置文件:如果项目中有
log4j.properties,确保里面的配置符合需求,比如:log4j.rootLogger=ERROR, console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
简单来说,你的setLogLevel("ERROR")确实会在设置之后生效,但无法回溯抑制之前已经输出的启动日志,同时可能被Log4j的配置覆盖,这就是你还能看到INFO/WARN日志的原因。
内容的提问来源于stack exchange,提问作者Tim

