-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Common URL Template path handling for REST requests (server and client) #17676
Conversation
/cc @kenfinnigan |
extensions/micrometer/deployment/src/test/resources/test-logging.properties
Outdated
Show resolved
Hide resolved
...untime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/vertx/VertxTracingAdapter.java
Outdated
Show resolved
Hide resolved
.../src/main/java/io/quarkus/resteasy/observability/deployment/RestPathAnnotationProcessor.java
Outdated
Show resolved
Hide resolved
There's no detail in the description so it's hard to guess what this is for? Until now, we didn't have specific extension for observability but we enabled it if the ad hoc extension was around and a config property enabled. What is the rationale for creating a specific extension here? |
@gsmet I can add a description, but the idea is we need a way for REST services to capture the parameterized version of a URL path for an endpoint as it's needed for setting on metrics and traces. Not using the parameterized version results in high cardinality metrics and traces because we get a separate version for each parameter passed to the endpoint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can approve, but seems odd given I contributed as well ;-)
This workflow status is outdated as a new workflow run has been triggered. |
This workflow status is outdated as a new workflow run has been triggered. 🚫 This workflow run has been cancelled. Failing Jobs - Building 8b77f0f
Full information is available in the Build summary check run. Test Failures⚙️ Devtools Tests - JDK 11 #📦 integration-tests/devtools✖ ✖ ✖ ✖ 📦 integration-tests/devtools/target/quarkus-codestart-build-test/project-maven-java-resteasy-reactive-codestart✖ 📦 integration-tests/devtools/target/quarkus-codestart-build-test/project-maven-kotlin-resteasy-reactive-codestart✖ 📦 integration-tests/devtools/target/quarkus-codestart-test/resteasy-reactive/real-data/java✖ ⚙️ Devtools Tests - JDK 11 Windows #📦 integration-tests/devtools✖ ✖ ✖ ✖ 📦 integration-tests/devtools/target/quarkus-codestart-build-test/project-maven-java-resteasy-reactive-codestart✖ 📦 integration-tests/devtools/target/quarkus-codestart-build-test/project-maven-kotlin-resteasy-reactive-codestart✖ 📦 integration-tests/devtools/target/quarkus-codestart-test/resteasy-reactive/real-data/java✖ |
I can't really say I fully understand what's going on here, but IIUC you are adding a CDI interceptor everywhere there is a Furthermore, is the new obversability module meant to be a hard dependency? Can't RESTEasy Classic and RESTEasy Reactive extensions just depend on an SPI module for the build items? |
Yes, but only when Micrometer or OpenTelemetry are also present, otherwise it is not included.
Not at present, but the interceptor only reads an annotation and sets a value in the Vertx context, so it should be fairly light.
Yes, that's right. Do you have pointers to examples? The reason a CDI Interceptor was chosen is we needed something that works for both RESTEasy Classic and RESTEasy Reactive. Maybe having the common annotation transformer is all that needs to be common, and we can have specific ways to retrieve the annotation and add it to the context.
Yes, it's meant to be a hard dependency. There originally was an SPI with just the build item, but then it became too complicated as to how to include the actual deployment dependency given the logic of "if (RESTEasy Classic OR RESTEasy Reactive) AND (Micrometer OR OpenTelemetry)". It was decided the best option was to directly include in the REST extensions but have the processor do nothing if Micrometer or OpenTelemetry aren't present. |
Reading the annotation part is what has me worried.
Basically you would need to add a new
OK |
Even when it's a straight read and then set without any computation associated with it? What alternatives are available to do what is needed?
Thanks |
Yes, our strategy has been to put this kind of thing in it's own
👍🏼 |
Where do we store the path value if not on an annotation? We need to store it somewhere between the annotation transformer in the build step and runtime. |
You could stuff the value in the implementation of If you like, I can have a go at this on Monday. |
If you have some time, that would be appreciated |
Sure yeah, I'll take care of it on Monday. I would do it tomorrow, but I have a talk to give so it's very unlikely I'll have the time :) |
That doesn't resolve the issue, Georgios. Doing something special in Resteasy reactive doesn't fix/address the mess that is resteasy classic. Part of what is nice about this solution is that it is comparatively simple. I've tried doing this 8 different ways, and this is the way that covers resteasy reactive AND resteasy classic (AND the clients in both cases). |
I'll fix things on the RESTEasy Reactive side on Monday, but RESTEasy Classic is up you to address the issues based on what Stuart brought up. |
As in mentioned in my previous comment the client is broken, it will overwrite the server version, and can't handle concurrent async requests. |
As I am observing (putting the micrometer side of these tests together), the interceptor does not overwrite the server value because it uses a different context entirely (which the client filter running later doesn't see). So there is something else to fix there, I agree (and I've moved this PR back to draft while I sort that out). I understand the desire to do something different for RR. The tests in extensions/micrometer/deployment cover resteasy classic (server and client) and integration-tests/micrometer-prometheus will cover resteasy reactive (server and client). The resteasy reactive tests (minimally) will be failing and ready for you to fix on Monday, @geoand =) |
Previously I'd moved away from |
[Edit] Things have been moved around. @geoand .. tests have been updated with expected URIs:
OpenTelemetry with RR is not ready yet. |
The RESTEasy Reactive server part is done and I am looking into the client part as well (which seems to be more involved). |
I pushed a fix for the Reactive REST Client as well. There is still one test failing:
|
Yep, there was. All fixed. Found another issue with the classic path, that's also been corrected. Let's see how CI does. |
This workflow status is outdated as a new workflow run has been triggered. Failing Jobs - Building 4d0bbe4
Full information is available in the Build summary check run. Test Failures⚙️ Native Tests - Misc4 #📦 integration-tests/opentelemetry✖ |
...st-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java
Outdated
Show resolved
Hide resolved
...sy/runtime/src/main/java/io/quarkus/resteasy/runtime/QuarkusRestPathTemplateInterceptor.java
Outdated
Show resolved
Hide resolved
} finally { | ||
if (annotation != null) { | ||
((HttpServerRequestInternal) request.getCurrent().request()).context().putLocal("UrlPathTemplate", | ||
annotation.value()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this won't deal with subresources, but I don't know how big an issue this is. As sub resources are directly instantiated by the user code you can't guarantee that interceptors will be applied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would a subresource have a path annotation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well the initial resource locator method will, however the resource that is returned likely won't be managed by CDI so won't be intercepted.
.../io/quarkus/resteasy/reactive/server/deployment/ServerResourceMethodCustomizerBuildItem.java
Outdated
Show resolved
Hide resolved
...sor/src/main/java/org/jboss/resteasy/reactive/server/processor/ResourceMethodCustomizer.java
Outdated
Show resolved
Hide resolved
Test failure looks related, it looks like a META-INF/services entry is not registered in native mode. |
This workflow status is outdated as a new workflow run has been triggered. 🚫 This workflow run has been cancelled. Failing Jobs - Building 77c361b
|
- Add tests for Micrometer and OpenTelemetry to verify server and client uri is parameterized - Add UrlTemplatePath handling for RESTEasy Reactive Server - Add UrlTemplatePath handling for Reactive REST Client - Move Opentelemetry listener registration to relevant extension - Use a DynamicFeature to set the UrlPathTemplate - Expand existing MethodScanner Co-authored-by: Erin Schnabel <[email protected]> Co-authored-by: Ken Finnigan <[email protected]> Co-authored-by: Georgios Andrianakis <[email protected]> Co-authored-by: Stuart Douglas <[email protected]>
I probably shouldn't approve as I was involved in it
@kenfinnigan we have all been involved in it, so that would apply to any of our reviews :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes that aren't mine LGTM! (but I can't approve as it is my PR)
Fixes #16952
Fixes #15231
Fixes #15044
Provide a common way to remember the parameterized path of a REST endpoint.
Both Micrometer and OpenTelemetry use parameterized values to reduce the cardinality of telemetry data, e.g. using
/hello/{name}
instead of/hello/gary
.RESTEasy classic and RESTEasy Reactive manage creation/registration of templated paths very differently and two extensions need to be able to consume the parameterized version of the path.
Resteasy classic server requests: An additional interceptor annotation is added that stores the partly-resolved templated value from the original
@Path
annotation (taking a configured Rest ApplicationPath value into account). An associated interceptor binding looks up that annotation to retrieve the templated path, and set it on the common vertx context where consumers (both Micrometer and OpenTelemetry) can find it.Resteasy classic client requests: