Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中使用play framewok和akka映射诊断上下文日志记录_Java_Scala_Playframework_Akka_Typesafe - Fatal编程技术网

在java中使用play framewok和akka映射诊断上下文日志记录

在java中使用play framewok和akka映射诊断上下文日志记录,java,scala,playframework,akka,typesafe,Java,Scala,Playframework,Akka,Typesafe,我正在尝试用java将mdc登录到PlayFilter中,以处理我在scala中遵循本教程并尝试转换为java的所有请求 但mdc仍然没有传播到所有执行上下文。 我使用这个dispatcher作为默认的调度器,但是它有很多执行上下文。我需要将mdc传播到所有执行上下文 下面是我的java代码 import java.util.Map; import org.slf4j.MDC; import scala.concurrent.ExecutionContext; import scala.co

我正在尝试用java将mdc登录到PlayFilter中,以处理我在scala中遵循本教程并尝试转换为java的所有请求

但mdc仍然没有传播到所有执行上下文。 我使用这个dispatcher作为默认的调度器,但是它有很多执行上下文。我需要将mdc传播到所有执行上下文

下面是我的java代码

import java.util.Map;

import org.slf4j.MDC;

import scala.concurrent.ExecutionContext;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import akka.dispatch.Dispatcher;
import akka.dispatch.ExecutorServiceFactoryProvider;
import akka.dispatch.MessageDispatcherConfigurator;

public class MDCPropagatingDispatcher extends Dispatcher {
    public MDCPropagatingDispatcher(
            MessageDispatcherConfigurator _configurator, String id,
            int throughput, Duration throughputDeadlineTime,
            ExecutorServiceFactoryProvider executorServiceFactoryProvider,
            FiniteDuration shutdownTimeout) {
        super(_configurator, id, throughput, throughputDeadlineTime,
                executorServiceFactoryProvider, shutdownTimeout);

    }

    @Override
    public ExecutionContext prepare() {
        final Map<String, String> mdcContext = MDC.getCopyOfContextMap();
        return new ExecutionContext() {

            @Override
            public void execute(Runnable r) {
                Map<String, String> oldMDCContext = MDC.getCopyOfContextMap();
                setContextMap(mdcContext);
                try {
                    r.run();
                } finally {
                    setContextMap(oldMDCContext);
                }
            }

            @Override
            public ExecutionContext prepare() {
                return this;
            }

            @Override
            public void reportFailure(Throwable t) {
                play.Logger.info("error occured in dispatcher");
            }

        };
    }

    private void setContextMap(Map<String, String> context) {
        if (context == null) {
            MDC.clear();
        } else {
            play.Logger.info("set context "+ context.toString());
            MDC.setContextMap(context);
        }
    }
}



import java.util.concurrent.TimeUnit;

import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;

import com.typesafe.config.Config;

import akka.dispatch.DispatcherPrerequisites;
import akka.dispatch.MessageDispatcher;
import akka.dispatch.MessageDispatcherConfigurator;

