javaloggingjava.util.logginggigaspaces

Java file logger being hijacked and redirected into a file belonging to another logger (from Gigaspaces API) after creation


I'm seeing a rather odd issue.

I created some standard Java loggers (using Logger.getLogger(), a FileHandle, and a SimpleFormatter.) Those work fine, and output the log file as expected.

Then, I used some classes from the Gigaspaces API (com.gigaspaces.gs-openspaces - included via a Maven dependency), which includes its own logging. After that, all of the output of my loggers ended up inside the Gigaspaces log file (e.g. ~/.m2/repository/com/gigaspaces/logs/2017-03-27~12.46-gigaspaces-service-135.60.146.142-23534.log) instead of in the appropriate log files that they are supposed to be using.

If I then create more loggers after I've initialised Gigaspaces, these new loggers work as expected. Only loggers created before initialising gigaspaces are affected.

I tried poking around in the code for Gigaspaces a little bit, there's a lot of code in there. I didn't see anything immediately obvious.

Am I doing something wrong with setting up my loggers? It doesn't seem right that a library can steal the output from pre-existing loggers that are unrelated to its classes.

The below short test program demonstrates the problem:

    Logger testLog = Logger.getLogger("testlog");
    try {
        FileHandler fh = new FileHandler("testlog.log");
        fh.setFormatter(new SimpleFormatter());
        testLog.addHandler(fh);
    }
    catch (Exception e) {
        // Not important
        e.printStackTrace();
    }

    testLog.log(Level.INFO, "This appears in the main log file");

    // Spin up gigaspaces, even by trying to connect to a space that doesn't exist
    UrlSpaceConfigurer testSpaceConfigurer = new UrlSpaceConfigurer("jini://*/*/testSpace?locators=127.0.01").lookupTimeout(1);
    try {
        GigaSpace g = new GigaSpaceConfigurer(testSpaceConfigurer).gigaSpace();
    }
    catch (Exception e) {
        // This will throw an exception, just ignore it.
    }
    testSpaceConfigurer.close();

    testLog.log(Level.INFO, "This appears in the (wrong) gigaspaces log file");

Solution

  • Overriding the security manager, as suggested by jmehrens, seems to be the way to go. I was able to stop Gigaspaces from stealing the logging by denying it permission to run the reset() methods on the LogManager, thusly:

    // Silly hack to keep gigaspaces from STEALING ALL OUR LOGS
    static {
        System.setSecurityManager(new SecurityManager() {
            @Override
            public void checkPermission(Permission p) {
                if (p instanceof LoggingPermission) {
                    for (StackTraceElement stackTraceElement : new Exception().getStackTrace()) {
                        if (stackTraceElement.getMethodName().equalsIgnoreCase("reset") && stackTraceElement.getClassName().equalsIgnoreCase("java.util.logging.LogManager")) {
                            throw new SecurityException("No resetting the logger!  It is forbidden.");
                        }
                    }
                }
            }
        });
    }
    

    I this case, I just added the override in a static block of the class that creates my gigaspace instances, but anywhere before initialising them should do.