Jersey Server Logging /w Logback

2020-04-18 09:43发布

问题:

How would I go about getting Jersey LoggingFilter working with logback? I saw this post:

How to get jersey logs at server?

but it unfortunately relies on the java.util.Logger. I am not super well versed when it comes to web.xml configuration so I would not know how to go about offering the init-param different loggers.

Note that I am using Spring 3 for dependency injection, but am creating loggers per class with the code:

Logger logger = LoggerFactory.getLogger(MyClass.class);

Hope this is enough information. If not, let me know.

My web container is Tomcat 7.0.12.

回答1:

You can bridge java.util.Logger calls to Logback by using the jul-to-slf4j bridge. With that installed you can control Jersey logging (and any other JUL) with your logback.xml.



回答2:

I tried to use Jersey-Spring4 with logback and was not able to redirect access logs via the LoggingFeature to my logback-logger. The logback-logger was configured like <logger name="org.glassfish.jersey" level="INFO"/> and I assumed this should do the trick.

After I learned that Jersey is using JUL, I was sad for a few minutes and carried on with using org.slf4j:jul-to-slf4j. To make it work I had to

private void registerLogback(final ServletContext servletContext) {
    servletContext.addListener(new LogbackConfigListener());

    //this is only necessary if you externalise logback.xml from resources     
    try { LogbackConfigurer.initLogging(servletContext.getRealPath("/WEB-INF/logback.xml")); }
    catch (FileNotFoundException | JoranException e) { e.printStackTrace(); }

    LogManager.getLogManager().reset();
    SLF4JBridgeHandler.removeHandlersForRootLogger();
    SLF4JBridgeHandler.install();
}

in my WebApplicationInitializer.onStartup(ServletContext servletContext).

My ResourceConfig looked like

register(new LoggingFeature(createLogger(), Level.ALL, LoggingFeature.DEFAULT_VERBOSITY, 0)); 

private Logger createLogger() {
    final ConsoleHandler consoleHandler = new ConsoleHandler();
    consoleHandler.setLevel(Level.ALL);

    final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
    logger.setLevel(Level.ALL);
    logger.addHandler(consoleHandler);

    return logger;
}

What logged access to the console. Removing the ConsoleHandler sadly did not end up in logs being logged to the logback-logger, the just got swallowed. But the red log statements on the console gave me the hint that this could be STDERR, albeit their were INFO.

Finally LoggingFeature not logging correctly based on configuration on constructor gave me the missing piece.

My final and working ResourceConfig ended up as

register(new LoggingFeature(Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), Level.INFO, LoggingFeature.DEFAULT_VERBOSITY, 0));

Where LoggingFeature.DEFAULT_LOGGER_NAME and Level.INFO seem to be the crucial part.

In the end I don't know exactly went wrong, but this is the result of my guessing and it works. If this helps anybody I am happy.



回答3:

Slf4jLogger from org.apache.cxf:cxf-core package is another option. It implements java.util.logging.Logger and delegate cals to slf4J.

Jersey server:

ResourceConfig config = new ResourceConfig(HelloWorldResource.class);
config.register(
    new Slf4jLogger(this.getClass().getName(), null));

Jersey client:

ClientBuilder
    .newClient()
    .register(
        new LoggingFeature(
                new Slf4jLogger(this.getClass().getName(), null)));