4

I'm using Akka FSM with Scala and logging using the log member of the FSM trait, i.e. an instance of akka.event.Logging.

When calling context.system.shutdown() to shutdown the actor system when the application wants to terminate normally, it seems that latest log messages are sometimes lost (and not printed out at all).

Is there way to guarantee that all log messages are always printed out before the system is shutdown?

akisaarinen
  • 111
  • 1
  • 5
  • How would you know that all messages are printed? – Viktor Klang Jun 19 '12 at 19:05
  • I am not sure what you mean. From my application's point of view, it does not need any notification when all log messages are printed. In other words, I do not need to 'know' that all messages are printed. I just want to see them printed. And in my current case, I can verify that a message which I have logged is not printed out. Does this clear things at all? – akisaarinen Jun 20 '12 at 07:32
  • My point was, Akka cannot possibly know when all messages are processed. – Viktor Klang Jun 20 '12 at 08:43
  • I understand that. And because the logging subsystem is also implemented using Akka messages, there is no way of guaranteeing the outputting of all log messages? If that's true, would there be any way of making it at least very very likely that all pending log messages are flushed, given that I am using a single-node actor system without the distribution features? – akisaarinen Jun 20 '12 at 09:22
  • If you tell me how to do it, I can take a stab at it. The easiest solution for you is probably to have your logger shut the system down and not your actor. – Viktor Klang Jun 20 '12 at 09:27
  • I do not have a suggestion at the moment, I haven't looked into Akka logging internals much yet. I will get back to you in case I come up with anything. Regarding your suggestion of letting the logger shut down the system, could you provide any pointers how to accomplish this? Right now I am calling context.system.shutdown() in my actor, and am using the default actors from Akka to do the logging (only outputting to stdout). What would be the easiest way to inject shutdowning to the logger? – akisaarinen Jun 20 '12 at 13:21
  • Listen for the log message that you know is last, and then shut down? – Viktor Klang Jun 20 '12 at 13:32
  • No, he’d have to listen for the printing of the last message by the logger (because the problem quite certainly is that the log event is in the logger’s mailbox when the system shuts down). Easiest would be to implement your own logger (look at akka.event.Logging.DefaultLogger to see just how easy that is) and have that one call context.system.shutdown() upon reception of some message. Then send that message to actorSelection("/system/log*") when you want to shut down. – Roland Kuhn Jun 20 '12 at 14:41
  • Thanks Roland, that sounds like a plan. I'll try that. – akisaarinen Jun 20 '12 at 15:21

1 Answers1

1

Based on Dr. Kuhn's suggestion, here is a sample TerminatingLogger. I put mine in the error() channel so that it won't fall into the string comparison often, but you can obviously put it wherever you want.

class TerminatingLogger extends Actor with StdOutLogger {
    override def receive: Receive = {
      case InitializeLogger(_) ⇒ sender() ! LoggerInitialized
      case error : akka.event.Logging.Error if error.message.toString().equals("TERMINATE_SYSTEM") =>
      {
        context.system.shutdown()
      }
      case event: LogEvent     ⇒ 
      {
       print(event) 
      }
    }
  }

Then just configure it in your application.conf file

akka {
  loggers = [com.namespace.TerminatingLogger]
}
fbl
  • 2,840
  • 3
  • 33
  • 41