web-dev-qa-db-ja.com

Apache Spark Scala内でログイン

Apacheでコードを実行するときに追加データを記録できるソリューションを探していますSpark実行中に発生する可能性のあるいくつかの問題を後で調査するのに役立つノード。例com.typesafe.scalalogging.LazyLoggingは、Apache Sparkなどの分散環境でログインスタンスをシリアル化できないため失敗します。

私はこの問題を調査しましたが、今のところ私が見つけた解決策はorg.Apache.spark.Loggingこのような特性:

class SparkExample with Logging {
  val someRDD = ...
  someRDD.map {
    rddElement => logInfo(s"$rddElement will be processed.")
    doSomething(rddElement)
  }
}

ただし、ログ特性はApache Sparkのマークが付けられているため、@DeveloperApiおよびクラスのドキュメントには次のように記載されています。

これは今後のリリースで変更または削除される可能性があります。

私は疑問に思っています-それらは私が使用できる既知のロギングソリューションであり、RDPがApache Sparkノードで実行されたときにデータをログに記録できるようにしますか?

@ Later Edit:以下のコメントの一部は、Log4Jの使用を提案しています。 Log4Jを使用しようとしましたが、Scalaクラス(およびScalaオブジェクトではない)からのロガーを使用すると、まだ問題が発生します。コード:

import org.Apache.log4j.Logger
import org.Apache.spark._

object Main {
 def main(args: Array[String]) {
  new LoggingTestWithRDD().doTest()
 }
}

class LoggingTestWithRDD extends Serializable {

  val log = Logger.getLogger(getClass.getName)

  def doTest(): Unit = {
   val conf = new SparkConf().setMaster("local[4]").setAppName("LogTest")
   val spark = new SparkContext(conf)

   val someRdd = spark.parallelize(List(1, 2, 3))
   someRdd.map {
     element =>
       log.info(s"$element will be processed")
       element + 1
    }
   spark.stop()
 }

}

私が見ている例外は次のとおりです:

スレッド「メイン」での例外org.Apache.spark.SparkException:タスクはシリアル化できません->原因:Java.io.NotSerializableException:org.Apache.log4j.Logger

51
Bogdan N

で提案されているAkhilのソリューションを使用できます
https://www.mail-archive.com/[email protected]/msg29010.html 。私は自分で使用しましたが、動作します。

Akhil Das Mon、2015年5月25日08:20:40 -0700
この方法で試してください:

object Holder extends Serializable {      
   @transient lazy val log = Logger.getLogger(getClass.getName)    
}


val someRdd = spark.parallelize(List(1, 2, 3)).foreach { element =>
   Holder.log.info(element)
}
45
florins

Log4j 2.xを使用します。コアロガーはシリアル化可能になりました。問題が解決しました。

Jiraのディスカッション: https://issues.Apache.org/jira/browse/LOG4J2-801

"org.Apache.logging.log4j" % "log4j-api" % "2.x.x"

"org.Apache.logging.log4j" % "log4j-core" % "2.x.x"

"org.Apache.logging.log4j" %% "log4j-api-scala" % "2.x.x"
4
Ryan Stack
val log = Logger.getLogger(getClass.getName),

「ログ」を使用してログを書き込むことができます。また、ロガーのプロパティを変更する必要がある場合は、/ confフォルダーにlog4j.propertiesが必要です。デフォルトでは、その場所にテンプレートがあります。

1
Venkata Karthik

これは古い投稿ですが、多くの苦労の末に得た作業ソリューションを提供したいと思います。

Rdd.map関数内でrddの内容を印刷したいが、Task Not Serializalable Error。これはscalaを拡張している静的オブジェクトJava.io.Serializable

import org.Apache.log4j.Level

object MyClass extends Serializable{

val log = org.Apache.log4j.LogManager.getLogger("name of my spark log")

log.setLevel(Level.INFO)

def main(args:Array[String])
{

rdd.map(t=>

//Using object's logger here

val log =MyClass.log

log.INFO("count"+rdd.count)
)
}

}
0
khushbu kanojia

mapfilter、またはその他のRDD関数の前後に何らかのコードを実行する必要がある場合は、mapPartitionを使用してみてください。明示的に渡されました。

例:

val log = ??? // this gets captured and produced serialization error
rdd.map { x =>
  log.info(x)
  x+1
}

になる:

rdd.mapPartition { it =>
  val log = ??? // this is freshly initialized in worker nodes
  it.map { x =>
    log.info(x)
    x + 1
  }
}

すべての基本的なRDD関数は、常にmapPartitionで実装されます。

パーティショナーを明示的に処理し、失うことのないようにしてください。Scaladoc、preservesPartitioningパラメーターを参照してください。これはパフォーマンスにとって重要です。

0
ragazzojp

ここに私の解決策があります:

すべてのspark jobの基本クラスでSLF4j(Log4jバインディングを使用)を使用しています。次のようなものがあります。

import org.slf4j.LoggerFactory
val LOG = LoggerFactory.getLogger(getClass) 

分散機能コードでLOGを使用する場所の直前に、ロガー参照をローカル定数にコピーします。

val LOG = this.LOG

それは私のために働いた!

0
Thamme Gowda