forked from micronaut-projects/micronaut-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc: Context propagation documentation (micronaut-projects#9554)
- Loading branch information
Showing
19 changed files
with
422 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
The new Propagation Context API aims to simplify reactor instrumentation, avoid thread-local usage, and integrate idiomatically with Kotlin Coroutines. | ||
|
||
The api:core.propagation.PropagatedContext[] object represents the context propagation. We designed the context propagation API for immutability. It consists of multiple elements of type api:core.propagation.PropagatedContextElement[]. | ||
|
||
Each element represents a particular state that needs to be propagated. There is a special element that can be used to update and restore the thread-local value api:core.propagation.ThreadPropagatedContextElement[]: | ||
|
||
.Example of MDC propagated element implementing `ThreadPropagatedContextElement` | ||
[source,java] | ||
---- | ||
include::{testsuitejava}/propagation/MdcPropagationContext.java[tags="class"] | ||
---- | ||
<1> The class has the MDC state passed in the contractor | ||
<2> The context update sets the MDC state as the current one | ||
<3> The previous state is captured to be restored | ||
<3> The previous state is restored | ||
|
||
In this example, the propagated context element implements the setting of the MDC context and it restores it after. | ||
|
||
NOTE: The api:core.propagation.ThreadPropagatedContextElement[] is inspired by Kotlin Coroutines propagation API element `kotlinx.coroutines.ThreadContextElement` | ||
|
||
snippet::io.micronaut.docs.propagation.MdcService[tags="createUser", indent=0, title="MDC propagation example"] | ||
|
||
IMPORTANT: In the previous versions of Micronaut Framework, we would capture the context to propagate, this is not the case since Micronaut Framework 4. We always require for the context to be modified manually and repropagated. |
19 changes: 19 additions & 0 deletions
19
src/main/docs/guide/contextPropagation/httpFilterContextPropagation.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Modifying the propagated context is a common scenario. Usually, you want to extend the context to include the request-related values. | ||
|
||
To use a non-reactive HTTP filter API, you need to add a method parameter api:core.propagation.MutablePropagatedContext[] and modify the propagated context elements by adding or removing the existing ones: | ||
|
||
.Example of adding a new MDC propagated context element | ||
[source,java] | ||
---- | ||
include::{testsuitejava}/propagation/MdcFilter.java[tags="class", indent=0] | ||
---- | ||
|
||
The next filter in the chain will have the new propagated context available. Any of the thread-local context elements will be set for the next filter or the controller method invocation. | ||
|
||
To use the legacy reactive HTTP filters, simply modify and propagate the context bound to the following chain invocation: | ||
|
||
.Example of adding a new MDC propagated context element for the reactive filter: | ||
[source,java] | ||
---- | ||
include::{testsuitejava}/propagation/MdcLegacyFilter.java[tags="class", indent=0] | ||
---- |
28 changes: 28 additions & 0 deletions
28
src/main/docs/guide/contextPropagation/reactorContextPropagation.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
Since Micronaut Framework version 4, https://projectreactor.io[Project Reactor] integration no longer captures the state automatically. Micronaut Framework users need to extend the propagation context manually. | ||
|
||
Before version 4, Micronaut Framework required the instrumentation of every reactive operator to capture the current state to propagate it. It added an unwanted overhead and forced us to maintain complicated Reactor operators' instrumentation. | ||
|
||
Since 3.5.0, Reactor-Core embeds support for the `io.micrometer:context-propagation` SPI. This allows to achieve the same thread-local propagation by including the https://micrometer.io/docs/contextPropagation[Micrometer Context Propagation] dependency. | ||
|
||
The framework automatically adds the `PropagatedContext` to Project Reactor's context for interceptors and the HTTP filters. You can access it via the utility class api:core.async.propagation.ReactorPropagation[]. | ||
|
||
NOTE: api:core.async.propagation.ReactorPropagation[] is an experimental class and might change in the future. | ||
|
||
It is possible to use https://micrometer.io/docs/contextPropagation[Micrometer Context Propagation], which Reactor supports for propagation and restoring the thread-local context. | ||
|
||
To enable it, include the dependency: | ||
|
||
dependency:context-propagation[groupId="io.micrometer",scope="compile"] | ||
|
||
After that, all the thread-local propagated elements can restore their thread-local value. | ||
|
||
NOTE: The thread-local values are read-only. To modify them, the `PropagatedContext` instance needs to be changed and put into the Reactor's context. | ||
|
||
If you have Micrometer Context Propagation on the classpath but don't want to use it, apply the following configuration: | ||
|
||
.Disable Micrometer Context Propagation in Reactor | ||
[configuration] | ||
---- | ||
reactor: | ||
enable-automatic-context-propagation: false | ||
---- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
test-suite-kotlin/src/test/kotlin/io/micronaut/docs/ioc/beans/User.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package io.micronaut.docs.ioc.beans | ||
|
||
import io.micronaut.core.annotation.Introspected | ||
|
||
// tag::class[] | ||
@Introspected(accessKind = [Introspected.AccessKind.FIELD]) | ||
class User( | ||
val name: String // <1> | ||
) { | ||
var age = 18 // <2> | ||
} | ||
// end::class[] |
29 changes: 29 additions & 0 deletions
29
test-suite/src/test/java/io/micronaut/docs/propagation/MdcFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package io.micronaut.docs.propagation; | ||
|
||
import io.micronaut.context.annotation.Requires; | ||
import io.micronaut.core.propagation.MutablePropagatedContext; | ||
import io.micronaut.http.HttpRequest; | ||
import io.micronaut.http.annotation.RequestFilter; | ||
import io.micronaut.http.annotation.ServerFilter; | ||
import org.slf4j.MDC; | ||
|
||
import static io.micronaut.http.annotation.Filter.MATCH_ALL_PATTERN; | ||
|
||
@Requires(property = "mdc.example.filter.enabled") | ||
// tag::class[] | ||
@ServerFilter(MATCH_ALL_PATTERN) | ||
public class MdcFilter { | ||
|
||
@RequestFilter | ||
public void myRequestFilter(HttpRequest<?> request, MutablePropagatedContext mutablePropagatedContext) { | ||
try { | ||
String trackingId = request.getHeaders().get("X-TrackingId"); | ||
MDC.put("trackingId", trackingId); | ||
mutablePropagatedContext.add(new MdcPropagationContext()); | ||
} finally { | ||
MDC.remove("trackingId"); | ||
} | ||
} | ||
|
||
} | ||
// end::class[] |
60 changes: 60 additions & 0 deletions
60
test-suite/src/test/java/io/micronaut/docs/propagation/MdcFilterSpec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright 2017-2020 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.docs.propagation; | ||
|
||
import io.micronaut.context.ApplicationContext; | ||
import io.micronaut.context.annotation.Requires; | ||
import io.micronaut.http.HttpRequest; | ||
import io.micronaut.http.MediaType; | ||
import io.micronaut.http.annotation.Controller; | ||
import io.micronaut.http.annotation.Get; | ||
import io.micronaut.http.client.HttpClient; | ||
import io.micronaut.runtime.server.EmbeddedServer; | ||
import org.junit.Test; | ||
import org.slf4j.MDC; | ||
|
||
import java.util.Map; | ||
import java.util.UUID; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
public class MdcFilterSpec { | ||
|
||
@Test | ||
public void testFilterSpec() { | ||
try (EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer.class, Map.of("mdc.example.filter.enabled", true))) { | ||
try (HttpClient client = HttpClient.create(embeddedServer.getURL())) { | ||
|
||
String tracingId = UUID.randomUUID().toString(); | ||
HttpRequest<Object> request = HttpRequest | ||
.GET("/mdc/test") | ||
.header("X-TrackingId", tracingId); | ||
assertEquals(client.toBlocking().retrieve(request), tracingId); | ||
} | ||
} | ||
} | ||
|
||
@Controller("/mdc") | ||
@Requires(property = "mdc.example.filter.enabled") | ||
static class MDCController { | ||
|
||
@Get(value = "/test", produces = MediaType.TEXT_PLAIN) | ||
String test() { | ||
return MDC.get("trackingId"); | ||
} | ||
|
||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
test-suite/src/test/java/io/micronaut/docs/propagation/MdcLegacyFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package io.micronaut.docs.propagation; | ||
|
||
import io.micronaut.context.annotation.Requires; | ||
import io.micronaut.context.propagation.slf4j.MdcPropagationContext; | ||
import io.micronaut.core.propagation.PropagatedContext; | ||
import io.micronaut.http.HttpRequest; | ||
import io.micronaut.http.MutableHttpResponse; | ||
import io.micronaut.http.annotation.Filter; | ||
import io.micronaut.http.filter.HttpServerFilter; | ||
import io.micronaut.http.filter.ServerFilterChain; | ||
import org.reactivestreams.Publisher; | ||
import org.slf4j.MDC; | ||
|
||
import static io.micronaut.http.annotation.Filter.MATCH_ALL_PATTERN; | ||
|
||
@Requires(property = "mdc.example.legacy.filter.enabled") | ||
// tag::class[] | ||
@Filter(MATCH_ALL_PATTERN) | ||
public class MdcLegacyFilter implements HttpServerFilter { | ||
|
||
@Override | ||
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, | ||
ServerFilterChain chain) { | ||
try { | ||
String trackingId = request.getHeaders().get("X-TrackingId"); | ||
MDC.put("trackingId", trackingId); | ||
try (PropagatedContext.Scope ignore = PropagatedContext.get().plus(new MdcPropagationContext()).propagate()) { | ||
return chain.proceed(request); | ||
} | ||
} finally { | ||
MDC.remove("trackingId"); | ||
} | ||
} | ||
|
||
} | ||
// end::class[] |
60 changes: 60 additions & 0 deletions
60
test-suite/src/test/java/io/micronaut/docs/propagation/MdcLegacyFilterSpec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright 2017-2020 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.docs.propagation; | ||
|
||
import io.micronaut.context.ApplicationContext; | ||
import io.micronaut.context.annotation.Requires; | ||
import io.micronaut.http.HttpRequest; | ||
import io.micronaut.http.MediaType; | ||
import io.micronaut.http.annotation.Controller; | ||
import io.micronaut.http.annotation.Get; | ||
import io.micronaut.http.client.HttpClient; | ||
import io.micronaut.runtime.server.EmbeddedServer; | ||
import org.junit.Test; | ||
import org.slf4j.MDC; | ||
|
||
import java.util.Map; | ||
import java.util.UUID; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
public class MdcLegacyFilterSpec { | ||
|
||
@Test | ||
public void testFilterSpec() { | ||
try (EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer.class, Map.of("mdc.example.legacy.filter.enabled", true))) { | ||
try (HttpClient client = HttpClient.create(embeddedServer.getURL())) { | ||
|
||
String tracingId = UUID.randomUUID().toString(); | ||
HttpRequest<Object> request = HttpRequest | ||
.GET("/mdc/test") | ||
.header("X-TrackingId", tracingId); | ||
assertEquals(client.toBlocking().retrieve(request), tracingId); | ||
} | ||
} | ||
} | ||
|
||
@Controller("/mdc") | ||
@Requires(property = "mdc.example.legacy.filter.enabled") | ||
static class MDCController { | ||
|
||
@Get(value = "/test", produces = MediaType.TEXT_PLAIN) | ||
String test() { | ||
return MDC.get("trackingId"); | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.