Akka Logging外面的演员

时间:2012-04-14 21:48:52

标签: scala logging akka

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

6 个答案:

答案 0 :(得分:25)

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

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

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

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

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

%X{akkaSource}将在可用时打印actor路径(就像标准日志记录一样)。

答案 1 :(得分:21)

使用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!")

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

答案 2 :(得分:9)

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

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

答案 3 :(得分:8)

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

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

在类构造函数中。

答案 4 :(得分:1)

根据latest (currently version 2.6.9) logging documentation,使用从org.slf4j.LoggerFactory获得的记录器非常好,实际上,这是推荐的登录参与者外部的方法。我在此复制准确的措辞。

使用通过以下方式检索到的记录器是完全可以的 org.slf4j.LoggerFactory,但随后的日志记录事件将不包括 akkaSource MDC值。 这是登录时的推荐方式 演员以外的人,包括来自Future回调的记录。

此后,我还将根据示例提供一个代码段

val log = LoggerFactory.getLogger("com.mypackage.MyObject")

Future {
  // do something
  "result"
}.onComplete {
  case Success(result) => log.info("Success!: {}", result)
  case Failure(exc)    => log.error("Failure!", exc)
}

为了通过记录日志来最大程度地降低性能损失,可以为SLF4J后端配置异步附加程序。建议使用Logback作为日志记录后端。

dependencies {
  compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
}

为生产配置logback.xml的起点:

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>myapp.log</file>
    <immediateFlush>false</immediateFlush>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>myapp_%d{yyyy-MM-dd}.log</fileNamePattern>
    </rollingPolicy>
    <encoder>
        <pattern>[%date{ISO8601}] [%level] [%logger] [%marker] [%thread] - %msg MDC: {%mdc}%n</pattern>
    </encoder>
</appender>

<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
    <queueSize>8192</queueSize>
    <neverBlock>true</neverBlock>
    <appender-ref ref="FILE" />
</appender>

<root level="INFO">
    <appender-ref ref="ASYNC"/>
</root>

日志记录通常表示IO和锁定,这可能会减慢 代码同步执行的操作。

上面显示的配置是AKKA日志记录文档提供的配置。该文档提供了更多信息,可以在here

中找到

答案 5 :(得分:0)

只需创建您自己的记录器:

private val log = LoggerFactory.getLogger(YourClass.getClass)