public class MDCPropagatingDispatcherConfigurator extends
        MessageDispatcherConfigurator {
    private MessageDispatcher instance;

    public MDCPropagatingDispatcherConfigurator(Config config,
            DispatcherPrerequisites prerequisites) {
        super(config, prerequisites);
        Duration throughputDeadlineTime = new FiniteDuration(-1,
                TimeUnit.MILLISECONDS);
        FiniteDuration shutDownDuration = new FiniteDuration(1,
                TimeUnit.MILLISECONDS);
        instance = new MDCPropagatingDispatcher(this, "play.akka.actor.contexts.play-filter-context",
                100, throughputDeadlineTime,
                configureExecutor(), shutDownDuration);
    }

    public MessageDispatcher dispatcher() {
        return instance;
    }

}
import java.util.Map;
导入org.slf4j.MDC;
导入scala.concurrent.ExecutionContext;
导入scala.concurrent.duration.duration;
导入scala.concurrent.duration.FiniteDuration;
导入akka.dispatch.Dispatcher;
导入akka.dispatch.ExecutorServiceFactoryProvider;
导入akka.dispatch.MessageDispatcherConfiguration;
公共类MDCPropagatingDispatcher扩展了Dispatcher{
公共MDCPropagatingDispatcher(
MessageDispatcherConfiguration\u配置程序,字符串id,
int吞吐量,持续时间通过输出死线时间,
ExecutorServiceFactoryProvider ExecutorServiceFactoryProvider,
有限持续时间(关闭超时){
超级(\u配置程序、id、吞吐量、吞吐量死线时间、,
executorServiceFactoryProvider,关闭超时);
}
@凌驾
public ExecutionContext prepare(){
最终映射mdcContext=MDC.getCopyOfContextMap();
返回新的ExecutionContext(){
@凌驾
public void execute(可运行的r){
Map oldMDCContext=MDC.getCopyOfContextMap();
setContextMap(mdcContext);
试一试{
r、 run();
}最后{
setContextMap(oldMDCContext);
}
}
@凌驾
public ExecutionContext prepare(){
归还这个;
}
@凌驾
公共失效报告失败(可丢弃的t){
play.Logger.info(“dispatcher中发生错误”);
}
};
}
私有void setContextMap(映射上下文){
if(上下文==null){
MDC.clear();
}否则{
play.Logger.info(“set context”+context.toString());
setContextMap(上下文);
}
}
}
导入java.util.concurrent.TimeUnit;
导入scala.concurrent.duration.duration;
导入scala.concurrent.duration.FiniteDuration;
导入com.typesafe.config.config;
导入akka.dispatch.DispatcherPrerequisites;
导入akka.dispatch.MessageDispatcher;
导入akka.dispatch.MessageDispatcherConfiguration;
公共类MDCPropagatingDispatcherConfiguration扩展
MessageDispatcherConfiguration{
私有消息调度实例;
公共MDCPropagatingDispatcherConfiguration(配置,
DispatcherPrerequire(站点先决条件){
超级(配置,先决条件);
Duration throughputDeadlineTime=新完成的持续时间(-1,
时间单位(毫秒);
最终持续时间关闭持续时间=新的最终持续时间(1,
时间单位(毫秒);
instance=new-MDCPropagatingDispatcher(这是“play.akka.actor.context.play-filter-context”,
100,通过输出死线时间,
configureExecutor(),关机持续时间);
}
public MessageDispatcher(){
返回实例;
}
}
过滤拦截器

public class MdcLogFilter implements EssentialFilter {
@Override
public EssentialAction apply(final EssentialAction next) {
    return new MdcLogAction() {
        @Override
        public Iteratee<byte[], SimpleResult> apply(
                final RequestHeader requestHeader) {
            final String  uuid = Utils.generateRandomUUID();
            MDC.put("uuid", uuid);
            play.Logger.info("request started"+uuid);
            final ExecutionContext playFilterContext = Akka.system()
                    .dispatchers()
                    .lookup("play.akka.actor.contexts.play-custom-filter-context");
            return next.apply(requestHeader).map(
                    new AbstractFunction1<SimpleResult, SimpleResult>() {
                        @Override
                        public SimpleResult apply(SimpleResult simpleResult) {
                            play.Logger.info("request ended"+uuid);
                            MDC.remove("uuid");
                            return simpleResult;
                        }
                    }, playFilterContext);

        }

        @Override
        public EssentialAction apply() {
            return next.apply();
        }
    };
}
公共类MdcLogFilter实现EssentialFilter{
@凌驾
公共要素申请(下一步为最终要素){
返回新的MdcLogAction(){
@凌驾
公共迭代者申请(
最终请求头(请求头){
最后一个字符串uuid=Utils.generateRandomUUID();
MDC.put(“uuid”,uuid);
play.Logger.info(“请求已启动”+uuid);
final ExecutionContext playFilterContext=Akka.system()
.调度员()
.lookup(“play.akka.actor.context.play自定义筛选上下文”);
返回next.apply(requestHeader.map)(
新的AbstractFunction1(){
@凌驾
公共SimpleResult应用(SimpleResult SimpleResult){
play.Logger.info(“请求结束”+uuid);
MDC.移除(“uuid”);
返回simpleResult;
}
},playFilterContext);
}
@凌驾
公共要素应用(){
返回next.apply();
}
};
}

}下面是我的解决方案,在现实生活中得到了验证。它在Scala中,不是为了玩,而是为了Scalatra,但基本概念是一样的。希望您能够了解如何将其移植到Java

import org.slf4j.MDC
import java.util.{Map => JMap}
import scala.concurrent.{ExecutionContextExecutor, ExecutionContext}

object MDCHttpExecutionContext {

  def fromExecutionContextWithCurrentMDC(delegate: ExecutionContext): ExecutionContextExecutor =
    new MDCHttpExecutionContext(MDC.getCopyOfContextMap(), delegate)
}

class MDCHttpExecutionContext(mdcContext: JMap[String, String], delegate: ExecutionContext)
  extends ExecutionContextExecutor {

  def execute(runnable: Runnable): Unit = {
    val callingThreadMDC = MDC.getCopyOfContextMap()
    delegate.execute(new Runnable {
      def run() {
        val currentThreadMDC = MDC.getCopyOfContextMap()
        setContextMap(callingThreadMDC)
        try {
          runnable.run()
        } finally {
          setContextMap(currentThreadMDC)
        }
      }
    })
  }

  private[this] def setContextMap(context: JMap[String, String]): Unit = {
    Option(context) match {
      case Some(ctx) => {
        MDC.setContextMap(context)
      }
      case None => {
        MDC.clear()
      }
    }
  }

  def reportFailure(t: Throwable): Unit = delegate.reportFailure(t)
}
您必须确保在所有异步调用中都使用此ExecutionContext。我通过依赖注入实现这一点,但有不同的方法。我就是这样做的:


这种方法背后的思想如下。MDC对属性及其值使用线程本地存储。如果您的单个请求可以在多个线程上运行,那么您需要确保启动的新线程使用正确的MDC。为此,创建一个自定义执行器,确保在新线程开始执行分配给它的任务之前,将MDC值正确复制到新线程中。您还必须确保当线程完成任务并继续执行其他任务时,您将旧值放入其MDC中,因为池中的线程可以在不同的请求之间切换

你能解决它吗?如果是,你能发布你的解决方案吗
bind[ExecutionContext] idBy BindingIds.GlobalExecutionContext toSingle {
    MDCHttpExecutionContext.fromExecutionContextWithCurrentMDC(
      ExecutionContext.fromExecutorService(
        Executors.newFixedThreadPool(globalThreadPoolSize)
      )
    )
  }