Reputation: 3608
I am using Akka actors from within Java and am trying to turn on the logging of messages. Based on the documentation, it seems that setting akka.actor.debug.receive
should cause all messages to be logged. The following test should log the "hello"
message being sent and received.
import akka.actor.AbstractLoggingActor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.japi.pf.ReceiveBuilder;
import akka.pattern.Patterns;
import akka.testkit.JavaTestKit;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import io.scalac.amqp.Persistent$;
import org.hamcrest.CoreMatchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import scala.concurrent.duration.Duration$;
public class LoggingTest
{
@Before
public void createActorSystem() {
Config config = ConfigFactory.parseString(
"akka: {" +
" actor: { debug: { receive: on, fsm: on, unhandled: on, autoreceive: on }}," +
" log-config-on-start: off" +
" ,loglevel: DEBUG" +
" ,stdout-loglevel: DEBUG" +
"}");
system = ActorSystem.create(getClass().getSimpleName(),
config);
}
@After
public void shutdownActorSystem() {
JavaTestKit.shutdownActorSystem(system);
}
private static class TestActorWithLogging extends AbstractLoggingActor {
public TestActorWithLogging(ActorRef target) {
receive(ReceiveBuilder.
matchAny(msg -> target.tell(msg, self())).
build());
}
}
@Test
public void messageLogging() {
new JavaTestKit(system) {{
system.log().debug("Running messageLogging");
ActorRef actor = system.actorOf(Props.create(TestActorWithLogging.class, getRef()));
send(actor, "hello");
expectMsgEquals("hello");
}};
}
private ActorSystem system;
}
When I run the test, I get the following output. Lifecycle messages are logged, so the config is being applied. However, I don't see any log statements about the "hello"
message.
Running LoggingTest
[DEBUG] [09/17/2015 16:49:48.893] [main] [EventStream] StandardOutLogger started
[DEBUG] [09/17/2015 16:49:49.020] [main] [EventStream(akka://LoggingTest)] logger log1-Logging$DefaultLogger started
[DEBUG] [09/17/2015 16:49:49.020] [main] [EventStream(akka://LoggingTest)] logger log1-Logging$DefaultLogger started
[DEBUG] [09/17/2015 16:49:49.023] [main] [EventStream(akka://LoggingTest)] Default Loggers started
[DEBUG] [09/17/2015 16:49:49.023] [main] [EventStream(akka://LoggingTest)] Default Loggers started
[DEBUG] [09/17/2015 16:49:49.050] [main] [akka.actor.ActorSystemImpl(LoggingTest)] Running messageLogging
[DEBUG] [09/17/2015 16:49:49.103] [LoggingTest-akka.actor.default-dispatcher-4] [akka://LoggingTest/system] received AutoReceiveMessage Envelope(Terminated(Actor[akka://LoggingTest/user]),Actor[akka://LoggingTest/user])
[DEBUG] [09/17/2015 16:49:49.104] [LoggingTest-akka.actor.default-dispatcher-4] [EventStream] shutting down: StandardOutLogger started
[DEBUG] [09/17/2015 16:49:49.104] [LoggingTest-akka.actor.default-dispatcher-4] [EventStream] shutting down: StandardOutLogger started
[DEBUG] [09/17/2015 16:49:49.106] [LoggingTest-akka.actor.default-dispatcher-4] [EventStream] all default loggers stopped
[DEBUG] [09/17/2015 16:49:49.111] [LoggingTest-akka.actor.default-dispatcher-3] [akka://LoggingTest/] received AutoReceiveMessage Envelope(Terminated(Actor[akka://LoggingTest/system]),Actor[akka://LoggingTest/system])
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.33 sec
What should I be doing to log the messages?
Upvotes: 4
Views: 1678
Reputation: 35463
The setting you mention, akka.actor.debug.receive
is only for the Scala API for actors. This is because of the nature of how the receive
PartialFunction
is invoked in Scala. In Scala, the actor framework first sees if there is a case
defined for the input message using isDefinedAt
. If there is a case
defined for the message, then it will call apply
on the PartialFunction
and the message is handled. But if the message is not handled, then apply
is not called. In order to log all messages, handled or otherwise, the Scala framework needed a facility to wrap around the PartialFunction
evaluation to log regardless, and that facility is this setting plus the LoggingReceive
utility that wraps the receive
PartialFunction
and uses that setting to control logging.
In the Java world, you don't have this "check then apply" semantic. All messages hit the onReceive
method and in there, your instanceof
handling will determine if the message is handled or not. Because of this, it's pretty easy to define an abstract base Java class that implements onReceive
and logs accordingly (possibly based on that same setting) before delegating to a subclass method for actual message evaluation and handling.
Upvotes: 4