Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java util记录多个处理程序导致重复日志消息_Java_Java.util.logging - Fatal编程技术网

java util记录多个处理程序导致重复日志消息

java util记录多个处理程序导致重复日志消息,java,java.util.logging,Java,Java.util.logging,我遇到的情况是,多个处理程序被设置到一个记录器中。每个处理程序都会替换记录的敏感信息 请参阅下面的SSCCE import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.LogRecord; import java.util.logging.Logger; public class TestLogging { public static v

我遇到的情况是,多个处理程序被设置到一个记录器中。每个处理程序都会替换记录的敏感信息

请参阅下面的SSCCE

import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.logging.Logger;


public class TestLogging {

    public static void main(String[] args) {
        Logger logger=Logger.getLogger(A.class.getName());
        logger.addHandler(new ConsoleHandler(){
            {
                setFormatter(new Formatter() {
                    @Override
                    public String format(LogRecord record) {
                        return record.getMessage().replaceAll("method","replacing method");
                    }
                });
            }
        });
        logger.addHandler(new ConsoleHandler(){
            {
                setFormatter(new Formatter() {
                    @Override
                    public String format(LogRecord record) {
                        return record.getMessage().replaceAll("Logging","replacing logging");
                    }
                });
            }
        });
        logger.setUseParentHandlers(false);

        A a =new A();
        a.method();
    }


    public static class A{

        private static final Logger LOGGER=Logger.getLogger(A.class.getName());

        public void method(){
            LOGGER.info("\nLogging from inside method");
        }
    }
}
我希望输出是“从替换方法内部替换日志记录”,但我得到的是这样的输出

Logging from inside replacing method
replacing logging from inside method

如果我发现已经设置了另一个处理程序,如何将这两个处理程序合并为一个处理程序?

按设计,处理程序不应链接或合并,因为它们的主要目的是执行最终的日志记录处理,如写入文件。我建议稍微改变一下方法,合并格式化程序而不是处理程序。请看以下示例:

public class TestLogging {

public static void main(String[] args) {
    Logger logger = Logger.getLogger(A.class.getName());
    FormatHandler handler = new FormatHandler();
    logger.addHandler(handler);

    handler.addFormatter(new Formatter() {
        @Override
        public String format(LogRecord record) {
            return record.getMessage().replaceAll("method", "replacing method");
        }
    });

    handler.addFormatter(new Formatter() {
        @Override
        public String format(LogRecord record) {
            return record.getMessage().replaceAll("Logging", "replacing logging");
        }
    });
    logger.setUseParentHandlers(false);

    A a = new A();
    a.method();
}

public static class FormatHandler extends ConsoleHandler {

    private List<Formatter> formatters = new ArrayList<>();

    public FormatHandler() {
        setFormatter(new CompositeFormatter());
    }

    public void addFormatter(Formatter f) {
        formatters.add(f);
    }

    class CompositeFormatter extends Formatter {
        @Override
        public synchronized String format(LogRecord record) {
            String modifiedMessage;
            for(Formatter formatter : formatters){
                modifiedMessage = formatter.format(record);
                record.setMessage(modifiedMessage);
            }
            return record.getMessage();
        }
    }
}

public static class A {

    private static final Logger LOGGER = Logger.getLogger(A.class.getName());

    public void method() {
        LOGGER.info("\nLogging from inside method");
    }
    }
}
公共类测试日志{
公共静态void main(字符串[]args){
Logger=Logger.getLogger(A.class.getName());
FormatHandler=新的FormatHandler();
addHandler(handler);
handler.addFormatter(新格式化程序(){
@凌驾
公共字符串格式(日志记录){
return record.getMessage().replaceAll(“方法”,“替换方法”);
}
});
handler.addFormatter(新格式化程序(){
@凌驾
公共字符串格式(日志记录){
return record.getMessage().replaceAll(“记录”,“替换记录”);
}
});
logger.setUseParentHandlers(false);
A=新的A();
a、 方法();
}
公共静态类FormatHandler扩展了ConsoleHandler{
私有列表格式化程序=新的ArrayList();
公共格式化处理程序(){
setFormatter(新的CompositeFormatter());
}
公共void addFormatter(格式化程序f){
格式化程序。添加(f);
}
类复合格式化程序扩展格式化程序{
@凌驾
公共同步字符串格式(日志记录){
字符串修改消息;
for(格式化程序格式化程序:格式化程序){
modifiedMessage=formatter.format(记录);
record.setMessage(modifiedMessage);
}
return record.getMessage();
}
}
}
公共静态A类{
私有静态最终记录器Logger=Logger.getLogger(A.class.getName());
公开作废法(){
LOGGER.info(“\n从内部登录方法”);
}
}
}

它执行您想要的输出。

按设计处理程序不应该被链接或合并,因为它们的主要目的是执行最终的日志记录处理,如写入文件。我建议稍微改变一下方法,合并格式化程序而不是处理程序。请看以下示例:

public class TestLogging {

public static void main(String[] args) {
    Logger logger = Logger.getLogger(A.class.getName());
    FormatHandler handler = new FormatHandler();
    logger.addHandler(handler);

    handler.addFormatter(new Formatter() {
        @Override
        public String format(LogRecord record) {
            return record.getMessage().replaceAll("method", "replacing method");
        }
    });

    handler.addFormatter(new Formatter() {
        @Override
        public String format(LogRecord record) {
            return record.getMessage().replaceAll("Logging", "replacing logging");
        }
    });
    logger.setUseParentHandlers(false);

    A a = new A();
    a.method();
}

public static class FormatHandler extends ConsoleHandler {

    private List<Formatter> formatters = new ArrayList<>();

    public FormatHandler() {
        setFormatter(new CompositeFormatter());
    }

    public void addFormatter(Formatter f) {
        formatters.add(f);
    }

    class CompositeFormatter extends Formatter {
        @Override
        public synchronized String format(LogRecord record) {
            String modifiedMessage;
            for(Formatter formatter : formatters){
                modifiedMessage = formatter.format(record);
                record.setMessage(modifiedMessage);
            }
            return record.getMessage();
        }
    }
}

public static class A {

    private static final Logger LOGGER = Logger.getLogger(A.class.getName());

    public void method() {
        LOGGER.info("\nLogging from inside method");
    }
    }
}
公共类测试日志{
公共静态void main(字符串[]args){
Logger=Logger.getLogger(A.class.getName());
FormatHandler=新的FormatHandler();
addHandler(handler);
handler.addFormatter(新格式化程序(){
@凌驾
公共字符串格式(日志记录){
return record.getMessage().replaceAll(“方法”,“替换方法”);
}
});
handler.addFormatter(新格式化程序(){
@凌驾
公共字符串格式(日志记录){
return record.getMessage().replaceAll(“记录”,“替换记录”);
}
});
logger.setUseParentHandlers(false);
A=新的A();
a、 方法();
}
公共静态类FormatHandler扩展了ConsoleHandler{
私有列表格式化程序=新的ArrayList();
公共格式化处理程序(){
setFormatter(新的CompositeFormatter());
}
公共void addFormatter(格式化程序f){
格式化程序。添加(f);
}
类复合格式化程序扩展格式化程序{
@凌驾
公共同步字符串格式(日志记录){
字符串修改消息;
for(格式化程序格式化程序:格式化程序){
modifiedMessage=formatter.format(记录);
record.setMessage(modifiedMessage);
}
return record.getMessage();
}
}
}
公共静态A类{
私有静态最终记录器Logger=Logger.getLogger(A.class.getName());
公开作废法(){
LOGGER.info(“\n从内部登录方法”);
}
}
}

它执行您想要的输出。

不确定为什么投票关闭它。有礼貌地说为什么这需要关闭,甚至是在投票否决一个问题时。不知道为什么这被投票否决。有礼貌地说,为什么需要关闭这个问题,甚至在投票否决一个问题时。谢谢!。。现在将更改我的设计…)嘿不过我有个问题。。我们不能将控制台句柄和文件句柄添加到记录器并格式化消息吗?。。我已经被handler替换为FileHandler,它将在生产系统中使用。但是我想把它记录到我的开发人员机器上的控制台上(为什么不呢?)只要把CompositeFormatter也添加到FileHandler中就行了。然后回到同一个问题上,在控制台中同样的消息被记录了两次,我看到了。如果您想在开发和生产环境中使用不同的记录器实现,那么引入某种“开发模式”标志或构建概要文件。否则你的应用程序将永远不会知道它运行在哪种环境中。谢谢!。。现在将更改我的设计…)嘿不过我有个问题。。我们不能将控制台句柄和文件句柄添加到记录器并格式化消息吗?。。我已经被handler替换为FileHandler,它将在生产系统中使用。但是我想把它记录到我的开发人员机器上的控制台上(为什么不呢?)只要把CompositeFormatter也添加到FileHandler中就行了。然后回到同一个问题上,在控制台中同样的消息被记录了两次,我看到了。如果您想在开发和生产环境中使用不同的记录器实现,那么引入某种“开发模式”标志或构建概要文件。否则,你的应用程序永远不会知道它运行在哪种环境中