PySpark操作BigQuery时无法屏蔽INFO级别连接器日志求助
问题说明
在Dataproc环境使用Spark BigQuery连接器读取多张BigQuery表时,控制台会被大量来自连接器的INFO级别日志刷屏,典型日志输出如下:
22/07/15 14:24:04 INFO DirectBigQueryRelation: Going to read from pricing-dev.markdown_spark_temp._sbc_ecdac0aeeebedbdfdc7 columns=[MDS_FAM_ID, GEO_REGION_CD, OP_CMPNY_CD, ITEM_NBR, ITEM_DESC_1, UPC_NBR, BASE_DIV_NBR, CNTRY_NM, DEPT_NBR, DEPT_DESC, MDSE_CATG_NBR, MDSE_CATG_DESC, MDSE_SUBCATG_NBR, MDSE_SUBCATG_DESC, SUBCLASS_NBR, SUBCLASS_DESC, FINELINE_NBR, FINELINE_DESC, ACCTG_DEPT_NBR, ACCTG_DEPT_DESC, DEPT_SUBCATG_NBR, DEPT_SUBCATG_DESC, DEPT_C
这类日志主要来自DirectBigQueryRelation和BigQueryUtilScala两个类,需求是仅在程序触发错误时输出相关日志,其余场景关闭这类INFO日志,同时不能影响PySpark业务代码中自定义logger的正常输出。
此前尝试通过如下代码将两个类的日志级别设置为WARN,但配置未生效:
class PipelineLogger(): def __init__(self, spark_session: SparkSession): self.spark_session = spark_session log4j = spark_session._jvm.org.apache.log4j self.log_manager = log4j.LogManager self.log_manager.getLogger('BigQueryUtilScala').setLevel(self.log_manager.Level.WARN) self.log_manager.getLogger('DirectBigQueryRelation').setLevel(self.log_manager.Level.WARN) self.logger = self.log_manager.getLogger(__name__) self.info(f"Logger Initialized for App: {spark_session.sparkContext.getConf().get('spark.app.name')}")
配置失效原因
- Logger名称匹配错误:log4j按类的全限定包名匹配logger,仅传入类名无法定位到BigQuery连接器对应类的logger,配置自然不会生效。
- 配置时机过晚:如果在执行BigQuery读写操作之后才调整日志级别,相关类的logger已经完成初始化,后续setLevel操作无法覆盖已加载的配置,还是会打印INFO日志。
可行解决方案
以下两种方案都只会调整BigQuery连接器相关的日志级别,不会影响业务代码中自定义logger的正常输出。
方案1:代码内配置(推荐,单作业生效)
在SparkSession创建完成后、第一个BigQuery读写操作执行前,使用类的全限定名初始化日志配置,修正后的代码如下:
class PipelineLogger(): def __init__(self, spark_session: SparkSession): self.spark_session = spark_session log4j = spark_session._jvm.org.apache.log4j self.log_manager = log4j.LogManager # 传入BigQuery连接器相关类/包的全限定名 bq_related_loggers = [ "com.google.cloud.spark.bigquery.DirectBigQueryRelation", "com.google.cloud.spark.bigquery.BigQueryUtilScala", # 直接配置整个包路径,覆盖连接器所有类的INFO日志 "com.google.cloud.spark.bigquery", "com.google.cloud.bigquery.connector.common" ] for logger_name in bq_related_loggers: self.log_manager.getLogger(logger_name).setLevel(self.log_manager.Level.WARN) # 自定义业务日志logger正常初始化,不受上述配置影响 self.logger = self.log_manager.getLogger(__name__) self.logger.info(f"Logger Initialized for App: {spark_session.sparkContext.getConf().get('spark.app.name')}")
如果配置后仍有少量BigQuery相关INFO日志,可以直接在输出的日志中查找对应类的全限定包名,加入上述配置列表即可。
方案2:作业提交参数配置(无需改代码)
提交Spark作业时追加如下启动参数,从JVM层面调整BigQuery连接器的日志级别,不需要修改业务代码:
--conf spark.driver.extraJavaOptions="-Dlog4j.logger.com.google.cloud.spark.bigquery=WARN" \ --conf spark.executor.extraJavaOptions="-Dlog4j.logger.com.google.cloud.spark.bigquery=WARN"
如果需要集群全局生效,可以在Dataproc集群创建时通过初始化脚本修改/etc/spark/conf/log4j.properties文件,追加如下配置:
log4j.logger.com.google.cloud.spark.bigquery=WARN log4j.logger.com.google.cloud.bigquery.connector.common=WARN
内容的提问来源于stack exchange,提问作者Frank Pinto
相关产品推荐
相关产品推荐

