9

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.

Yang
  • 7,712
  • 9
  • 48
  • 65
city
  • 2,036
  • 2
  • 32
  • 40
  • Does [Akka documentation](http://doc.akka.io/docs/akka/2.2.3/scala/logging.html) 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 Nov 07 '13 at 03:21
  • @S.R.I, I know that. But now I need do it by myself. It is my course project... – city Nov 07 '13 at 15:58

3 Answers3

25

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.

Björn Antonsson
  • 1,019
  • 6
  • 9
10

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

sourcedelica
  • 23,940
  • 7
  • 66
  • 74
2
  1. use stackable modificator abstract override for stackable call of receive method.
  2. use new feature of Akka: event-sourced actor system (docs here).
Yuriy
  • 2,772
  • 15
  • 22