Есть ли у CompletableFuture соответствующий локальный контекст?

В прежние времена у нас был ThreadLocal для программ для переноса данных вместе с путем запроса, поскольку вся обработка запроса выполнялась в этом потоке, и такие вещи, как logback, использовали это с MDC.put ("requestId", getNewRequestId ());

Затем пришли scala и функциональное программирование, появился Futures, и вместе с ними появился Local.scala (по крайней мере, я знаю, что у Twitter Futures есть этот класс). Future.scala знает о Local.scala и передает контекст через все функции map / flatMap и т. Д. И т. Д., Так что я все еще могу делать Local.set ("requestId", getNewRequestId ()); и затем вниз по течению после того, как он прошел через много потоков, я все еще могу получить к нему доступ с помощью Local.get (...)

Soooo, мой вопрос в Java, могу ли я сделать то же самое с новым CompletableFuture где-нибудь с LocalContext или некоторым объектом (не уверен в имени), и таким образом, я могу изменить контекст MDC logback, чтобы сохранить его в этом контексте вместо ThreadLocal таким образом, что я не теряю идентификатор запроса и все мои журналы через thenApply, thenAccept и т. д. и т. д., все еще прекрасно работают с журналированием и флагом -XrequestId в конфигурации logback

РЕДАКТИРОВАТЬ:

В качестве примера. Если у вас есть запрос и вы используете log4j или logback, в фильтре вы установите MDC.put ("requestId", requestId), а затем в своем приложении вы запишете много операторов журнала.

log.info("request came in for url="+url);
log.info("request is complete");

Теперь в выводе журнала он покажет

INFO {time}: requestId425 request came in for url=/mypath
INFO {time}: requestId425 request is complete

Это использует трюк ThreadLocal для достижения этой цели. В твиттере мы используем scala и twitter Futures в scala вместе с классом Local.scala. Local.scala и Future.scala связаны между собой тем, что мы можем достичь описанного выше сценария, что очень приятно, и все наши операторы log могут регистрировать идентификатор запроса, поэтому разработчику никогда не придется запоминать идентификатор запроса, и вы можете проследить через один цикл запроса клиентов с этим идентификатором.

Я не вижу этого в java :(, что очень прискорбно, поскольку есть много вариантов использования для этого. Возможно, есть что-то, чего я не вижу, хотя?

 Holger21 июн. 2016 г., 12:26
Простой ответ: нет. Данные должны быть просто переданы от одного этапа к зависимым этапам. То, что вы просите, это вариант глобальных переменных.
 Dean Hiller22 мар. 2018 г., 16:34
конечно, здесь есть обсуждение, но они не понимают, что сломали контекст MDC log4j и logback (slf4j) через фьючерсыmail.openjdk.java.net/pipermail/core-libs-dev/2017-May/... и это не может быть исправлено, кроме как тем, что, когда я вношу библиотеку, я не могу изменить эту библиотеку. Они могут наконец понять это через год, или, возможно, кто-то другой сможет объяснить им это лучше. до тех пор мы должны делать наши проекты в Scala (MDC слишком важен, чтобы его можно было сломать).
 Dean Hiller22 мар. 2018 г., 15:37
@DidierL Я бы перевел только для thenCompose / thenApply так же, как в твиттере (т. Е. См. Код scala ... они уже решили его !!!)
 Dean Hiller14 февр. 2019 г., 00:33
@ JörnHorstmann Поправьте меня, если я ошибаюсь, но если я добавлю стороннюю библиотеку, которая использует фьючерсы, кто-то должен будет исправить все фьючерсы в этой сторонней библиотеке, чтобы MDC распространялся в эту библиотеку (и для продолжения регистрации использовать MDC). то есть. фьючерсы в твиттере действительно сделали это правильно ... надеюсь, фьючерсы на scala также скопировали этот паттерн. Это довольно удивительно и прекрасно работает.
 Didier L05 мар. 2018 г., 17:14
Просто мысль: еслиCompletableFuture имел такой контекст, каково было бы его поведение для всех методов, которые «объединяют» независимые CF? Например,thenCombine(), thenCompose(), allOf()
 Dean Hiller14 февр. 2019 г., 00:34
@ JörnHorstmann Целью этой функции является то, что я могу привлечь сторонних библиотек, и местное государство до сих пор путешествует по всем методам. то есть. java действительно нужен Local.java, о котором CompletableFuture знает, чтобы все это работало.
 Jörn Horstmann19 июл. 2018 г., 11:23
Java 9 добавил несколько методовCompletableFuture что сделало бы намного легче распространять контекст. НапримерnewIncompleteFuture​ а такжеdefaultExecutor​ (docs.oracle.com/javase/9/docs/api/java/util/concurrent/...). Вы все еще должны убедиться, что начальное будущее имеет правильный подкласс, хотя.
 Holger21 июн. 2016 г., 15:45
Так что это типичныйXY проблема, Вместо того, чтобы запрашивать локальный контекст, вы должны описать «проблему MDC logback», которую вы на самом деле пытаетесь решить.
 Dean Hiller21 июн. 2016 г., 15:20
ну, дерьмо, тогда кто-нибудь знает, как решить проблему MDC logback, так как эта проблема нарушается в java при использовании CompletableFuture, в то время как она прекрасно работает в scala, если вы привязываете ее к Local вместо ThreadLocal. Это была фантастическая особенность log4j и logback.
 Dean Hiller09 авг. 2016 г., 00:33
на самом деле это не проблема XY, хотя в качестве конкретного примера я привожу logback / log4j, так как теперь он ломается с помощью операторов MDC .... log больше не содержит правильный requestId при отображении на фьючерсы. Мы исправили это в scala, переопределив MDC для использования Local вместо ThreadLocal. Похоже, что в java нет решения (И я хочу использовать это для решения проблемы с платформой, из-за которой все становится действительно чисто ... Я использую это очень экономно, но это решает некоторые действительно хорошие проблемы.

Ответы на вопрос(1)

http://mail.openjdk.java.net/pipermail/core-libs-dev/2017-May/047867.html

реализовать что-то вроде Twitter Futures, которые передают Locals (очень похоже на ThreadLocal, но передает состояние).

Смотрите здесь метод def response () и узнайте, как он вызывает Locals.save () и Locals.restort ().https://github.com/simonratner/twitter-util/blob/master/util-core/src/main/scala/com/twitter/util/Future.scala

Если авторы Java исправят это, то MDC в logback будет работать во всех сторонних библиотеках. До этого ЭТО НЕ БУДЕТ РАБОТАТЬ, если вы не можете изменить стороннюю библиотеку (сомнительно, что вы можете это сделать).

Ваш ответ на вопрос