ฉันจะปิดใช้งานตัวจัดการคอนโซลเริ่มต้นในขณะที่ใช้ java logging API ได้อย่างไร


93

สวัสดีฉันกำลังพยายามใช้การบันทึกจาวาในแอปพลิเคชันของฉัน ฉันต้องการใช้ตัวจัดการสองตัว ตัวจัดการไฟล์และตัวจัดการคอนโซลของฉันเอง ตัวจัดการทั้งสองของฉันทำงานได้ดี การบันทึกของฉันจะถูกส่งไปยังไฟล์และไปที่คอนโซล การบันทึกของฉันจะถูกส่งไปยังตัวจัดการคอนโซลเริ่มต้นซึ่งฉันไม่ต้องการ หากคุณเรียกใช้รหัสของฉันคุณจะเห็นสองบรรทัดพิเศษที่ส่งไปยังคอนโซล ฉันไม่ต้องการใช้ตัวจัดการคอนโซลเริ่มต้น ไม่มีใครรู้วิธีปิดใช้งานตัวจัดการคอนโซลเริ่มต้น ฉันต้องการใช้เครื่องจัดการสองตัวที่ฉันสร้างขึ้นเท่านั้น

Handler fh = new FileHandler("test.txt");
fh.setFormatter(formatter);
logger.addHandler(fh);

Handler ch = new ConsoleHandler();
ch.setFormatter(formatter);
logger.addHandler(ch);

