Akka Logging外面的演员

Bra*_*ord 44 logging scala akka

我有一个打电话的Akka演员MyObject.foo().MyObject不是演员.如何设置登录?使用Actor很简单,因为我可以混合使用ActorLogging.在MyObject中,我无权访问context.system.我是否akka.event.Logging使用AkkaSystem()创建一个,然后隐含LogSource的内容?

Tom*_*icz 26

实际上我会将Akka日志重定向到并直接在所有不相关的类中使用此API.首先将其添加到您的配置中:

akka {
    event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
    loglevel = "DEBUG"
}
Run Code Online (Sandbox Code Playgroud)

然后选择一些SLF4J实现,我建议.在你的演员中继续使用ActorLogging特质.在其他类中,只需依赖SLF4J API - 甚至更好 - 尝试围绕SLF4J的slf4s外观.

提示:在Logback中尝试以下日志记录模式:

<pattern>%d{HH:mm:ss.SSS} | %-5level | %thread | %X{akkaSource} | %logger{1} | %m%n%rEx</pattern>
Run Code Online (Sandbox Code Playgroud)

%X{akkaSource}将打印演员路径时可用(就像标准的日志记录).

  • @AntonyStubbs:不,如果你想从异步日志中受益,你必须向某个actor发送消息 - 并使用该actor记录消息...... (2认同)

bns*_*ith 20

使用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!")
Run Code Online (Sandbox Code Playgroud)

这似乎是统一应用程序日志记录的简单解决方案.

  • 这个答案并没有解决实际问题.您创建一个完整的ActorSystem只是为了在类中进行一些日志记录.如果您在其他地方需要它,您是否要创建另一个ActorSystem?也可以通过你第一次创建的ActorSystem的引用. (7认同)

Mat*_*ler 9

正如已经提到的那样,你在演员系统中为非演员日志记录的选项而被宠坏了.我将尝试提供一组启发式方法来帮助您确定如何为您的工作路由日志记录.

  1. 您可以在actor和非actor代码中直接使用记录器(log4j 1.x,logback,log4j 2.x).
    • 这会将您的代码紧密地耦合到记录器实现.如果它是你的代码,不在其他地方使用,这很好,但如果你正在建立一个图书馆或打算开源你的工作,那就不好了.
    • 如果你这样做,你就不会从演员系统中获益.记录呼叫可能会成为阻塞呼叫,具体取决于您设置记录器的方式,因此,无论何时性能或对背压的控制都是重要问题,这都是不受欢迎的.
    • 因为actor代码(以及它可以使用的服务)可以在许多不同的线程上运行,所以一些传统的日志记录活动(例如使用线程局部MDC(映射诊断上下文))可能导致奇怪的竞争条件和上下文切换从消息输出的日志从演员传递给演员.在发送消息之前将MDC交换到消息之类的活动可能变得有必要保留actor和非actor代码之间的上下文.
    • 要捕获诸如死信和监督之类的ActorSystem事件,您可能需要编写日志记录适配器并在application.conf中指定它.这些非常简单.
  2. 您可以将SLF4J外观用于actor和非actor日志记录.
    • 您不再需要使用记录器,而且您的服务不再与akka耦合.这是便携性的最佳选择.
    • 您可以从日志框架继承阻塞行为.
    • 您可能必须管理MDC
    • 要捕获ActorSystem事件,您需要在application.conf中指定"akka.event.slf4j.Slf4jLogger".
    • 您需要在类路径中包含一个slf4j提供程序jar,以将slf4j日志事件路由到您选择的记录器
  3. 您可以在Actor和非演员代码中使用Akka的Logging作为您的外观
    • 你没有加入记录器i​​mpl或slf4j,但你加入了akka的版本.这可能是您的系统的要求,但对于库,它可能会降低可移植性.
    • 你必须传递一个actor系统作为记录器的"总线".与工作演员系统的紧密耦合进一步降低了可移植性.(在应用程序中,我通常使用隐式或全局ActorSystem构建一个LoggingViaActorSystem特性,这样可以更容易地在代码中处理此问题,但不能跨越依赖关系).
    • 即使您的记录器不支持,也可以保证无阻塞的异步日志记录.记录的因果一致性可能是由于使用单个消费者邮箱.但是,内存安全和背压不是(我相信Akka日志记录使用无界邮箱) -
    • 有一些选项,例如使用DiagnosticLoggingAdapter可以避免在工作从actor转移到actor时管理自己的MDC的复杂性.即使非参与者代码改变了这些MDC,也应该保持一致性.
    • 在内存不足崩溃期间,日志记录可能不可用,并且对默认调度程序上的线程不足很敏感
    • 除非您对登录标准输出感兴趣,否则您需要在application.conf中指定所选的记录器

欢迎您根据需要混合和匹配上述行为以满足您的要求.例如,您可以选择绑定到SLF4J以用于库,并将Akka日志记录用于其他所有内容.请注意,混合阻塞和非阻塞日志记录可能会导致竞争条件,其原因(通过actor记录的异步)在其效果后记录(直接记录同步).


Ant*_*bbs 8

我现在决定简单地通过DI构造函数注入(Guice)传递我的中央记录系统.在我定期进行日志记录的类中(异步性非常重要),我将注入的ActorSystem调用

this.log = akka.event.Logging.getLogger(actorSystem, this);
Run Code Online (Sandbox Code Playgroud)

在类构造函数中.

  • 对于不希望增长对象以保存此类引用的情况,您可能更喜欢的另一个选项是向需要执行日志记录的方法添加第二个参数列表`(implicit log:LoggingAdapter)`. (4认同)