Log4j'ye yığın takibi nasıl gönderilir?


152

Bir e.printStackTrace () yaparsanız, bir istisna yakaladığınızı ve standart çıktıda (örneğin, konsol gibi) aşağıdakileri aldığınızı varsayalım :

java.io.FileNotFoundException: so.txt
        at java.io.FileInputStream.<init>(FileInputStream.java)
        at ExTest.readMyFile(ExTest.java:19)
        at ExTest.main(ExTest.java:7)

Şimdi bunun yerine, aşağıdaki gibi almak için log4j gibi bir logger göndermek istiyorum:

31947 [AWT-EventQueue-0] ERROR Java.io.FileNotFoundException: so.txt
32204 [AWT-EventQueue-0] ERROR    at java.io.FileInputStream.<init>(FileInputStream.java)
32235 [AWT-EventQueue-0] ERROR    at ExTest.readMyFile(ExTest.java:19)
32370 [AWT-EventQueue-0] ERROR    at ExTest.main(ExTest.java:7)

Bunu nasıl yapabilirim?

try {
   ...
} catch (Exception e) {
    final String s;
    ...  // <-- What goes here?
    log.error( s );
}

Yanıtlar:


262

İstisnayı doğrudan kaydediciye iletirsiniz, örn.

try {
   ...
} catch (Exception e) {
    log.error( "failed!", e );
}

Yığın izini oluşturmak log4j'ye kalmıştır.


32
Kaydedici bir nesneyi ilk argümanı için alır ve bunu toString () yapar. Ancak ikinci argüman Atılabilir olmalıdır ve yığın izlemesini görüntüler.
Peter Lawrey

1
Ben ilk Dize ne şeyler asla bilmiyorum, genellikle sadece log.error(e.getLocalizedMessage(), e)gereksiz olan yapıyor sonunda . İlk argüman için null değeri var mı?
Mark Peters

5
@ Mark: Bağlamın istisna mesajından daha uygun bir mesaj vermeye çalışın, örneğin o sırada ne yapmaya çalışıyordu?
skaffman

2
@Mark Peters, Geçerli yönteme bağımsız değişkenleri ileti olarak kaydetmek veya - FileNotFound istisnası için açılmaya çalışılan yolun tam adı olabilir. Neyin yanlış olduğunu bulmanıza yardımcı olabilecek her şey - sadece durumu ayıklayamayacağınızı düşünün.
Thorbjørn Ravn Andersen

1
@skaffman: Aslında kullanıyorum log4j-1.2.8.jarve stackTraceyukarıda bahsettiğim gibi denedim ama sadece günlük dosyama yazdırıyor nullPointerException. Benim kod üzerinde kullanıldı e.printStackTrace()hepsi iz yazdırır. Neden bu Kolavery?
Yubaraj

9

İstisna içermeden bir yığın izlemesi kaydetmek istiyorsanız, bunu yapın:

String message = "";

