Java aroundReceive方法中的参与者MDC上下文

Java aroundReceive方法中的参与者MDC上下文,java,akka,mdc,Java,Akka,Mdc,我有一个Java Akka应用程序,我想根据消息中的信息为每个消息处理设置一个单独的MDC上下文,例如,我有以下所有消息的基本接口: public interface IdMessage { String getId(); } 此外,我为所有参与者提供了以下基本参与者: public class BaseActor extends AbstractActor { private final DiagnosticLoggingAdapter log = Logging.appl

我有一个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);
        }
    }
}
我想确保
SomeActor#receive()
中的所有日志条目都将在
BaseActor
中设置MDC上下文。要使此工作正常,需要在与
BaseActor\aroundReceive()方法相同的线程中执行
SomeActor\receice()


我没有找到任何关于
aroundReceive
行为的信息-这是否总是在与实际
receive
方法相同的线程中执行?根据我的测试,它总是在同一个线程中执行

我自己能够找到正确的实现方法,并愿意与大家分享,以防有人遇到同样的问题

将在与
receive
相同的线程中执行
aroundReceive
,因此这是设置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);
        }
    }
}
import java.util.Map;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.slf4j.MDC;
导入com.google.common.collect.ImmutableMap;
导入akka.actor.AbstractActor;
导入scala.PartialFunction;
导入scala.runtime.BoxedUnit;
公共类BaseActor扩展了AbstractActor{
私有最终记录器log=LoggerFactory.getLogger(BaseActor.class);
@凌驾
接收周围的公共无效(PartialFunction接收,对象消息){
if(消息实例IdMessage){
final Map originalMDC=log.getMDC();
setContextMap(ImmutableMap.of(“id”),((IdMessage)msg.getId());
试一试{
super.aroundReceive(receive,msg);
}最后{
if(originalMDC!=null){
MDC.setContextMap(originalMDC);
}否则{
MDC.clear();
}
}
}否则{
super.aroundReceive(receive,msg);
}
}
}
通过
BaseActor
的实现,
receive
中的所有日志条目都使用适当的MDC上下文进行记录。更多信息可以在这个有趣的博客中找到(使用Scala实现)


注意:虽然Akka有设置MDC上下文的方法,但我无法使用Akka
DiagnosticLoggingAdapter
实现相同的功能

我自己能够找到正确的实现方法,并愿意与大家分享,以防有人遇到同样的问题

将在与
receive
相同的线程中执行
aroundReceive
,因此这是设置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);
        }
    }
}
import java.util.Map;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.slf4j.MDC;
导入com.google.common.collect.ImmutableMap;
导入akka.actor.AbstractActor;
导入scala.PartialFunction;
导入scala.runtime.BoxedUnit;
公共类BaseActor扩展了AbstractActor{
私有最终记录器log=LoggerFactory.getLogger(BaseActor.class);
@凌驾
接收周围的公共无效(PartialFunction接收,对象消息){
if(消息实例IdMessage){
final Map originalMDC=log.getMDC();
setContextMap(ImmutableMap.of(“id”),((IdMessage)msg.getId());
试一试{
super.aroundReceive(receive,msg);
}最后{
if(originalMDC!=null){
MDC.setContextMap(originalMDC);
}否则{
MDC.clear();
}
}
}否则{
super.aroundReceive(receive,msg);
}
}
}
通过
BaseActor
的实现,
receive
中的所有日志条目都使用适当的MDC上下文进行记录。更多信息可以在这个有趣的博客中找到(使用Scala实现)


注意:虽然Akka有设置MDC上下文的方法,但我无法使用Akka
DiagnosticLoggingAdapter
实现相同的功能

中解释了
DiagnosticLoggingAdapter
不起作用的原因。至于在Receive
周围重写
,这被标记为内部API,并且仅当您将类放在包
akka.actor
中时才有效,这是一种黑客行为。看见但不确定Java可以做什么。中解释了
DiagnosticLoggingAdapter
不起作用的原因。至于在Receive
周围重写
,这被标记为内部API,并且仅当您将类放在包
akka.actor
中时才有效,这是一种黑客行为。看见不过,我不确定用Java可以做什么。