web-dev-qa-db-ja.com

Actor外のAkkaのログ

MyObject.foo()を呼び出すAkkaアクターがあります。 MyObjectはアクターではありません。どのようにログを設定するのですか? ActorLoggingをミックスインできるので、Actorを使用すると簡単です。 MyObjectでは、context.systemにアクセスできません。 AkkaSystem()を使用してakka.event.Loggingを作成してから、LogSourceを暗黙的に作成しますか?

45
Bradford

実際、私はAkkaのログを slf4j にリダイレクトし、このAPIを関連のないすべてのクラスで直接使用します。まず、これを構成に追加します。

akka {
    event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
    loglevel = "DEBUG"
}

次に、いくつかのSLF4J実装を選択します。 logback をお勧めします。あなたのアクターではActorLoggingトレイトを使い続けます。他のクラスでは、単にSLF4J APIに依存している-またはさらに優れている-SLF4Jの周りの slf4s facadeを試してみてください。

ヒント:Logbackで次のロギングパターンを試してください。

<pattern>%d{HH:mm:ss.SSS} | %-5level | %thread | %X{akkaSource} | %logger{1} | %m%n%rEx</pattern>

%X{akkaSource}は、(標準のロギングと同様に)使用可能な場合にアクターパスを出力します。

27

Akka 2.2.1を使用して、これを自分のアプリに入れて、俳優の外でログを取得することができました。

import akka.event.Logging
val system = ActorSystem("HelloSystem", ConfigFactory.load.getConfig("akka"))
val log = Logging.getLogger(system, this)
log.info("Hi!")

これは、アプリケーションのロギングを統合するためのより簡単なソリューションのようです。

20
bnsmith

すでに述べたように、アクターシステム内での非アクターロギングのオプションは台無しになっています。作業のログをどのようにルーティングする必要があるかを判断するのに役立つ一連のヒューリスティックを提供しようと試みます。

  1. ロガー(log4j 1.x、logback、log4j 2.x)を、アクターコードと非アクターコードの両方で直接使用できます。
    • これにより、コードがロガー実装に密接に結合されます。これはあなたのコードであり、他の場所で使用されない場合は問題ありませんが、ライブラリを構築している場合や、作品をオープンソース化する場合は問題ありません。
    • これを行うと、アクターシステムのメリットは得られません。ロガーの設定方法によっては、ロギングコールがブロッキングコールになる可能性があるため、パフォーマンスやバックプレッシャの制御が重要な懸念事項である場合、これは避けられます。
    • アクターコードは(それが使用できるサービスとともに)多くの異なるスレッドで動作できるため、threadlocal MDC(マップされた診断コンテキスト)の使用などのいくつかの従来のロギングアクティビティは、奇妙な競合状態と、俳優から俳優に移ります。メッセージを送信する前にMDCをメッセージにスワップするなどのアクティビティは、アクターコードと非アクターコード間のコンテキストを保持するために必要になる場合があります。
    • デッドレターや監督などのActorSystemイベントをキャプチャするには、ロギングアダプターを作成してapplication.confで指定する必要がある場合があります。これらは非常に簡単です。
  2. SLF4Jファサードを俳優と非俳優の両方のロギングに使用できます。
    • あなたはもはやロガーimplに結合されていません、そしてあなたのサービスはakkaに結合されていません。これは、移植性のための最良のオプションです。
    • ログフレームワークからブロッキング動作を継承できます。
    • MDCを管理する必要がある場合があります
    • ActorSystemイベントをキャプチャするには、application.confで「akka.event.slf4j.Slf4jLogger」を指定する必要があります
    • 選択したロガーにslf4jログイベントをルーティングするには、クラスパスにslf4jプロバイダーjarを含める必要があります
  3. AkkaのLoggingを、アクターコードと非アクターコードの両方でファサードとして使用できます
    • ロガーimpl OR to slf4jに接続されていませんが、akkaのバージョンに接続されています。これはおそらくシステムの要件ですが、ライブラリの場合、移植性が低下する可能性があります。
    • ロガーの「バス」として機能するには、アクターシステムを迂回する必要があります。動作しているアクターシステムに密結合すると、移植性がさらに低下します。 (通常、アプリ内で、暗黙的またはグローバルなActorSystemを使用して少しのLoggingViaActorSystemトレイトを構築します。これにより、コード内でこれを簡単に処理できるようになりますが、依存関係全体では処理できません)。
    • ロガーが非ブロッキング非同期ロギングをサポートしていない場合でも、それらが保証されています。ロギングの因果関係の一貫性は、単一のコンシューマメールボックスの使用が原因である可能性があります。ただし、メモリの安全性とバックプレッシャはそうではありません(Akkaのロギングでは無制限のメールボックスを使用すると思います)-
    • アクターからアクターに作業が渡されるときに独自のMDCを管理する複雑さを回避するために、 DiagnosticLoggingAdapter の使用などのオプションがあります。非アクターコードがこれらのMDCを変更する場合でも、一貫性を維持する必要があります。
    • ロギングは、メモリ不足のクラッシュ時には利用できない可能性が高く、デフォルトのディスパッチャーでのスレッド不足に敏感です。
    • 標準出力へのログに関心がない場合は、application.confで選択したロガーを指定する必要があります。

要件を満たすために、必要に応じて上記の動作を組み合わせることもできます。たとえば、ライブラリのSLF4Jにバインドし、他のすべてにAkkaロギングを使用することを選択できます。ブロッキングとノンブロッキングのログを混在させると、原因(アクター経由でログに記録された非同期)が影響(ログに直接記録された同期)の後にログに記録される競合状態が発生する可能性があることに注意してください。

9

これで、DIコンストラクターインジェクション(Guice)を介して中央のログシステムを渡すだけで解決しました。そして、定期的にロギングを行うクラス(非同期性が重要な場合)では、注入されたActorSystemを取得して、

this.log = akka.event.Logging.getLogger(actorSystem, this);

クラスのコンストラクタで。

8
Antony Stubbs

独自のロガーを作成するだけです。

private val log = LoggerFactory.getLogger(YourClass.getClass)
0
Mohsen Kashi