for(StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {                         
    message = message + System.lineSeparator() + stackTraceElement.toString();
}   
log.warn("Something weird happened. I will print the the complete stacktrace even if we have no exception just to help you find the cause" + message);

3
System.lineSeparator () için +1, bu, uzak bir hizmetten yanıt olarak aldığım bir yığın izini yazdırmama yardımcı oldu
Stephanie

1
Ne aradım, ama burada StringBuilder kullanmalısınız
Xerus

9

Yığın izlemeyi dize olarak da alabilirsiniz ExceptionUtils.getStackTrace.

Bkz. ExceptionUtils.java

Basit log.debugtutmak için sadece kullanıyorum log.error.


4

Sadece başıma geldiği ve faydalı olabileceği için. Eğer bunu yaparsan

try {
   ...
} catch (Exception e) {
    log.error( "failed! {}", e );
}

tüm yığın izini değil, istisnanın başlığını alırsınız. Çünkü kaydedici bir String geçirdiğinizi düşünecektir. {}Skaffman'ın dediği gibi yapmadan


1
Elbette burada tüm yığın izini alacaksınız, ancak {} aynı zamanda (hiçbir ikame olmadan) da yazdırılacak mı?
k1eran

1
o kadar emin olma arkadaşım! Bana işe yaramadı, sadece başlığı aldım. Ancak log4j sürümüne bağlı olabilir
iberbeu

@iberbeu haklı çünkü yığın izini Throwable.toString()döndürmez. ('{}'

4

Skaffman'ın cevabı kesinlikle doğru cevaptır. Gibi tüm kayıt cihazı yöntemleri error(), warn(), info(), debug()ikinci bir parametre olarak Throwable alır:

try {
...
 } catch (Exception e) {
logger.error("error: ", e);
}

Ancak, stacktrace öğesini bir String olarak da ayıklayabilirsiniz. Bazen "{}" yer tutucusunu kullanarak biçimlendirme özelliğinden yararlanmak istiyorsanız yararlı olabilir - yönteme bakın void info(String var1, Object... var2);Bu durumda Dize olarak bir yığın iziniz olduğunu söyleyin, o zaman böyle bir şey yapabilirsiniz:

try {
...
 } catch (Exception e) {
String stacktrace = TextUtils.getStacktrace(e);
logger.error("error occurred for usename {} and group {}, details: {}",username, group, stacktrace);
}

Bu, parametrelenmiş mesajı ve yığın izlemesini yöntem için yaptığı gibi yazdırır: logger.error("error: ", e);

Aslında akıllıca stacktrace bazı gürültü filtreleme seçeneği ile bir dize olarak stacktrace çıkarılması için bir yardımcı program olan bir açık kaynak kitaplık yazdı. Yani, çıkarılan yığın izlemenizle ilgilendiğiniz paket önekini belirlerseniz, bazı alakasız parçalardan filtrelenir ve sizi çok değerli bilgilerle bırakır. Burada, kütüphanenin hangi yardımcı programlara sahip olduğu ve nereden edinileceği (hem maven eserleri ve git kaynakları olarak) hem de nasıl kullanılacağını açıklayan makaleye bağlantı verilmiştir. Yığın izleme filtrelemeli Açık Kaynak Java kitaplığı, Sessiz Dize ayrıştırma Unicode dönüştürücü ve Sürüm karşılaştırması " Stacktrace gürültü filtresi " paragrafına bakın


1
Gömülü ama güzel bir cevap.
payne

Teşekkürler, @payne. Güzel bir geri bildirim için teşekkür ederim
Michael Gantman

2

Bu cevap, sorulan soru ile ilgili değil, sorunun başlığıyla ilgili olabilir.

public class ThrowableTest {

    public static void main(String[] args) {

        Throwable createdBy = new Throwable("Created at main()");
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintWriter pw = new PrintWriter(os);
        createdBy.printStackTrace(pw);
        try {
            pw.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.debug(os.toString());
    }
}

VEYA

public static String getStackTrace (Throwable t)
{
    StringWriter stringWriter = new StringWriter();
    PrintWriter  printWriter  = new PrintWriter(stringWriter);
    t.printStackTrace(printWriter);
    printWriter.close();    //surprise no IO exception here
    try {
        stringWriter.close();
    }
    catch (IOException e) {
    }
    return stringWriter.toString();
}

VEYA

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for(StackTraceElement stackTrace: stackTraceElements){
    logger.debug(stackTrace.getClassName()+ "  "+ stackTrace.getMethodName()+" "+stackTrace.getLineNumber());
}


0

bu iyi log4j hatası / istisna günlüğü - splunk / diğer günlük / izleme s / w tarafından okunabilir. her şey anahtar / değer çiftidir. log4j İstisna nesnesinden yığın izlemesini alıre

    try {
          ---
          ---
    } catch (Exception e) {
        log.error("api_name={} method={} _message=\"error description.\" msg={}", 
                  new Object[]{"api_name", "method_name", e.getMessage(), e});
    }

0
Try this:

catch (Throwable t) {
    logger.error("any message" + t);
    StackTraceElement[] s = t.getStackTrace();
    for(StackTraceElement e : s){
        logger.error("\tat " + e);
    }   
}

-1

Feryat kodu kullanabilirsiniz:

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public class LogWriterUtility {
    Logger log;

    public LogWriterUtility(Class<?> clazz) {
        log = LogManager.getLogger(clazz);
    }

public void errorWithAnalysis( Exception exception) {

        String message="No Message on error";
        StackTraceElement[] stackTrace = exception.getStackTrace();
        if(stackTrace!=null && stackTrace.length>0) {
            message="";
            for (StackTraceElement e : stackTrace) {
                message += "\n" + e.toString();
            }
        }
        log.error(message);


    }

}

Burada sadece arayabilirsiniz: LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

StackTrace'i günlüğünüze yazdıracaktır.


-2

Bunu oluşturun class:

public class StdOutErrLog {

private static final Logger logger = Logger.getLogger(StdOutErrLog.class);

public static void tieSystemOutAndErrToLog() {
    System.setOut(createLoggingProxy(System.out));
    System.setErr(createLoggingProxy(System.err));
}

public static PrintStream createLoggingProxy(final PrintStream realPrintStream) {
    return new PrintStream(realPrintStream) {
        public void print(final String string) {
            logger.info(string);
        }
        public void println(final String string) {
            logger.info(string);
        }
    };
}
}

Bunu kodunuzda arayın

StdOutErrLog.tieSystemOutAndErrToLog();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.