Skip to content
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

Any help setting up Transaction tracking with Jersey JAX-RS #1859

Open
3 tasks done
benallard opened this issue Dec 30, 2021 · 6 comments
Open
3 tasks done

Any help setting up Transaction tracking with Jersey JAX-RS #1859

benallard opened this issue Dec 30, 2021 · 6 comments

Comments

@benallard
Copy link

benallard commented Dec 30, 2021

Platform:

  • Java -> 8
  • Logback ->
  • Spring -> 5.13

The version of the SDK:
5.5.2


I have the following issue:

The provided spring SentryTracingFilter does not record any transaction as it is unable to get a transaction name.

We are not using spring-webmvc, but rather Jersey (2.35), so the request attribute "BEST_MATCHING_PATTERN" is not set.

The whole stuff seems to be working fine, except for the transaction name. there does not seems to be any way to get the 'MATCHING_PATTERN' for the request. I wouldn't mind having the class / method name instead, but i didn't found it in the request either. As if the jersey dispatcher would forget the method name / pattern immediately after calling it.

Is it the right place to ask for such help ?

Did anyone succeeded in recording traces in this context ?

Thanks.

@maciejwalkowiak
Copy link
Collaborator

maciejwalkowiak commented Dec 31, 2021

There seems to be no easy way to get the best matching patch in Jersey. If there would be, you could follow same steps as in the answer for similar problem referring Grails integration: https://forum.sentry.io/t/sentry-java-spring-boot-and-grails-performance-tracing-not-working/15765/3

One hint I can think of is looking up how its done in OpenTelemetry:
https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/spring/spring-webmvc-3.1/javaagent/src/main/java/org/springframework/web/servlet/OpenTelemetryHandlerMappingFilter.java
But, it does seem to be hacky, as the filter class needs to be in the org.springframework.web.servlet package to have access to package protected classes.

@benallard
Copy link
Author

benallard commented Jan 5, 2022

Got it. Using a JAX-RS ContainerRequestFilter, one can request the best_matching_pattern. You'll need to inject the ServletRequest to set the attribute. Then you can use the SentryTracingFilter out of the box. It's a bit sad that we'll need spring-webmvc` just to be able to pass the attribute name, but relaxing the transaction name provider will probably help there.

Note: the filter needs to be registered in the init-params of your servlet.

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;

import org.glassfish.jersey.server.ExtendedUriInfo;
import org.springframework.web.servlet.HandlerMapping;

public class BestMatchRequestExtractor implements ContainerRequestFilter {
    @Context private HttpServletRequest servletRequest;

    @Override
    public void filter(ContainerRequestContext aContainerRequestContext) {
        ExtendedUriInfo uriInfo = (ExtendedUriInfo) aContainerRequestContext.getUriInfo();
        String path = uriInfo.getMatchedTemplates().stream()
                .map(t -> normalizePath(t.getTemplate()))
                .reduce((a, b) -> b + a) // concatenate in reverse order
                .orElse("");
        servletRequest.setAttribute(
                HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE,
                path);
    }

    // See {@link io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxrsPathUtil.normalizePath}
    private static String normalizePath(String path) {
        // ensure that non-empty path starts with /
        if (path == null || "/".equals(path)) {
            path = "";
        } else if (!path.startsWith("/")) {
            path = "/" + path;
        }
        // remove trailing /
        if (path.endsWith("/")) {
            path = path.substring(0, path.length() - 1);
        }

        return path;
    }
}

@maciejwalkowiak What should we do with that class?

@maciejwalkowiak
Copy link
Collaborator

maciejwalkowiak commented Jan 6, 2022

Thanks for figuring it out! You don't need a dependency to spring-mvc to set attribute name. After all, HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE is a constant that won't change so you can just use a string equivalent.

There is an open PR for relaxing TransactionNameProvider #1861 - so you will be able to use another attribute name anyways.

I think we will keep this issue open, see if it gets upvoted - I don't think we have ever had before a request to support Jersey.

@marandaneto marandaneto added the performance Performance API issues label Jan 11, 2022
@marandaneto marandaneto added this to To do in kanban via automation Jan 18, 2022
@Ramblurr
Copy link

Ramblurr commented Jun 14, 2022

I'd like to take advantage of the recent changes in 6.0.0 that made ContainerRequestContext an interface.

The trouble I'm having is I'm not sure what exactly the string returned should be.

@benallard's solution relies on ContainerRequestContext which isn't available inside an implementation of ContainerRequestContext (only HttpServletRequest is).

I presume there is some way to build the required string with that class, but what should it be? The java docs don't state anywhere what the format of the transaction name should take.

@adinauer
Copy link
Member

adinauer commented Jun 14, 2022

@Ramblurr Jersey JAX-RS sounds like something that could be a community package. We'd be happy to point customers to your package if you had one.

The transaction name should make sense to the user and should not be something auto generated because transactions are grouped by their name in Sentry. It's often a function name or URL template (e.g. /posts/{postId}).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Backlog
kanban
To do
Development

No branches or pull requests

5 participants