`
bljoohe
  • 浏览: 1705 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

(java)如何用Actor记录日志

阅读更多
如何记录日志
创建一个 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)的细节见 如何记录日志.
分享到:
评论

相关推荐

    AkkaJava PDF Doc

    Akka提供了事件总线用于在Actor之间广播事件,日志服务用于记录运行时信息,调度器用于安排任务执行,而持续时间(Duration)用于表示时间间隔。 **扩展和微内核** Akka允许开发者通过扩展API来增加新的功能和组件...

    Akka Java文档

    介绍如何使用 Java 8 的 Lambda 表达式来定义 Actor 的行为。 ##### 4.2 容错性 (Java with Lambda Support) 展示如何在使用 Lambda 表达式的 Actor 中处理故障。 ##### 4.3 FSM (Java with Lambda Support) 使用 ...

    AKKA (java) 精讲

    这部分介绍了 Akka 提供的一些实用工具,包括事件总线、日志记录、调度器等。 #### 8. How To: Common Patterns 这部分介绍了常见的 Akka 编程模式,包括: - 定期调度消息。 - 构建单次使用的 Actor 树。 - 使用...

    Java类库大全

    9. **日志记录**:Log4j、SLF4J和Logback是常见的日志记录库,它们提供了灵活的日志级别控制和输出格式定制。 10. **图形用户界面**:JavaFX和Swing是Java内置的GUI库,而JavaFX提供了更现代和丰富的UI组件。对于更...

    一些Github 上超实用的 Java 项目集合(开源项目集合)

    至于日志,Log4j和SLF4J都是广泛采用的日志框架,它们提供了灵活的日志记录策略,可以根据需要配置输出级别和格式。 这个"awesome-java-master"压缩包可能包含了上述提到的以及更多其他Java开源项目。通过研究这些...

    aktrs:Java actor库-开源

    它通过TCP套接字(和SSL套接字),参与者配置文件,控制台和可调日志记录来提供远程参与者。 它的API易于使用,其核心是用几行源代码编写的。 aktrs需要Java 1.5或更高版本,没有其他依赖关系,可以根据其GNU通用...

    深度解析java游戏服务器开发.zip

    JUnit和Mockito等工具可以帮助编写测试代码,而日志系统如Log4j则用于记录运行时信息,方便问题定位。 通过以上分析,我们可以看到,Java游戏服务器开发是一项涵盖广泛的技术工作。从网络通信到并发处理,再到...

    akka java document

    - **日志记录:** 如何在 Akka 中记录日志。 - **日志框架:** 如何集成常用的日志框架。 **7.3 调度器** - **调度器概念:** 介绍 Akka 的调度器功能。 - **定时任务:** 如何使用调度器来安排定时任务。 **7.4 ...

    AkkaJava.pdf

    工具章节中,Akka文档将涵盖EventBus、日志记录、调度器、时长、Akka扩展、持久性邮箱以及微核心等实用功能。 在“如何做:常见模式”这一章节中,文档将提供关于如何在Akka中实现常见模式的指导,例如调度周期性...

    30种java技术框架-方案架构图汇总.zip

    14. **Logback**:日志记录框架,性能优于Log4j,提供了灵活的日志配置和输出策略。 15. **JUnit**:Java单元测试框架,用于编写和运行可重复的测试,是敏捷开发的重要工具。 16. **TestNG**:功能丰富的测试框架...

    基于Java的JActor的文件持久化组件 JFile.zip

    这在数据库、缓存服务、日志记录等场景中至关重要。JFile可能包含了特定的API,使得开发者能够方便地实现文件的序列化和反序列化,从而进行高效的数据持久化。 在laforge49-JFile-df391d8这个文件中,我们可以期待...

    play-java-chatroom-example.zip_java_play_speedf8d_untilbdm

    【描述】"Play java chat room example"进一步确认了我们正在处理一个用Java语言和Play框架实现的聊天室应用程序的实例。这个例子可能包含了一个基本的架构,展示了如何在实时环境中处理用户交互、消息传递以及多...

    Java写的游戏服务器.zip

    可能使用线程或者Actor模型来异步处理这些逻辑。 3. **数据库交互**:存储和检索玩家信息、游戏进度等数据。Java有丰富的ORM框架,如Hibernate和MyBatis,可以简化数据库操作。 4. **状态管理**:维护游戏世界的...

    基于java的JActor的文件持久化组件 JFile.zip

    JActor是Java中一个用于实现并发处理的框架,它利用了actor模型的概念,每个actor都是独立的执行单元,有自己的状态并且通过消息传递进行通信。在这种背景下,"基于java的JActor的文件持久化组件 JFile.zip" 提供了...

    某平台java爬虫代码

    - **日志记录**: 记录爬虫运行过程中的信息,方便调试和问题追踪。 - **数据模型**: 定义电影信息的Java类,如Movie、Actor、Director等。 - **测试代码**: 对爬虫功能进行单元测试,确保数据提取的准确性。 此外,...

    Akka开发库文档

    - 描述了Akka的工具类,例如事件总线、日志记录器、调度器、持续时间管理、扩展模块、微内核以及断路器等。 - 提供了如何实现常见模式的指导,例如调度周期性消息。 为了满足要求,以下是对上述知识点更详细的解释...

    actor-apps:初始聊天和菜单选项

    演员客户端应用此仓库包含所有客户端应用程序源代码。...jvm :actor-common-base的扩展,添加了一些特定于jvm的实现(联网和日志记录) actor-js :GWT应用程序,用于构建用于与Actor API一起使用的Java脚本库a

    JActor的文件持久化组件 JFile_JActor_java_

    - **日志记录**:JFile会记录每次操作的日志,用于故障恢复和审计。 - **检查点机制**:定期保存当前状态作为检查点,以便在系统异常时可以从最近的检查点快速恢复。 在分析JFile_JActor_java_的源码时,开发者可以...

    Akka说明文档

    - **Logging**:提供了日志记录的功能,便于调试和运维。 - **EventBus**:事件总线,用于在不同组件之间传递事件。 - **Scheduler**:定时任务调度器,可以定期执行指定的任务。 - **Futures**:异步计算模型,可以...

    Akka Scala 学习高清原版pdf

    - 日志记录提供了强大的日志管理功能。 - Scheduler可以安排任务在actor系统中按预定计划运行。 - Duration用于表示时间间隔。 - Akka扩展,如微内核和断路器,提供了额外的高级特性。 6. 常见模式和实践: - ...

Global site tag (gtag.js) - Google Analytics