Enable logging for JDK class programmatically

2019-05-11 06:01发布

Ok, the case is simple. I need to be able to enable/disable logging for a JDK class (HttpURLConnection) programmatically.

public class HttpLoggingTest {

    /**
      Just a dummy to get some action from HttpURLConnection
    */
    private static void getSomething(String urlStr) throws MalformedURLException, IOException {
        System.out.println("----- " + urlStr);
        HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();

        for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
            System.out.println(header.getKey() + "=" + header.getValue());
        }
        conn.disconnect();

    }

    public static void main(String[] args) throws MalformedURLException, IOException {

        // HERE : Enable JDK logging for class
        // sun.net.www.protocol.http.HttpURLConnection
        getSomething("http://www.goodle.com");

        // HERE: Disable JDK logging for class
        // sun.net.www.protocol.http.HttpURLConnection
        getSomething("http://www.microsoft.com");           
    }        
}

In other words: before the first URL call the logging must be enabled and then disabled before the next call.

That is the challenge !
I'm unable to figure out how to do it.

Must work with Java 7.

Note:

I can do it by using configuration file, logging.properties :

sun.net.www.protocol.http.HttpURLConnection.level = ALL

but I want to have a programmatic solution.

UPDATE

Here's code that works in Java 6 but not in Java 7:

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;    

public class HttpLoggingTest {

    /**
      Just a dummy to get some action from HttpURLConnection
    */
    private static void getSomething(String urlStr) throws MalformedURLException, IOException {
        System.out.println("----- " + urlStr);
        HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();

        for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
            System.out.println(header.getKey() + "=" + header.getValue());
        }
        conn.disconnect();            
    }

    private static void enableConsoleHandler() {
        //get the top Logger
        Logger topLogger = java.util.logging.Logger.getLogger("");

        // Handler for console (reuse it if it already exists)
        Handler consoleHandler = null;
        //see if there is already a console handler
        for (Handler handler : topLogger.getHandlers()) {
            if (handler instanceof ConsoleHandler) {
                //found the console handler
                consoleHandler = handler;
                break;
            }
        }

        if (consoleHandler == null) {
            //there was no console handler found, create a new one
            consoleHandler = new ConsoleHandler();
            topLogger.addHandler(consoleHandler);
        }
        consoleHandler.setLevel(Level.ALL);
    }

    public static void main(String[] args) throws MalformedURLException, IOException {

        enableConsoleHandler();

        final Logger httpLogger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");


        // Enable JDK logging for class
        //sun.net.www.protocol.http.HttpURLConnection
        httpLogger.setLevel(java.util.logging.Level.FINE);
        getSomething("http://www.goodle.com");

        // Disable JDK logging for class
        // sun.net.www.protocol.http.HttpURLConnection
        httpLogger.setLevel(java.util.logging.Level.INFO);
        getSomething("http://www.microsoft.com");           
    }        
}

UPDATE2

In order to make sure that a solution only enables output from our target class (and not all sorts of other JDK internal classes) I've created this minimal JAXB example. Here JAXB is simply an example of 'something else', it could have been any other part of the JDK that also use PlatformLogger.

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * Minimal dummy JAXB example. Only purpose is to provoke
 * some JAXB action. Non-prod quality!
 */
@XmlRootElement(name = "book")
public class Celebrity {

    @XmlElement
    public String getFirstName() {
        return "Marilyn";
    }

    @XmlElement
    public String getLastName() {
        return "Monroe";
    }

    public void printXML() {
        JAXBContext context;
        try {
            context = JAXBContext.newInstance(Celebrity.class);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.marshal(this, System.out);
        } catch (JAXBException ex) {
        }
    }
}

Instantiate an instance of the Celebrity class and call printXML(). Put that into getSomething() method. This must not generate JAXB internal logging output ... or else you've enabled logging for more than you thought.

标签: java logging
2条回答
兄弟一词,经得起流年.
2楼-- · 2019-05-11 06:25

Try:

java.util.logging.Logger logger = 
        java.util.logging.Logger.getLogger(
            "sun.net.www.protocol.http.HttpURLConnection");
logger.setLevel(java.util.logging.Level.FINE);
查看更多
三岁会撩人
3楼-- · 2019-05-11 06:29

Stumbled over PlatformLoggingMXBean the other day. I'll need to try something like:

PlatformLoggingMXBean platformLoggingMXBean = 
    ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class);
platformLoggingMXBean.setLoggerLevel(
    "sun.net.www.protocol.http.HttpURLConnection", "FINE");

and see it it works.

查看更多
登录 后发表回答