Java 文件记录器在创建后被劫持并重定向到属于另一个记录器(来自 Gigaspaces API)的文件
Java file logger being hijacked and redirected into a file belonging to another logger (from Gigaspaces API) after creation
我看到一个相当奇怪的问题。
我创建了一些标准的 Java 记录器(使用 Logger.getLogger()、一个 FileHandle 和一个 SimpleFormatter。)
这些工作正常,并按预期输出日志文件。
然后,我使用了 Gigaspaces API 中的一些 类(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");
您必须 pin the "testlog" logger 否则您可能会丢失所有应用到它的更改。
修改记录器需要权限。一种选择可能是使用不允许 GigaSpaces 重定向您的日志记录的自定义安全管理器。
如果 GigaSpaces 正在调用 LogManager.reset(),那么绕过删除处理程序的一种骇人听闻、肮脏的方法是扩展 FileHandler 并覆盖 equals。
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");
}
}
按照 jmehrens 的建议,覆盖安全管理器似乎是可行的方法。
我能够通过拒绝 Gigaspaces 对 LogManager 上的 运行 reset() 方法的权限来阻止 Gigaspaces 窃取日志记录,因此:
// 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 实例的 class 的静态块中添加了覆盖,但在初始化它们之前的任何地方都应该这样做。
我看到一个相当奇怪的问题。
我创建了一些标准的 Java 记录器(使用 Logger.getLogger()、一个 FileHandle 和一个 SimpleFormatter。) 这些工作正常,并按预期输出日志文件。
然后,我使用了 Gigaspaces API 中的一些 类(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");
您必须 pin the "testlog" logger 否则您可能会丢失所有应用到它的更改。
修改记录器需要权限。一种选择可能是使用不允许 GigaSpaces 重定向您的日志记录的自定义安全管理器。
如果 GigaSpaces 正在调用 LogManager.reset(),那么绕过删除处理程序的一种骇人听闻、肮脏的方法是扩展 FileHandler 并覆盖 equals。
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");
}
}
按照 jmehrens 的建议,覆盖安全管理器似乎是可行的方法。 我能够通过拒绝 Gigaspaces 对 LogManager 上的 运行 reset() 方法的权限来阻止 Gigaspaces 窃取日志记录,因此:
// 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 实例的 class 的静态块中添加了覆盖,但在初始化它们之前的任何地方都应该这样做。