-
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
Micrometer Vertx JAX-RS path template is not properly recovered for metric uri labels #14813
Comments
/cc @ebullient |
Thanks for the reproducer. This kind of parameter matching is .. difficult. Can you try using a match pattern? I added this specifically to get around accuracy limitations in understanding rest paths:
|
I tried the option as described but it did not seem to work. I played with the pattern a bit but didn't investigate deeper. Even if it worked I fear this will be very hard to get right in changing services with many developers. Do you see a way of making this work out of the box? As we have the parameters there must have already been some kind of awareness of the template at that layer of request processing. Or maybe the patterns can be pre-created or something. |
The maps we have in hand are completely unordered. I could make strings and sort the parameterized values by length to make sure the match was more accurate -- but that is more expensive than a regex match, and could still be wrong some of the time. There may be a few more tricks down the line with Vert.x 4, but there isn't a clear way to grab the parameterized endpoint used in the original annotation. Maybe I'll chew on that a little more for more Quarkus magic. Can you share the patterns you've tried? |
I tried your original and I dug a bit deeper into the code and noticed that this filter isn't actually executed as part of any of any normal vertx filter chains. From what I can tell it is explicitly run as a ContainerRequestFilter (or ServerRequestFilter). E.g. the public class VertxMeterBinderRestEasyContainerFilter implements ContainerRequestFilter {
@Override
public void filter(final ContainerRequestContext requestContext) {
VertxMeterBinderContainerFilterUtil.doFilter(CDI.current().select(CurrentVertxRequest.class).get().getCurrent(),
requestContext.getUriInfo());
}
} I think in both cases as @Provider
public class MyContainerVertxFilter implements ContainerRequestFilter {
@Override
public void filter(final ContainerRequestContext requestContext) {
System.out.println("ContainerVertxFilter");
var resourceMethodInvoker = ((PostMatchContainerRequestContext) requestContext).getResourceMethod();
var resourceMethod = resourceMethodInvoker.getMethod();
var resourceClass = resourceMethodInvoker.getResourceClass();
UriBuilder resourceUriBuilder= UriBuilder.fromResource(resourceClass)
.path(resourceMethod);
String resourceUri= resourceUriBuilder.toTemplate();
System.out.println(resourceUri);
}
} Gives me the template string. This relies on knowing the But investigating in a direction like that seems to be the best way to me. Otherwise I fear a large amount of all quarkus applications with micrometer metrics out there will have broken uri labels on their metrics. |
Well, I agree with you, which is why the matchPattern is there (and should work). (regardless of what other path might be taken, as we have lots of ways to handle http traffic). I'll update the current tests to chase why the pattern isn't matching, I must have made a mistake somewhere. |
Ok. The PR does sort out the behavior of I'll need to take another gander at the more ambitious solution, which may need to wait until Vert.x 4 (see #14905) |
Awesome. Hoping for pre Vert.x 4 (Quarkus 2.0) obviously ;) Please let me know you decide to go that way though because we'll probably want to investigate a workaround in the direction of what I described above on our end in that case. Otherwise the only way I see would be to tell developers to add |
Using JAX-RS is the most common? Or native/naked Vert.x web? Or servlets with undertow... |
Pretty exclusively JAX-RS right now for us. I am aware that a general solution for Quarkus is much harder. That's why I would investigate workarounds on our end if it turns out to be infeasible for a while. |
Needs to be extra escaped, e.g.:
But there was also some other wonkiness going on that is resolved in the linked PR.
Correct. The Vert.x filter does a hand-off at the container boundary (Vert.x http/web filter chains don't see it, for the most part). I use ContainerFilters w/ Resteasy & Resteasy reactive to deal w/ JAX-RS details. Undertow servlets & websockets are on a totally different path (that isn't well instrumented, either). |
Describe the bug
To reduce label cardinality Micrometer default http metrics have to use the URL template string instead of raw request URL (e.g.
/items/123
must be converted back to/items/{id}
). The implementation for this is in VertxMeterBinderContainerFilterUtil. Unfortunately the approach taken there is not reliable as it does a simple search and replace of the passed value with the parameter which produces wrong behavior in many common cases.Expected behavior
/{foo}/{bar}
handling/123/1
should result in http metric label{foo}/{bar}
Actual behavior
Due to the search and replace approach
/{foo}/{bar}
handling/123/1
instead can result in a http metric label like{bar}23/{bar}
.To Reproduce
Using a basic JAX-RS example with quarkus micrometer enabled:
Steps to reproduce the behavior:
Notice the replacement failing for the uri label:
I'm not sure if the ordering is guaranteed so you might have to swap
123/1
with1/123
.Environment (please complete the following information):
The text was updated successfully, but these errors were encountered: