我正在尝试在我的Spark作业中使用log4j 2 记录器。基本要求:log4j2配置位于类路径之外,因此我需要明确指定其位置。当我在IDE中直接运行我的代码而不使用spark-submit
时, log4j2 运行良好。但是,当我使用spark-submit
向Spark集群提交相同的代码时,它无法找到log42配置并回退到默认的旧log4j。
启动器命令
${SPARK_HOME}/bin/spark-submit \
--class my.app.JobDriver \
--verbose \
--master 'local[*]' \
--files "log4j2.xml" \
--conf spark.executor.extraJavaOptions="-Dlog4j.configurationFile=log4j2.xml" \
--conf spark.driver.extraJavaOptions="-Dlog4j.configurationFile=log4j2.xml" \
myapp-SNAPSHOT.jar
maven中的Log4j2依赖
<dependencies>
. . .
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!-- Bridge log4j to log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!-- Bridge slf4j to log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependencies>
我想念的任何想法?
答案 0 :(得分:4)
显然目前在Spark中没有log4j2的官方支持官员。以下是关于该主题的详细讨论:https://issues.apache.org/jira/browse/SPARK-6305
在实践方面,这意味着:
如果您可以访问Spark配置和jar并且可以修改它们,那么在手动将log4j2 jar添加到SPARK_CLASSPATH并向Spark提供log4j2
配置文件后,您仍然可以使用log4j2
。
如果您在托管Spark集群上运行并且无法访问Spark jars / configs,那么您仍然可以使用log4j2
,但它的使用仅限于在驱动程序端执行的代码。执行程序运行的任何代码部分都将使用Spark执行程序记录器(旧的log4j)
答案 1 :(得分:2)
Spark回退到log4j,因为它可能无法在启动期间初始化日志记录系统(您的应用程序代码未添加到类路径中)。
如果允许在集群节点上放置新文件,则在所有节点上创建目录(例如/opt/spark_extras
),将所有log4j2 jar放在那里,并为spark-submit添加两个配置选项:
--conf spark.executor.extraClassPath=/opt/spark_extras/*
--conf spark.driver.extraClassPath=/opt/spark_extras/*
然后将库添加到类路径中。
如果您无权修改群集上的文件,可以尝试其他方法。使用--jars
将所有log4j2 jar添加到spark-submit参数。根据{{3}},所有这些库将被添加到驱动程序和执行程序的类路径中,因此它应该以相同的方式工作。
答案 2 :(得分:0)
尝试使用--driver-java-options
${SPARK_HOME}/bin/spark-submit \
--class my.app.JobDriver \
--verbose \
--master 'local[*]' \
--files "log4j2.xml" \
--driver-java-options "-Dlog4j.configuration=log4j2.xml" \
--jars log4j-api-2.8.jar,log4j-core-2.8.jar,log4j-1.2-api-2.8.jar \
myapp-SNAPSHOT.jar
答案 3 :(得分:0)
如果在您自己的一个依赖项中使用了log4j2,那么很容易将所有配置文件配对并使用一个或两个高级记录器IF的编程配置,并且仅在找不到配置文件时。< / p>
下面的代码可以解决问题。只需将记录器命名为顶级记录器即可。
private static boolean configured = false;
private static void buildLog()
{
try
{
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
System.out.println("Configuration found at "+ctx.getConfiguration().toString());
if(ctx.getConfiguration().toString().contains(".config.DefaultConfiguration"))
{
System.out.println("\n\n\nNo log4j2 config available. Configuring programmatically\n\n");
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory
.newConfigurationBuilder();
builder.setStatusLevel(Level.ERROR);
builder.setConfigurationName("IkodaLogBuilder");
AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE")
.addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute("pattern",
"%d [%t] %msg%n%throwable"));
builder.add(appenderBuilder);
LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout").addAttribute("pattern",
"%d [%t] %-5level: %msg%n");
appenderBuilder = builder.newAppender("file", "File").addAttribute("fileName", "./logs/ikoda.log")
.add(layoutBuilder);
builder.add(appenderBuilder);
builder.add(builder.newLogger("ikoda", Level.DEBUG)
.add(builder.newAppenderRef("file"))
.add(builder.newAppenderRef("Stdout"))
.addAttribute("additivity", false));
builder.add(builder.newRootLogger(Level.DEBUG)
.add(builder.newAppenderRef("file"))
.add(builder.newAppenderRef("Stdout")));
((org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false)).start(builder.build());
ctx.updateLoggers();
}
else
{
System.out.println("Configuration file found.");
}
configured=true;
}
catch(Exception e)
{
System.out.println("\n\n\n\nFAILED TO CONFIGURE LOG4J2"+e.getMessage());
configured=true;
}
}