aroundReceive 方法中的 Actor MDC 上下文
Actor MDC context in aroundReceive method
我有一个 Java Akka 应用程序,我想根据消息中的信息为每个消息处理设置一个单独的 MDC 上下文,例如,我有以下所有消息的基本接口:
public interface IdMessage {
String getId();
}
此外,我还有以下所有演员的基本演员:
public class BaseActor extends AbstractActor {
private final DiagnosticLoggingAdapter log = Logging.apply(this);
@Override
public void aroundReceive(PartialFunction<Object, BoxedUnit> receive, Object msg) {
if (msg instanceof IdMessage) {
final Map<String, Object> originalMDC = log.getMDC();
log.setMDC(ImmutableMap.of("id", ((IdMessage) msg).getId()));
try {
super.aroundReceive(receive, msg);
} finally {
if (originalMDC != null) {
log.setMDC(originalMDC);
} else {
log.clearMDC();
}
}
} else {
super.aroundReceive(receive, msg);
}
}
}
以及实际的 actor 实现:
public class SomeActor extends BaseActor {
SomeActor() {
receive(ReceiveBuilder
.match(SomeMessage.class, message -> {
...
}
}
}
我想确保 SomeActor#receive()
中的所有日志条目都将在 BaseActor
中设置 MDC 上下文。为了使这项工作 SomeActor#receice()
需要在与 BaseActor#aroundReceive()
方法相同的线程中执行。
我没有找到关于 aroundReceive
行为的任何信息 - 是否总是在与实际 receive
方法相同的线程中执行?根据我的测试,它总是在同一个线程中执行。
我能够自己找出正确的实施方式,并希望分享它以防有人遇到同样的问题。
aroundReceive
将在与 receive
相同的线程中执行,因此这是设置 MDC 上下文的正确位置。
我使用 org.slf4j.MDC
来设置 MDC 上下文,这里是完整代码:
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import com.google.common.collect.ImmutableMap;
import akka.actor.AbstractActor;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
public class BaseActor extends AbstractActor {
private final Logger log = LoggerFactory.getLogger(BaseActor.class);
@Override
public void aroundReceive(PartialFunction<Object, BoxedUnit> receive, Object msg) {
if (msg instanceof IdMessage) {
final Map<String, Object> originalMDC = log.getMDC();
MDC.setContextMap(ImmutableMap.of("id", ((IdMessage) msg).getId()));
try {
super.aroundReceive(receive, msg);
} finally {
if (originalMDC != null) {
MDC.setContextMap(originalMDC);
} else {
MDC.clear();
}
}
} else {
super.aroundReceive(receive, msg);
}
}
}
通过 BaseActor
的实现,receive
中的所有日志条目都使用适当的 MDC 上下文进行记录。可以在这个有趣的博客 post(使用 Scala 实现)中找到更多信息。
注意:我无法使用 Akka DiagnosticLoggingAdapter
实现相同的功能,尽管它有设置 MDC 上下文的方法。
我有一个 Java Akka 应用程序,我想根据消息中的信息为每个消息处理设置一个单独的 MDC 上下文,例如,我有以下所有消息的基本接口:
public interface IdMessage {
String getId();
}
此外,我还有以下所有演员的基本演员:
public class BaseActor extends AbstractActor {
private final DiagnosticLoggingAdapter log = Logging.apply(this);
@Override
public void aroundReceive(PartialFunction<Object, BoxedUnit> receive, Object msg) {
if (msg instanceof IdMessage) {
final Map<String, Object> originalMDC = log.getMDC();
log.setMDC(ImmutableMap.of("id", ((IdMessage) msg).getId()));
try {
super.aroundReceive(receive, msg);
} finally {
if (originalMDC != null) {
log.setMDC(originalMDC);
} else {
log.clearMDC();
}
}
} else {
super.aroundReceive(receive, msg);
}
}
}
以及实际的 actor 实现:
public class SomeActor extends BaseActor {
SomeActor() {
receive(ReceiveBuilder
.match(SomeMessage.class, message -> {
...
}
}
}
我想确保 SomeActor#receive()
中的所有日志条目都将在 BaseActor
中设置 MDC 上下文。为了使这项工作 SomeActor#receice()
需要在与 BaseActor#aroundReceive()
方法相同的线程中执行。
我没有找到关于 aroundReceive
行为的任何信息 - 是否总是在与实际 receive
方法相同的线程中执行?根据我的测试,它总是在同一个线程中执行。
我能够自己找出正确的实施方式,并希望分享它以防有人遇到同样的问题。
aroundReceive
将在与 receive
相同的线程中执行,因此这是设置 MDC 上下文的正确位置。
我使用 org.slf4j.MDC
来设置 MDC 上下文,这里是完整代码:
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import com.google.common.collect.ImmutableMap;
import akka.actor.AbstractActor;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
public class BaseActor extends AbstractActor {
private final Logger log = LoggerFactory.getLogger(BaseActor.class);
@Override
public void aroundReceive(PartialFunction<Object, BoxedUnit> receive, Object msg) {
if (msg instanceof IdMessage) {
final Map<String, Object> originalMDC = log.getMDC();
MDC.setContextMap(ImmutableMap.of("id", ((IdMessage) msg).getId()));
try {
super.aroundReceive(receive, msg);
} finally {
if (originalMDC != null) {
MDC.setContextMap(originalMDC);
} else {
MDC.clear();
}
}
} else {
super.aroundReceive(receive, msg);
}
}
}
通过 BaseActor
的实现,receive
中的所有日志条目都使用适当的 MDC 上下文进行记录。可以在这个有趣的博客 post(使用 Scala 实现)中找到更多信息。
注意:我无法使用 Akka DiagnosticLoggingAdapter
实现相同的功能,尽管它有设置 MDC 上下文的方法。