在 Akka 中记录收到的消息
Logging received messages in Akka
我正在使用 Java 中的 Akka actor 并尝试打开消息日志记录。根据 documentation,似乎设置 akka.actor.debug.receive
应该会导致记录所有消息。以下测试应记录正在发送和接收的 "hello"
消息。
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;
}
当我 运行 测试时,我得到以下输出。记录了生命周期消息,因此正在应用配置。但是,我没有看到任何关于 "hello"
消息的日志语句。
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
我应该如何记录消息?
您提到的设置,akka.actor.debug.receive
仅适用于 Scala API 演员。这是因为在 Scala 中调用 receive
PartialFunction
的方式的性质。在 Scala 中,actor 框架首先使用 isDefinedAt
查看是否为输入消息定义了 case
。如果为消息定义了 case
,那么它将在 PartialFunction
上调用 apply
并处理消息。但是如果消息没有被处理,那么 apply
就不会被调用。为了记录所有消息,处理或其他方式,Scala 框架需要一个工具来包装 PartialFunction
评估以记录,而该工具是此设置加上包装 [=] 的 LoggingReceive
实用程序11=] PartialFunction
并使用该设置来控制日志记录。
在 Java 世界中,您没有这种 "check then apply" 语义。所有消息都命中 onReceive
方法,在那里,您的 instanceof
处理将决定消息是否被处理。因此,很容易定义一个抽象基础 Java class 来实现 onReceive
并在委托给子 class 之前相应地记录(可能基于相同的设置)实际消息评估和处理的方法。
我正在使用 Java 中的 Akka actor 并尝试打开消息日志记录。根据 documentation,似乎设置 akka.actor.debug.receive
应该会导致记录所有消息。以下测试应记录正在发送和接收的 "hello"
消息。
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;
}
当我 运行 测试时,我得到以下输出。记录了生命周期消息,因此正在应用配置。但是,我没有看到任何关于 "hello"
消息的日志语句。
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
我应该如何记录消息?
您提到的设置,akka.actor.debug.receive
仅适用于 Scala API 演员。这是因为在 Scala 中调用 receive
PartialFunction
的方式的性质。在 Scala 中,actor 框架首先使用 isDefinedAt
查看是否为输入消息定义了 case
。如果为消息定义了 case
,那么它将在 PartialFunction
上调用 apply
并处理消息。但是如果消息没有被处理,那么 apply
就不会被调用。为了记录所有消息,处理或其他方式,Scala 框架需要一个工具来包装 PartialFunction
评估以记录,而该工具是此设置加上包装 [=] 的 LoggingReceive
实用程序11=] PartialFunction
并使用该设置来控制日志记录。
在 Java 世界中,您没有这种 "check then apply" 语义。所有消息都命中 onReceive
方法,在那里,您的 instanceof
处理将决定消息是否被处理。因此,很容易定义一个抽象基础 Java class 来实现 onReceive
并在委托给子 class 之前相应地记录(可能基于相同的设置)实际消息评估和处理的方法。