Quarkus: Include stacktraces with unhandled exceptions

Viewed 722

I'm new to quarkus/resteasy, but when I run my quarkus app locally in dev mode, unhandled exceptions include useful details and a stack trace, like this:

{ 
  "details": "Error handling b4f19eef-3634-49f4-865e-55ee75ee3f82-1, org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException: bla bla bla...",
  "stack": "org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException: Cannot invoke ... 
            ... mile long stack trace here ..."
}

However, running from the server, I get these condensed error messages, like this:

{
  "details": "Error id e7bdec12-e36c-40fe-a7c6-096ec8eb62ca-4",
  "stack": ""
}

How can I get exception messages like I get locally from the server? What causes this change? I haven't been able to find any application.properties that might relate to this (https://quarkus.io/guides/all-config), and I'm not sure where else to look.

2 Answers

As mentioned by Geoand, you don't really want to do that on any other env then the local dev env. However JaxRS(impl by Resteasy) gives your full control and you can create custom JaxRS exception mapper to convert unhandled exceptions to any HTTP response you want, including all the gory details of your stacktraces. Example:

@Provider
@Priority(10000)
//the more generic the mapper, the lower its prio should be(the lower the number the higher the pri), so you can override it with more specific mappers
public class ChattyExceptionMapper implements ExceptionMapper<Exception> {

    @Context
    HttpHeaders headers;
    //you can inject all JaxRS ctx data using @Context, see spec
    @Context
    ResourceInfo resourceInfo;

    @Override
    public Response toResponse(Exception e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        return Response
                .serverError()
                .entity(Map.of(
                        "requestHeaders", headers.getRequestHeaders(),
                        "endpointClass", resourceInfo.getResourceClass(),
                        "endpointMethod", resourceInfo.getResourceMethod().getName(),
                        "stacktrace", sw.toString()))
                .build();
    }
}

I way more useful approach in prod might be, that you report the stacktrace/error info in the background to some error reporting system(e.g. Sentry,...), assign some ID to that incident and return the incident id in your error response(via your custom exception mapper). This way you can proactively monitor the errors before you receive complaints from customers/clients and if you do, you can link the incidentId to all the detail data in your error reporting system.

Quarkus does this on purpose.

In dev-mode as you are developing an application you want to have all the information you can get. However in production mode, you don't want to leak the internals of your application to the caller. So in this case, you only see the stacktrace on the server logs

Related