Java 将System.out.println重定向到日志
在我的项目测试套件中,大量使用了Java 将System.out.println重定向到日志,java,logging,Java,Logging,在我的项目测试套件中,大量使用了 System.out.println 我正在尝试将这些输出重定向到日志文件(通过配置或从单点重定向,而不重构整个项目),以便在需要时禁用这些输出以提高性能。我使用log4j进行日志记录。 有人知道这可能吗?如果是,怎么做? 提前谢谢。如果可能的话,我的建议是重构。 对于可能的解决方案,请检查这些类似的问题 使用shell重定向。找出项目的“java”调用,如果您使用的是最模糊的类UNIX系统,那么ps aux | grep java将有所帮助 然后用>/p
System.out.println
我正在尝试将这些输出重定向到日志文件(通过配置或从单点重定向,而不重构整个项目),以便在需要时禁用这些输出以提高性能。我使用log4j进行日志记录。
有人知道这可能吗?如果是,怎么做?
提前谢谢。如果可能的话,我的建议是重构。 对于可能的解决方案,请检查这些类似的问题
使用shell重定向。找出项目的“java”调用,如果您使用的是最模糊的类UNIX系统,那么ps aux | grep java将有所帮助 然后用>/path/to/logfile运行这个命令。例如:
java -jar myjar.jar -cp path/to/lib.jar:path/to/otherlib.jar com.bigcorp.myproject.Main > /var/log/myproject.log
我认为您可以使用将输出设置为文件输出流。然后您可以将这一行放在BeforeClass方法中。我喜欢使用BaseTest类,并将这行代码放在该类的beforeclass方法中。然后让所有测试用例扩展这个类。公共类递归日志记录{
public class RecursiveLogging {
public static void main(String[] args) {
System.setOut(new PrintStream(new CustomOutputStream()));
TestMyException.testPrint();
}
}
class CustomOutputStream extends OutputStream {
private Logger logger = Logger.getLogger(this.getClass());
@Override
public final void write(int b) throws IOException {
// the correct way of doing this would be using a buffer
// to store characters until a newline is encountered,
// this implementation is for illustration only
logger.info((char) b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
byte[] pb = new byte[len];
for (int i = 0 ; i < len ; i++) {
pb[i] = (b[off + i]);
}
String str = new String(pb);
logger.info(str);
}
}
公共静态void main(字符串[]args){
系统设置(新的打印流(新的CustomOutputStream());
TestMyException.testPrint();
}
}
类CustomOutputStream扩展了OutputStream{
私有记录器=Logger.getLogger(this.getClass());
@凌驾
公共最终无效写入(int b)引发IOException{
//正确的方法是使用缓冲区
//要存储字符直到遇到换行符,
//此实现仅用于说明
logger.info((char)b);
}
@凌驾
公共无效写入(字节[]b,int off,int len)引发IOException{
如果(b==null){
抛出新的NullPointerException();
}如果((关闭<0)| |(关闭>b.length)| |(len<0)||
((关+长)>b.length)| |((关+长)<0)){
抛出新的IndexOutOfBoundsException();
}else if(len==0){
返回;
}
字节[]pb=新字节[len];
对于(int i=0;i
鉴于最好更换System.out.println()
,有时我们别无选择。无论如何,我已经为此做了一些实用程序:
SystemOutToSlf4j.enableForClass(MyClass.class)
然后,来自MyClass的所有println将重定向到记录器。
不是这个问题。本页非常详细地解释了这一点:不要因为重定向系统而犹豫不决,而是咬紧牙关,使用一个像样的IDE,一次过重构整个代码库,用log.info(…)代替。在方法
println(String)
调用getLogger(caller.getClass())
应替换为getLogger(caller.getClassName())
,否则为SLF4J配置的日志框架将打印stackTraceeElement的类名。
public class SystemOutToSlf4j extends PrintStream {
private static final PrintStream originalSystemOut = System.out;
private static SystemOutToSlf4j systemOutToLogger;
/**
* Enable forwarding System.out.println calls to the logger if the stacktrace contains the class parameter
* @param clazz
*/
public static void enableForClass(Class clazz) {
systemOutToLogger = new SystemOutToSlf4j(originalSystemOut, clazz.getName());
System.setOut(systemOutToLogger);
}
/**
* Enable forwarding System.out.println calls to the logger if the stacktrace contains the package parameter
* @param packageToLog
*/
public static void enableForPackage(String packageToLog) {
systemOutToLogger = new SystemOutToSlf4j(originalSystemOut, packageToLog);
System.setOut(systemOutToLogger);
}
/**
* Disable forwarding to the logger resetting the standard output to the console
*/
public static void disable() {
System.setOut(originalSystemOut);
systemOutToLogger = null;
}
private String packageOrClassToLog;
private SystemOutToSlf4j(PrintStream original, String packageOrClassToLog) {
super(original);
this.packageOrClassToLog = packageOrClassToLog;
}
@Override
public void println(String line) {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
StackTraceElement caller = findCallerToLog(stack);
if (caller == null) {
super.println(line);
return;
}
org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(caller.getClass());
log.info(line);
}
public StackTraceElement findCallerToLog(StackTraceElement[] stack) {
for (StackTraceElement element : stack) {
if (element.getClassName().startsWith(packageOrClassToLog))
return element;
}
return null;
}
}