9
votes

Now, I am asked to add logging function in akka's actor.

When a message is received, before it is handled, this message should be written into log. And before a message is sent out, this message should be logged first.

I think I should override the receive and send functions in Actor. Suppose I create a trait actorlog which extends Actor. And class myActor extends actorlog. But in myActor, I need to override receive function (it seems it causes problems here). So I am confused what I should do.

PS. I know akka provides logging. But now I need implement this function by myself.

3
Does Akka documentation have no information that can help you? You don't need to override receive just for logging purposes, though it has its uses in other scenarios.S.R.I
@S.R.I, I know that. But now I need do it by myself. It is my course project...city

3 Answers

25
votes

There is a utility to get logging of the received messages in Akka. It's briefly mentioned in the logging documentation. Basically you wrap your receive function in it like this:

def receive = LoggingReceive {
                // your normal receive here
              }

And then you enable it in your config with:

akka.actor.debug.receive=on

The information will be logged at debug level.

10
votes

Besides the other answers here, another approach is to use orElse to prepend a partial function to your receive. In that partial function, put the logging in isDefinedAt so it gets called on every message.

For example:

trait ReceiveLogger {
  this: Actor with ActorLogging =>

  def logMessage: Receive = new Receive {
    def isDefinedAt(x: Any) = {
      log.debug(s"Got a $x")
      false
    }
    def apply(x: Any) = throw new UnsupportedOperationException  
  }
}  

class MyActor extends Actor with ActorLogging with ReceiveLogger {
  def receive: Receive = logMessage orElse {
     case ...
  }
}

Using orElse is a general approach for composing receive behavior. In most cases I am composing things like this:

def otherBehavior: Receive = {
  case OtherMessage => ...
}

class MyActor extends Actor {
  def receive = otherBehavior orElse {
    case ...
  }
} 

A good example of the stackable traits approach can be seen in this presentation: http://www.slideshare.net/EvanChan2/akka-inproductionpnw-scala2013

2
votes
  1. use stackable modificator abstract override for stackable call of receive method.
  2. use new feature of Akka: event-sourced actor system (docs here).