ログ

データ プロセッシング ライブラリでは 、ログコンテキストでエンリッチ化されたログを提供するためにコンテキストロギングが使用されます。ログコンテキストは、ログメッセージが生成された時点での計算コンテキストに関する追加情報を提供するキーと値のペアのセットです。

context-logging SLF4J をベースにしています。

context-logging データ プロセッシング ライブラリには依存せず、プロジェクトのスタンドアロンコンポーネントとして使用できます。

ログコンテキストおよびコンテキストアウェアロガー

ログコンテキストは、動的にバインド されたスレッドローカルのキー / 値のペアのセットで、ContextAwareLoggerによって配信された各ログメッセージに自動的に追加されます。

次のスニペットは、ログコンテキストで拡張されたログメッセージの例です。

2020/10/13 22:33:54.393 INFO    Main$: Final assessment: Assessment(true,0.0) // Task=main deltaset=mapValues13 catalog=output layer=assessment partition=assessment spark.stageId=59 spark.partitionId=16 spark.attemptNumber=0 spark.taskAttemptId=400

ログコンテキストは、次 LogContext.withChildのコード スニペットに示すように、制御フローがスコープから外れるまで新しいバインディングが配置されている実行ブロックを指定することで、任意に拡張できます。

Scala
Java
import com.here.platform.pipeline.logging.{ContextLogging, LogContext}

object LogContextExample extends ContextLogging {
  // extending `ContextLogging` is roughly equivalent to:
  // protected val logger = new ContextAwareLogger(getClass)

  def someLoggingMethod(): Unit = logger.info("some info message")

  def main(arg: Array[String]): Unit = {
    // => some info message
    someLoggingMethod()

    LogContext.withChild("key", "value") {
      // => some info message // key=value
      someLoggingMethod()

      LogContext.withChild("another-key", "another-value") {
        // => some info message // key=value another-key=another-value
        someLoggingMethod()
      }

      // => some info message // key=value
      someLoggingMethod()
    }
  }
}
import com.here.platform.pipeline.logging.LogContext;
import com.here.platform.pipeline.logging.java.ContextAwareLogger;

public class LogContextExample {

  static ContextAwareLogger logger = new ContextAwareLogger(LogContextExample.class);

  public static void someLoggingMethod() {
    logger.info("some info message");
  }

  public static void main(String[] args) {

    // => some info message
    someLoggingMethod();

    LogContext.withChild("key", "value", () -> {
      // => some info message // key=value
      someLoggingMethod();

      LogContext.withChild("another-key", "another-value", () -> {
        // => some info message // key=value another-key=another-value
        someLoggingMethod();
      });

      // => some info message // key=value
      someLoggingMethod();
    });
  }
}

データ プロセッシング ライブラリでコンテキストをログに記録します

データ プロセッシング ライブラリは、フレームワークに渡されたほとんどのユーザー定義関数に関するログコンテキストに、現在のドライバータスク、コンパイルフェーズ、および処理中のパーティションに関する情報を入力します。 したがって ContextAwareLogger 、ログコンテキストを自分で補強しない場合でも、デバッグ情報のこの有用なソースを失わないように、他のログソリューションよりもを常に優先する必要があります。

関数コンパイラーでコンテキストをログに記録します

各機能コンパイラメソッド (mappingFn, resolveFn, compileInFn, compileOutFn) では、ログコンテキストに少なくともメソッドの名前、処理中のパーティションKey、現在の Spark ステージ、およびステージ内のタスクに関する情報が含まれています。

Deltaset Transformations でコンテキストをログに記録します

DeltaSet すべての変換で、ログコンテキストに id は、の、 DeltaSet 現在の Spark ステージおよびステージ内のタスクに関する情報が含まれます。 マッピングの変換には、処理中のキーも含まれます。

サンプリング

ログ記録は貴重な情報源ですが、 1 回のロガー呼び出しで生成されるすべてのメッセージに関心がない場合があります。また、同じログメッセージのインスタンスが多すぎると(データが異なる場合もあります)、ログが散乱し、追加情報をほとんど提供せずにコストに影響が出ることがあります。

このような場合は 、サンプリングロガーを使用できます。サンプリングロガーは、サンプリング方式に基づいて、すべてのロガー呼び出しのサブセットを出力する、特別なコンテキストアウェアロガーです。

Scala
Java
import com.here.platform.pipeline.logging.{ContextLogging, SamplingLogger}

object SamplingLoggingExample extends ContextLogging {
  // extending `ContextLogging` is roughly equivalent to:
  // protected val logger = new ContextAwareLogger(getClass)

  val samplingLogger: SamplingLogger = logger.oneEvery(3)

  def main(arg: Array[String]): Unit = {
    // => Without sampling: 1
    // => Every 3: 1
    // => Once: 1
    // => Without sampling: 2
    // => Without sampling: 3
    // => Without sampling: 4
    // => [3 times] Every 3: 4
    // => Without sampling: 5
    // => Exiting...
    // => [flush] Every 3: 5
    // => [flush] [4 times] Once: 2

    (1 to 5).foreach { count =>
      logger.info(s"Without sampling: $count")
      samplingLogger.info(s"Every 3: $count")
      // a sampling strategy can be specified for single logger calls
      logger.limit(1).warn(s"Once: $count")
    }

    logger.info("Exiting...")
  }
}
import com.here.platform.pipeline.logging.java.ContextAwareLogger;
import com.here.platform.pipeline.logging.java.SamplingLogger;

public class SamplingLoggingExample {

  static ContextAwareLogger logger = new ContextAwareLogger(SamplingLoggingExample.class);
  static SamplingLogger samplingLogger = logger.oneEvery(3);

  public static void main(String[] args) {
    // => Without sampling: 1
    // => Every 3: 1
    // => Once: 1
    // => Without sampling: 2
    // => Without sampling: 3
    // => Without sampling: 4
    // => [3 times] Every 3: 4
    // => Without sampling: 5
    // => Exiting...
    // => [flush] Every 3: 5
    // => [flush] [4 times] Once: 2

    for (int i = 1; i <= 5; ++i) {
      logger.info("Without sampling: {}", i);
      samplingLogger.info("Every 3: {}", i);
      // a sampling strategy can be specified for single logger calls
      logger.limit(1).warn("Once: {}", i);
    }

    logger.info("Exiting...");
  }
}

」に一致する結果は 件です

    」に一致する結果はありません