2015-08-01 12 views
8

Mam trywialny projekt iskry w Scali i chciałbym użyć logback, ale iskop/hadoop wydaje się wymuszać na mnie log4j.Spark wymuszając log4j

  1. Wydaje się to sprzeczne z moim rozumieniem celu slf4j; to jest to nie jest niedopatrzenie w iskrze/hadoop?

  2. Czy muszę zrezygnować z logowania i użyć log4j, czy istnieje obejście zastępcze ?

W build.sbt Próbowałem wykluczeń ...

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

... ale to powoduje wyjątek ...

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

Czy chcesz, aby wszystkie rejestratory iskier używały Twojego. A może tylko Twoja aplikacja? –

+0

Sądzę, że oczekiwałem, że wszystkie logowania będą dotyczyć mojego wybranego wiązania slf4j, w tym przypadku logback. Bez wykluczenia slf4j ostrzega mnie, że znajduje zarówno log4j (od iskry), jak i logback (ode mnie). Na tym etapie działam lokalnie. – Pengin

+1

Potrzebujesz log4j i log4j-over-slf4j, aby uczynić go "działającym". Jednak będziesz musiał zmierzyć się z innymi problemami podczas uruchamiania iskiernika. Zobacz: http://stackoverflow.com/questions/31790944/best-way-to-send-apache-spark-loggin-to-redis-logstash-on-an-amazon-emr-cluster –

Odpowiedz

5

I napotkał ten sam wyjątek jak ty . Myślę, że powinieneś także dodać log4j-over-slf4j jako zależność oprócz wyłączenia log4j i slf4j-log4j12. Mi to pasuje.

log4j-over-slf4j to kropla zamiennika dla log4j, ponieważ zapewnia dokładnie takie samo api jak log4j i faktycznie kieruje wszystkie wywołania log4j do slf4j, które z kolei kieruje wszystko do logu pod spodem. https://www.slf4j.org/legacy.html zawiera objaśnienia szczegółowe.