【问题标题】:Logging received messages in Akka在 Akka 中记录收到的消息
【发布时间】:2015-12-14 21:22:18
【问题描述】:

我在 Java 中使用 Akka 演员,并试图打开消息记录。基于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

我应该怎么做才能记录这些消息?

【问题讨论】:

    标签: java akka


    【解决方案1】:

    您提到的设置,akka.actor.debug.receive 仅适用于演员的 Scala API。这是因为在 Scala 中如何调用 receive PartialFunction 的性质。在 Scala 中,actor 框架首先使用isDefinedAt 查看是否为输入消息定义了case。如果为消息定义了case,那么它将在PartialFunction 上调用apply 并处理消息。但是如果消息没有被处理,那么apply 就不会被调用。为了记录所有消息,无论是否处理,Scala 框架需要一个工具来包装PartialFunction 评估以记录无论如何,该工具是这个设置加上包装receive PartialFunctionLoggingReceive 实用程序并使用该设置来控制日志记录。

    在 Java 世界中,您没有这种“检查然后应用”语义。所有消息都命中onReceive 方法,在那里,您的instanceof 处理将确定消息是否被处理。正因为如此,在委派给子类方法进行实际消息评估和处理之前,定义一个实现 onReceive 并相应记录(可能基于相同设置)的抽象 Java 基类非常容易。

    【讨论】:

    • 看起来邮件通过aroundReceive,而不是onReceive。但除此之外,这是可行的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2015-09-04
    相关资源
    最近更新 更多