如何记录日志
创建一个 LoggingAdapter 并使用它的 error, warning, info, 或 debug 方法, 如下例:
import akka.event.Logging
class MyActor extends Actor {
val log = Logging(context.system, this)
override def preStart() = {
log.debug("Starting")
}
override def preRestart(reason: Throwable, message: Option[Any]) {
log.error(reason, "Restarting due to [{}] when processing [{}]",
reason.getMessage, message.getOrElse(""))
}
def receive = {
case "test" ? log.info("Received test")
case x ? log.warning("Received unknown message: {}", x)
}
}
为了方便你可以向actor中混入 log 成员, 而不是象上例一下定义它.
class MyActor extends Actor with akka.actor.ActorLogging {
...
}
Logging 的第二个参数是这个日志通道的源. 这个源对象以下面的规则转换成字符串:
如果它是Actor或ActorRef,则使用它的路径
如果是String,就使用它自己
如果是类,则使用它的simpleName
其它的类型,而且当前作用域中又没有隐式的 LogSource[T] 实例则会导致编译错误.
日志消息可以包含参数占位符 {}, 如果该日志级别被打开,则占位符会被替换。如果给出的参数数量多过 占位符的数量,则在日志语句的结尾将被追加一个警告 (i.e. 在同一级别的同一行)。你可以传入一个Java数组来为多个占位符提供数据:
val args = Array("The", "brown", "fox", "jumps", 42)
system.log.debug("five parameters: {}, {}, {}, {}, {}", args)
日志源的 Java Class 也会被包含在生成的 LogEvent中. 如果是简单的字符串,它会被替换成一个 “标志” 类 akka.event.DummyClassForStringSources 以便对这种情况作特殊处理,例如 在SLF4j事件监听器中会使用字符串而不是类名来查找要用到的日志记录器实例。
辅助的日志选项
Akka 为非常底层的debug提供了一组配置选项,这些主要是为akka的开发者所用,而非普通用户。
你一定要将日志级别设为 DEBUG 来使用这些选项:
akka {
loglevel = DEBUG
}
下面这个配置选项在你想知道Akka装载了哪些配置设置时非常有用:
akka {
# 在actor系统启动时以INFO级别记录完整的配置
# 当你不确定使用的是哪个配置时有用
log-config-on-start = on
}
如果你希望记录所有被使用akka.event.LoggingReceive的Actor处理的用户级消息的细节:
akka {
debug {
# 打开 LoggingReceive 功能, 以DEBUG级别记录所有接收到的消息
receive = on
}
}
如果你希望记录Actor所处理的所有自动接收的消息的细节:
akka {
debug {
# 为所有的 AutoReceiveMessages(Kill, PoisonPill 之类) 打开DEBUG日志
autoreceive = on
}
}
如果你希望记录Actor的所有生命周期变化 (重启,死亡等 ) 的细节:
akka {
debug {
# 打开actor生命周期变化的DEBUG日志
lifecycle = on
}
}
如果你希望记录所有继承了LoggingFSM的FSM actor的事件、状态转换和计时器的细节:
akka {
debug {
# 打开所有 LoggingFSMs 事件、状态转换和计时器的DEBUG日志
fsm = on
}
}
如果你希望监控对 ActorSystem.eventStream 的订阅/取消订阅:
akka {
debug {
# 打开eventStream上订阅关系变化的DEBUG日志
event-stream = on
}
}
辅助的远程日志选项
如果你希望以DEBUG级别查看所有远程发送的消息: (这些日志是被传输层发送时所记录,而非actor)
akka {
remote {
# 如果打开这个选项,Akka将以DEBUG级别记录所有发出的消息, 不打开则不记录
log-sent-messages = on
}
}
如果你希望以DEBUG级别查看接收到的所有远程消息: (这些日志是被传输层接收时所记录,而非actor)
akka {
remote {
# 如果打开这个选项,Akka将以DEBUG级别记录所有接收到的消息, 不打开则不记录
log-received-messages = on
}
}
同时参阅 TestKit 的日志选项: 跟踪Actor调用.
将日志源转换为字符串和类
在运行时将源对象转换成要插入 LogEvent 的源字符串和类的规则是使用隐式参数的方式实现的, 因此是可配置的: 只需要创建你自己的 LogSource[T] 实例并将它放在创建logger的作用域中即可。
import akka.event.LogSource
import akka.actor.ActorSystem
object MyType {
implicit val logSource: LogSource[AnyRef] = new LogSource[AnyRef] {
def genString(o: AnyRef): String = o.getClass.getName
override def getClazz(o: AnyRef): Class[_] = o.getClass
}
}
class MyType(system: ActorSystem) {
import MyType._
import akka.event.Logging
val log = Logging(system, this)
}
这个例子创建了一个日志源来模拟Java logger的传统用法,该日志源使用原对象的类名作为日志类别。 在这里加入对 getClazz 的重写只是为了作说明,因为它精确地包含了缺省行为。
Note
你也可以先创建字符串然后将它作为日志源传入,但要知道这时 LogEvent 中的 Class[_] 将是 akka.event.DummyClassForStringSources.
SLF4J 事件监听器对这种情况会特殊处理 (使用实际的字符串来查找logger实例而不是类名), 你在实现自己的日志适配器时可能也会这么做。
事件处理器
日志记录是通过一个事件总线异步地完成的. 你可以配置要为哪些事件处理器订阅日志事件。通过 Configuration 中的event-handlers 。 你还可以在这里定义日志级别。
akka {
# 在启动时注册的事件处理器 (Logging$DefaultLogger 记录日志到标准输出)
event-handlers = ["akka.event.Logging$DefaultLogger"]
# 可选: ERROR, WARNING, INFO, DEBUG
loglevel = "DEBUG"
}
缺省会注册一个事件处理器,它将日志记录到标准输出. 在生产系统中不建议使用它。 在 ‘akka-slf4j’ 模块中还有一个 SLF4J 事件处理器。
创建监听器的示例:
import akka.event.Logging.InitializeLogger
import akka.event.Logging.LoggerInitialized
import akka.event.Logging.Error
import akka.event.Logging.Warning
import akka.event.Logging.Info
import akka.event.Logging.Debug
class MyEventListener extends Actor {
def receive = {
case InitializeLogger(_) ? sender ! LoggerInitialized
case Error(cause, logSource, logClass, message) ? // ...
case Warning(logSource, logClass, message) ? // ...
case Info(logSource, logClass, message) ? // ...
case Debug(logSource, logClass, message) ? // ...
}
}
SLF4J
Akka 为 SL4FJ提供了一个事件处理器. 它在 ‘akka-slf4j.jar’ 模块中. 它的唯一依赖是 slf4j-api 包. 在运行时,你还需要一个 SLF4J 后端, 我们推荐 Logback:
lazy val logback = "ch.qos.logback" % "logback-classic" % "1.0.0" % "runtime"
你需要打开 Configuration 的‘event-handlers’中的 Slf4jEventHandler。 你还可以在这里定义事件总线的日志级别。更细粒度的日志级别可以在SLF4j后端的配置(例如:logback.xml)中定义。
akka {
event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
loglevel = "DEBUG"
}
SLF4J 为每个日志事件选择日志记录器是基于创建LoggingAdapter时的日志源的 Class[_], 如果日志源是一个字符串,那么就使用这个串 (i.e. LoggerFactory.getLogger(c: Class[_]) 用于前者而 LoggerFactory.getLogger(s: String) 用于后者).
注意
如果创建LoggingAdapteractor时向工厂方法提供了一个ActorSystem,那么该Acotr系统的名字 将被加在 字符串 日志源的后面。 如果不希望这样,只要象下面这样传一个 LoggingBus :
val log = Logging(system.eventStream, "my.nice.string")
日志线程与MDC中的Akka源
日志的记录是异步的,完成日志记录的线程被保存在 Mapped Diagnostic Context (MDC) 的 sourceThread 属性里. 在 Logback 的模式配置中线程名可以通过 %X{sourceThread} 指定:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ISO8601} %-5level %logger{36} %X{sourceThread} - %msg%n</pattern>
</encoder>
</appender>
Note
在应用程序的非Akka的部分也建议使用MDC的 sourceThread 使得这个值在日志里保持一致。
另一个有用的工具是 Akka 的创建logger实例时会捕捉 actor 的地址, 这意味着可以访问到整个actor实例的身份信息来将日志信息与其它信息进行关联(例如:路由的成员)。 这个信息保存在MDC的 akkaSource属性中:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
</encoder>
</appender>
要了解这个属性所包括的内容(也适用于非
actor)的细节见 如何记录日志.
分享到:
相关推荐
JActor 是一个 Java 的 Actor 模式的实现,经过测试在 i5 CPU 上可支持每秒钟发送超过亿条消息,可能是目前最快的。这相当于是 Scala 的 Actor 的纯 Java 版本。 示例代码: // Create a mailbox factory with a ...
actor开源代码分享,actor开源代码分享,actor开源代码分享,actor开源代码分享
NULL 博文链接:https://zhwj184.iteye.com/blog/1613351
基于Akka的高性能可伸缩的JAVA网络游戏服务器。...如果有逻辑需要更改其他Actor的数据需要是用sendActorMessage方法。ExampleServer为服务器事例项目。 当前结构完成单服务器部分。集群部分还有待调整。
测试跨语言角色之间的通信 此回购包含实验,以确定在ray运行时内部实现跨语言... 在每个EchoClient远程java actor上调用addEcho方法,并将RayEcho python句柄传递给这些方法。 EchoClient Java参与者将使用python句
Diaco是Java的分布式actor框架。 它简化了旨在成为轻量级且快速解决方案的并发编程。 它的设计在很大程度上受到影响。 快速开始 Diaco可以用作现有项目的依赖项。 在这种情况下,必须将存储库添加到目标项目的pom....
libGDX的Actor类的最基本实现,同时应该使用Stage对Actor的子类进行draw(),这点需注意。而其实,Actor只需要对draw()方法进行覆盖即可,然后使用Stage进行加载,而Actor的其他方法只是为了丰富Actor子类的方法...
ga_server 基于protoactor框架的actor游戏服务器
除非为了在Actor Core.vi的中不断监视或输送某些值,当然此时就需要解决如何在适当时刻停止while循环的问题了。本例中未予以演示,但可以从本例的全局变量的g_bool中得到参考,while循环到底应该在何时被结束。
标签:typesafe、akka、actor、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,...
它最初是一个使 Java Akka 更容易使用的库。 然而,通过它的演变,很明显 API 的客户端根本不需要依赖 Akka; 他们的需求可以通过对任何演员系统提供者通用的演员 API 来满足。 这是相当重要的警告,Javactor 公开...
标签:typesafe、akka、actor、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
玩具演员框架 这对做真实的工作没有什么用,只是一个尝试一些事情的场所。 该API就像我认为的Orbit一样,尽管我只尝试了几分钟。
使用NuGet软件包管理器控制台进行安装:PM> Install-Package Proto.Actor源代码这是Proto Actor的.NET存储库。 Proto.Actor超快速,分布式,跨平台的actor。 使用NuGet软件包管理器控制台进行安装:PM> Install-...
LabVIEW Actor 框架 示例文件 通过示例,详细介绍了Actor的使用。
C++ Actor Framework 简单样例。主要针对了 消息发送,接收,处理。event_base-actor,blocking_acotr的使用。
主要介绍了JAVA Actor模型的的相关资料,文中讲解非常细致,帮助大家更好的学习JAVA,感兴趣的朋友可以了解下
1.2 为什么在游戏中使用Java 1.3 为Java准备系统 1.3.1 安装Java SDK 1.3.2 编译和运行Java程序 1.3.3 使用命令行 1.3.4 使用集成开发环境(IDE) 1.3.5 关于Java2文档的说明 1.4 总结 第2章 预备:学习Java2 API 2.1 ...
通过Actor模型使用响应式消息传输模式,可编写出具有高性能、高响应性、高可伸缩性和高韧性的并发应用程序。《响应式架构:消息模式Actor实现与Scala、Akka应用集成》由10章构成,详细介绍了使用Actor模型中的响应式...
Actor Framework 实际应用