Я следовал Ведение журнала 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 станут пустыми.