import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class LoggingExample {
    private static Logger logger = Logger.getLogger("test");

    static {
        try {
            logger.setLevel(Level.INFO);

            Formatter formatter = new Formatter() {

                @Override
                public String format(LogRecord arg0) {
                    StringBuilder b = new StringBuilder();
                    b.append(new Date());
                    b.append(" ");
                    b.append(arg0.getSourceClassName());
                    b.append(" ");
                    b.append(arg0.getSourceMethodName());
                    b.append(" ");
                    b.append(arg0.getLevel());
                    b.append(" ");
                    b.append(arg0.getMessage());
                    b.append(System.getProperty("line.separator"));
                    return b.toString();
                }

            };

            Handler fh = new FileHandler("test.txt");
            fh.setFormatter(formatter);
            logger.addHandler(fh);

            Handler ch = new ConsoleHandler();
            ch.setFormatter(formatter);
            logger.addHandler(ch);

            LogManager lm = LogManager.getLogManager();
            lm.addLogger(logger);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        logger.info("why does my test application use the standard console logger ?\n" + " I want only my console handler (Handler ch)\n " + "how can i turn the standard logger to the console off. ??");
    }
}

1
ฉันสามารถแนะนำให้ใช้b.append(formatMessage(arg0))แทนb.append(arg0.getMessage()). ด้วยformatMessageวิธีการที่คุณทำให้ฟอร์แมตเตอร์ของคุณเข้ากันได้กับการใช้งานpublic void log(Level level, String msg, Object param1)และวิธีการที่คล้ายกัน
วิกเตอร์

คำตอบ:


102

ตัวจัดการคอนโซลเริ่มต้นจะเชื่อมต่อกับ root logger ซึ่งเป็นพาเรนต์ของตัวบันทึกอื่น ๆ ทั้งหมดรวมถึงของคุณด้วย ดังนั้นฉันจึงเห็นสองวิธีในการแก้ปัญหาของคุณ:

หากสิ่งนี้มีผลกับคลาสเฉพาะของคุณเท่านั้นวิธีแก้ปัญหาที่ง่ายที่สุดคือปิดใช้งานการส่งบันทึกไปยังผู้บันทึกหลัก:

logger.setUseParentHandlers(false);

หากคุณต้องการเปลี่ยนลักษณะการทำงานนี้สำหรับทั้งแอปของคุณคุณสามารถลบตัวจัดการคอนโซลเริ่มต้นออกจากตัวบันทึกรูททั้งหมดก่อนที่จะเพิ่มตัวจัดการของคุณเอง:

Logger globalLogger = Logger.getLogger("global");
Handler[] handlers = globalLogger.getHandlers();
for(Handler handler : handlers) {
    globalLogger.removeHandler(handler);
}

หมายเหตุ: หากคุณต้องการใช้ตัวจัดการบันทึกเดียวกันในคลาสอื่นด้วยวิธีที่ดีที่สุดคือย้ายการกำหนดค่าบันทึกไปยังไฟล์กำหนดค่าในระยะยาว


2
วิธี setUseParentHandlers ใช้งานได้ขอบคุณ ฉันจะลบตัวจัดการคอนโซลเริ่มต้นออกจาก root logger ได้อย่างไร
loudiyimo

10
คุณยังสามารถใช้ Logger.getLogger ("") ซึ่งใช้ได้กับฉันโดยที่ "global" ใช้ไม่ได้ (อาจเป็นผลมาจาก SLF4J ในการผสมหรือไม่)
sehugg

2
หากคุณต้องการ slf4j ฉันขอแนะนำให้คุณใช้สิ่งนี้ LogManager.getLogManager().reset(); SLF4JBridgeHandler.install();
Somatik

8
"" คือตัวระบุของ root logger "global" คือชื่อคนตัดไม้ (ลูกของรูท) ซึ่งสร้างขึ้นโดยค่าเริ่มต้นและจะใช้ในสถานการณ์การบันทึกแบบง่าย
Paolo Fulgoni

1
คำตอบนี้ไม่ได้ผลสำหรับฉัน แต่คำตอบของ Dominique
BullyWiiPlaza

110

แค่ทำ

LogManager.getLogManager().reset();

1
ขอบคุณนี่คือคำตอบที่ถูกต้อง คำตอบที่ทำเครื่องหมายว่าถูกต้องใช้ไม่ได้
Andreas L.

1
สิ่งนี้ควรชี้ให้เห็นว่าสิ่งนี้จะส่งผลกระทบต่อตัวจัดการทุกตัวสำหรับทุกชื่อLoggerดังนั้นนี่อาจเป็นปัญหาสำหรับระบบบันทึกที่ซับซ้อนมากขึ้น ควรโทรครั้งเดียวเมื่อเริ่มต้นกระบวนการเพื่อให้แน่ใจว่าคนตัดไม้อนาคตจะไม่ได้รับผลกระทบ และแน่นอนผู้ที่ต้องการคอนโซลจะต้องได้รับConsoleHandlerถึงตามที่คาดไว้
AxelH

20

สิ่งนี้แปลก แต่ใช้ Logger.getLogger("global") ไม่ได้ในการตั้งค่าของฉัน (เช่นเดียวกับLogger.getLogger(Logger.GLOBAL_LOGGER_NAME))

อย่างไรก็ตามLogger.getLogger("")ทำงานได้ดี

หวังว่าข้อมูลนี้จะช่วยใครบางคน ...


3
มีใครช่วยบอกเราหน่อยได้ไหมว่าทำไม getLogger (Logger.GLOBAL_LOGGER_NAME) ไม่ทำงาน แต่ getLogger ("") ทำ
deinocheirus

2
@deinocheirus ดูความคิดเห็นของฉันสำหรับคำตอบ
Paolo Fulgoni

9

ทำการรีเซ็ตการกำหนดค่าและตั้งค่าระดับรูทเป็นปิด

LogManager.getLogManager().reset();
Logger globalLogger = Logger.getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME);
globalLogger.setLevel(java.util.logging.Level.OFF);

5

คุณต้องสั่งให้คนตัดไม้ของคุณไม่ส่งข้อความของมันไปยังคนตัดไม้แม่:

...
import java.util.logging.*;
...
Logger logger = Logger.getLogger(this.getClass().getName());
logger.setUseParentHandlers(false);
...

อย่างไรก็ตามควรทำสิ่งนี้ก่อนที่จะเพิ่มตัวจัดการใด ๆ ให้กับคนตัดไม้


สิ่งนี้ใช้ได้ผลในกรณีของฉันแม้ว่าฉันจะต้องเพิ่มตัวจัดการด้วยตนเองสำหรับคนตัดไม้นี้
Sachin Gorade
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.