Регистратор файлов Java был захвачен и перенаправлен в файл, принадлежащий другому регистратору (из Gigaspaces API) после создания

Я вижу довольно странную проблему.

Я создал несколько стандартных регистраторов Java (используя Logger.getLogger(), FileHandle и SimpleFormatter.) Они работают нормально и выводят файл журнала, как и ожидалось.

Затем я использовал некоторые классы из API Gigaspaces (com.gigaspaces.gs-openspaces - включенные через зависимость Maven), который включает в себя собственную регистрацию. После этого все выходные данные моих регистраторов оказались в файле журнала Gigaspaces (например, ~/.m2/repository/com/gigaspaces/logs/2017-03-27~12.46-gigaspaces-service-135.60.146.142-23534.log) вместо соответствующих файлов журналов, которые они должны использовать.

Если после инициализации Gigaspaces я затем создаю больше регистраторов, эти новые регистраторы работают должным образом. Это касается только регистраторов, созданных до инициализации гигапространств.

Я попытался немного покопаться в коде Gigaspaces, там много кода. Я не видел ничего сразу очевидного.

Я делаю что-то не так с настройкой своих регистраторов? Неправильно, что библиотека может украсть выходные данные из уже существующих регистраторов, которые не связаны с ее классами.

Нижеприведенная короткая тестовая программа демонстрирует проблему:

    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");

2 ответа

Решение

Как представляется, переопределение менеджера по безопасности, как предлагает jmehrens, - это путь. Я смог остановить Gigaspaces от кражи журналирования, отказав ему в разрешении запускать методы reset() на LogManager, таким образом:

// 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.");
                    }
                }
            }
        }
    });
}

В этом случае я просто добавил переопределение в статическом блоке класса, который создает мои экземпляры Gigaspace, но в любом случае перед их инициализацией следует это сделать.

Вы должны закрепить регистратор "testlog", иначе вы рискуете потерять все изменения, которые вы к нему применяете.

Для изменения регистраторов требуются разрешения. Одним из вариантов может быть использование настраиваемого менеджера безопасности, который не позволяет GigaSpaces перенаправлять ваши записи.

Если GigaSpaces вызывает LogManager.reset (), то один хакерский, вонючий, грязный способ обойти удаление вашего обработчика - это расширение FileHandler и переопределение равных.

public class GigaSpaces {

    //Pin the logger
    private static final Logger testLog = Logger.getLogger("testlog");
    static {
        try {
            FileHandler fh = new FileHandler("testlog.log") {
                public boolean equals(Object o) {
                    return false; //Pure Evil.
                }
            };

            fh.setFormatter(new SimpleFormatter());
            testLog.addHandler(fh);
        }
        catch (Exception e) {
            // Not important
            e.printStackTrace();
        }
    }

    public void foo() throws Throwable {
        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.
        } finally {
            testSpaceConfigurer.close();
        }

        testLog.log(Level.INFO, "This appears in the (wrong) gigaspaces log file");
    }
}
Другие вопросы по тегам