2014-09-26 47 views
3

对于可以相当简洁地表达的Actor,为了添加日志命令,必须添加块({...})令人沮丧。我想在处理消息之前记录我的内部状态,然后处理消息 - 这可能吗?如何在接收中记录内部演员的状态?

def receive = { 
    // I want to log here instead and remove the non-critical logs from below 
    // e.g. log.debug(s"Received $message") 
    //  log.debug(s"Internal state is $subscriptions") 
    case RegisterChannel(name, owner) => { 
     getChannel(name) match { 
     case Some(deadChannel: DeadChannel) => { 
      subscriptions += (RealChannel(name, Server(owner)) -> subscriptions(deadChannel)) 
      subscriptions -= deadChannel 
      context.watch(owner) 
      log.debug(s"Replaced $deadChannel with a real channel $channels") 
     } 
     case Some(realChannel: RealChannel) => 
      log.error(s"Refusing to use RegisterChannel($name, $owner) due to $realChannel") 
     case None => { 
      subscriptions += (RealChannel(name, Server(owner)) -> Vector()) 
      context.watch(owner) 
      log.debug(s"Registered a new channel $channels") 
     } 
     } 
    } 

    case Terminated(dead) => { 
     getRole(dead) match { 
     case Some(client: Client) => // Remove subscriptions 
      log.debug(s"Received Client Terminated($dead) $client") 
      subscriptionsFor(client).foreach { subscription => 
      subscriptions += (subscription._1 -> subscription._2.filterNot(c => c == client)) 
      } 
     case Some(server: Server) => { // Remove any channels 
      log.debug(s"Received Server Terminated($dead) $server") 
      channelsBy(server).foreach { realChannel => 
      subscriptions += (DeadChannel(realChannel.name) -> subscriptions(realChannel)) 
      subscriptions -= realChannel 
      } 
     } 
     case None => 
      log.debug(s"Received Terminated($dead) but no channel is registered") 
     } 
    } 
    // I want to log here as well, to see what effect the message had 
    // e.g. log.debug(s"Finished $message") 
    //  log.debug(s"Internal state is now $subscriptions") 
} 

我不知道这是否是一个阿卡特定或斯卡拉模式匹配的具体问题,所以我都标记

编辑:尝试的@aepurniet的答案后,我不知道如何解决编译器错误。收到需要返回PartialFunction[Any,Unit],但是当比赛不是唯一的项目在=> {...}它似乎是回到Any=>AnyRef

// Compiler error because msg=>{...} is not proper type 
def receive = msg => { 
    log.info(s"some log") 

    msg match { 
     case RegisterChannel(name, owner) => { 
     getChannel(name) match { 
    <snip> 

回答

5

received = { case ... }实际上是received = msg => msg match { case ... }简写。您可以重写receive = msg => { log.info(..); msg match { case ... } }您可能需要另外指定类型。

+0

这看起来如此接近。当我尝试时,我得到了你预测的类型问题,但我无法弄清楚如何解决这个问题。我已经编辑了这个最后一个小问题的帖子,如果你再看一下,会非常感激 – Hamy 2014-09-26 17:49:46

3

akka.event.LoggingReceive,您可以使用这样的:

def receive = LoggingReceive { 
    case ... 
} 

然后,设置akka.actor.debug.receiveon,这将记录(以DEBUG)收到的所有消息,以及他们是否被处理或没有。

请参阅Akka官方文档中的Tracing Actor Invocations部分。

对于附加的状态记录,你可以做同样的事情到LoggingReceive

def withStateLogging(handler: Receive): Receive = { 
    case msg if handler.isDefinedAt(msg) ⇒ 
    log.debug("before actual receive") 
    log.debug(s"received: $msg") 
    log.debug(s"state: $state") 
    handler(msg) 
    log.debug("after actual receive") 
    log.debug(s"finished: $msg") 
    log.debug(s"state: $state") 
} 

def receive = withStateLogging { 
    case ... 
}