2015-08-01 11 views
8

Ho un progetto spark ban in Scala e vorrei usare logback, ma spark/hadoop sembra forzare log4j su di me.Spark forcing log4j

  1. Questo sembra in disaccordo con la mia comprensione dello scopo di slf4j; è non è una svista in scintilla/hadoop?

  2. Devo rinunciare al logback e usare log4j, o c'è una soluzione alternativa ?

In build.sbt ho provato esclusioni ...

"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" 

... ma questo si traduce in un'eccezione ...

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

Vuoi che tutta la registrazione di scintille utilizzi la tua. O solo la tua app? –

+0

Suppongo che mi aspettavo che tutto il logging vada alla mia associazione slf4j scelta, in questo caso il logback. Senza l'esclusione slf4j mi avverte che trova sia log4j (dalla scintilla) che il logback (da me). Sto lavorando localmente in questa fase. – Pengin

+1

È necessario log4j e log4j-over-slf4j per renderlo "funzionante". Tuttavia, si incontreranno altri problemi durante l'esecuzione di spark-submit. Vedi: http://stackoverflow.com/questions/31790944/best-way-to-send-apache-spark-loggin-to-redis-logstash-on-an-amazon-emr-cluster –

risposta

5

ho incontrato la stessa eccezione come la tua . Penso che dovresti anche aggiungere log4j-over-slf4j come dipendenza oltre a escludere log4j e slf4j-log4j12. Per me funziona.

log4j-over-slf4j è una sostituzione in sostituzione di log4j poiché fornisce esattamente la stessa API di log4j e inoltra effettivamente tutte le chiamate a log4j a slf4j che a sua volta indirizza tutto al framework di registro sottostante. https://www.slf4j.org/legacy.html fornisce spiegazioni dettagliate.