Log4J:如何将OutputStream或Writer重定向到logger的writer?

jav*_*eed 20 java logging log4j outputstream writer

我有一个方法,它在启动后以异步方式运行,使用OutputStream或Writer作为参数.

它充当OutputStream或Writer的录制适配器(它是我无法更改的第三方API).

我怎么能将Log4J的内部OutputStream或Writer传递给该方法?
...因为Log4J吞下了System.out和System.err,我之前使用过.

Art*_*ves 7

我的建议是,为什么不编写OutputStream呢?!我准备为你写一个,但我在网上找到了这个好例子,看看吧!

LogOutputStream.java

/*
 * Jacareto Copyright (c) 2002-2005
 * Applied Computer Science Research Group, Darmstadt University of
 * Technology, Institute of Mathematics & Computer Science,
 * Ludwigsburg University of Education, and Computer Based
 * Learning Research Group, Aachen University. All rights reserved.
 *
 * Jacareto is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * Jacareto is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with Jacareto; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

package jacareto.toolkit.log4j;


import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import java.io.OutputStream;

/**
 * This class logs all bytes written to it as output stream with a specified logging level.
 *
 * @author <a href="mailto:cspannagel@web.de">Christian Spannagel</a>
 * @version 1.0
 */
public class LogOutputStream extends OutputStream {
    /** The logger where to log the written bytes. */
    private Logger logger;

    /** The level. */
    private Level level;

    /** The internal memory for the written bytes. */
    private String mem;

    /**
     * Creates a new log output stream which logs bytes to the specified logger with the specified
     * level.
     *
     * @param logger the logger where to log the written bytes
     * @param level the level
     */
    public LogOutputStream (Logger logger, Level level) {
        setLogger (logger);
        setLevel (level);
        mem = "";
    }

    /**
     * Sets the logger where to log the bytes.
     *
     * @param logger the logger
     */
    public void setLogger (Logger logger) {
        this.logger = logger;
    }

    /**
     * Returns the logger.
     *
     * @return DOCUMENT ME!
     */
    public Logger getLogger () {
        return logger;
    }

    /**
     * Sets the logging level.
     *
     * @param level DOCUMENT ME!
     */
    public void setLevel (Level level) {
        this.level = level;
    }

    /**
     * Returns the logging level.
     *
     * @return DOCUMENT ME!
     */
    public Level getLevel () {
        return level;
    }

    /**
     * Writes a byte to the output stream. This method flushes automatically at the end of a line.
     *
     * @param b DOCUMENT ME!
     */
    public void write (int b) {
        byte[] bytes = new byte[1];
        bytes[0] = (byte) (b & 0xff);
        mem = mem + new String(bytes);

        if (mem.endsWith ("\n")) {
            mem = mem.substring (0, mem.length () - 1);
            flush ();
        }
    }

    /**
     * Flushes the output stream.
     */
    public void flush () {
        logger.log (level, mem);
        mem = "";
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很高兴找到这个。在我的使用场景中,给定的“LogOutputStream”有以下问题,我需要修复:1.它依赖于 log4j 而不是 commons-logging,我更改了它,并且我硬编码了“logger.info()”,因为 commons-logging 没有级别(据我以秒为单位看到) 1. 它假定换行符是 `\n`,我需要将其更改为 `System.getProperty("line.separator")` 1. 因为它的 `flush()` 不检查 `mem` 是否为空,当包装 `Writer` 在最后一个 `println()` 之后调用 `flush()` 时,您会在输出中得到一个额外的空行 (2认同)

Car*_*sta 7

您可以使用Log4j IOStreams

IOStreams 组件是一个 Log4j API 扩展,它提供了来自 java.io 的许多类,这些类可以在写入另一个 OutputStream 或 Writer 的同时写入 Logger,或者 InputStream 或 Reader 读取的内容可以被 Logger 窃听。

您可以通过以下方式创建 OutputStream:

OutputStream outputStream = IoBuilder
            .forLogger(logger)
            .buildOutputStream();
Run Code Online (Sandbox Code Playgroud)

下面是一个 Appium 的例子,以编程方式启动它并使用 log4j 控制它的日志。

    final Logger logger = LogManager.getLogger(getClass());

    cap = new DesiredCapabilities();
    cap.setCapability("noReset", "false");

    //Build the Appium service
    builder = new AppiumServiceBuilder();
    builder.withIPAddress("127.0.0.1");
    builder.usingPort(4723);
    builder.withCapabilities(cap);
    builder.withArgument(GeneralServerFlag.SESSION_OVERRIDE);
    builder.withArgument(GeneralServerFlag.LOG_LEVEL,"debug");

    //Start the server with the builder
    service = AppiumDriverLocalService.buildService(builder);

    OutputStream outputStream = IoBuilder
            .forLogger(logger)
            .buildOutputStream();
    service.addOutPutStream(outputStream);

    service.start();
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!!!