Использование SLF4J в Акке - PullRequest
0 голосов
/ 24 ноября 2018

Я следовал Ведение журнала Doc для использования SLF4J с logback в моем приложении Akka.Но у меня проблема при входе в неакторные классы: я не могу записать MDC (например, sourceActorSystem) в неакторные классы с помощью регистратора SLF4J.Вот мое простое приложение:

1- pom.xml:

<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-slf4j_2.12</artifactId>
    <version>2.5.18</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

2- application.conf:

akka {
  loggers = ["akka.event.slf4j.Slf4jLogger"]
  loglevel = "DEBUG"
  logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
}

3- logback.xml, которое использует sourceThread, akkaSource и sourceActorSystem MDC:

<configuration scan="true" scanPeriod="30 seconds" > 
    <contextName>akka-sample</contextName>
    <jmxConfigurator />
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss} %-5level [%contextName] [%X{sourceThread}] [%X{sourceActorSystem}] [%X{akkaSource}] %logger{40} -| %msg %rEx%n</pattern>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

4- UserActor: класс актера, регистрирующий DiagnosticLoggingAdapter:

public class UserActor extends AbstractActor {
    DiagnosticLoggingAdapter logger = Logging.getLogger(this);
    Handler handler = new Handler(); // non-actor class

    public static Props props() {
        return Props.create(UserActor.class, UserActor::new);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
            .match(UserMessages.Register.class, register -> {
                logger.info("{} received", register);
                // Delegate message-handling to a non-actor class
                handler.onRegister(register, getSelf(), getSender());
            })
            .build();
    }
}

5- Handler: неакторный класс, который регистрируется с помощью SLF4J logger.Каждый экземпляр UserActor имеет поле Handler для делегирования ему обработки сообщений:

public class Handler {
    org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());

    public void onRegister(UserMessages.Register register, ActorRef self, ActorRef sender) {
        logger.info("Handling {}", register);
        sender.tell(new UserMessages.Registered(), self);
    }
}

6 - Простое приложение:

public class Application {
    public static void main(String [] args) throws InterruptedException {
        ActorSystem system = null;
        try {
            system = ActorSystem.create("akka-system");
            ActorRef user1 = system.actorOf(UserActor.props(), "user-1");
            ActorRef user2 = system.actorOf(UserActor.props(), "user-2");
            user2.tell(UserMessages.Register.builder().userId("1").build(), user1);
            Thread.sleep(2000);
        } finally {
            system.terminate();
        }
    }
}

Вывод журнала:

18:07:30 INFO  [akka-sample] [] [] [] akka.event.slf4j.Slf4jLogger -| Slf4jLogger started 
18:07:30 INFO  [akka-sample] [akka-system-akka.actor.default-dispatcher-4] [akka-system] [akka://akka-system/user/user-2] x.y.akka.UserActor -| UserMessages.Register(userId=1) received 
18:07:30 INFO  [akka-sample] [] [] [] x.y.akka.Handler -| Handling UserMessages.Register(userId=1) 

Как видите, только вход в систему UserActor (класс актера) имеет sourceThread, akkaSource и sourceActorSystem MDC;Но в Handler (без актера) они пусты.Также, если я изменю akka.event.DiagnosticLoggingAdapter в UserActor на org.slf4j.Logger, эти MDC станут пустыми.

...