2015-08-01 7 views
8

Ich habe triviale Funken Projekt in Scala und möchte Logback verwenden, aber Spark/Hadoop scheint Log4j auf mich zwingen.Spark Forcing log4j

  1. Dies scheint im Widerspruch zu meinem Verständnis des Zwecks von slf4j; ist es kein Versehen in Funken/Hadoop?

  2. Muss ich auf logback verzichten und log4j verwenden, oder gibt es eine Problemumgehung?

In build.sbt Ich habe versucht, Ausschlüsse ...

"org.apache.spark" %% "spark-core" % "1.4.1" excludeAll(
    ExclusionRule(name = "log4j"), 
    ExclusionRule(name = "slf4j-log4j12") 
), 
"org.slf4j" % "slf4j-api" % "1.7.12", 
"ch.qos.logback" % "logback-core" % "1.1.3", 
"ch.qos.logback" % "logback-classic" % "1.1.3" 

... aber dies führt zu einer Ausnahme ...

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Level 
    at org.apache.hadoop.mapred.JobConf.<clinit>(JobConf.java:354) 
    at java.lang.Class.forName0(Native Method) 
    at java.lang.Class.forName(Class.java:344) 
    at org.apache.hadoop.conf.Configuration.getClassByNameOrNull(Configuration.java:1659) 
    at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:91) 
    at org.apache.hadoop.util.ReflectionUtils.setConf(ReflectionUtils.java:75) 
    at org.apache.hadoop.util.ReflectionUtils.newInstance(ReflectionUtils.java:133) 
    at org.apache.hadoop.security.Groups.<init>(Groups.java:55) 
    at org.apache.hadoop.security.Groups.getUserToGroupsMappingService(Groups.java:182) 
    at org.apache.hadoop.security.UserGroupInformation.initialize(UserGroupInformation.java:235) 
    at org.apache.hadoop.security.UserGroupInformation.ensureInitialized(UserGroupInformation.java:214) 
    at org.apache.hadoop.security.UserGroupInformation.getLoginUser(UserGroupInformation.java:669) 
    at org.apache.hadoop.security.UserGroupInformation.getCurrentUser(UserGroupInformation.java:571) 
    at org.apache.spark.util.Utils$$anonfun$getCurrentUserName$1.apply(Utils.scala:2162) 
    at org.apache.spark.util.Utils$$anonfun$getCurrentUserName$1.apply(Utils.scala:2162) 
    at scala.Option.getOrElse(Option.scala:120) 
    at org.apache.spark.util.Utils$.getCurrentUserName(Utils.scala:2162) 
    at org.apache.spark.SparkContext.<init>(SparkContext.scala:301) 
    at spike.HelloSpark$.main(HelloSpark.scala:19) 
    at spike.HelloSpark.main(HelloSpark.scala) 
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Level 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:372) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
    ... 20 more 
+0

Möchten Sie, dass die Funkenerfassung Ihre verwendet. Oder nur deine App? –

+0

Ich vermutete, dass ich erwartet habe, dass die Protokollierung zu meiner ausgewählten slf4j-Bindung geht, in diesem Fall Logback. Ohne den Ausschluss warnt mich slf4j, dass es sowohl log4j (von funke) als auch logback (von mir) findet. Ich laufe in diesem Stadium lokal. – Pengin

+1

Sie benötigen log4j und log4j-over-slf4j, damit es "funktioniert". Sie werden jedoch andere Probleme haben, wenn Sie Spark-submit ausführen. Siehe: http://stackoverflow.com/questions/31790944/best-way-to-send-apache-spark-loggin-to-redis-logstash-on-an-amazon-emr-cluster –

Antwort

5

traf ich die gleiche Ausnahme wie Sie . Ich denke, Sie sollten auch log4j-over-slf4j als Abhängigkeit hinzufügen außer log4j und slf4j-log4j12. Für mich geht das.

log4j-over-slf4j ist ein Ersatz für log4j, da es exakt die gleiche API wie log4j bereitstellt und alle Aufrufe von log4j an slf4j weiterleitet, die wiederum alles an das darunterliegende Protokollframework weiterleitet. https://www.slf4j.org/legacy.html gibt detaillierte Erklärungen.