log4j에 stacktrace를 보내는 방법은 무엇입니까?


152

e.printStackTrace () 를 수행하면 예외를 잡아서 표준 출력 (예 : 콘솔)에서 다음을 얻습니다 .

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

이제 이것을 log4j와 같은 로거로 보내서 다음을 얻습니다.

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)

어떻게해야합니까?

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

답변:


262

예외를 로거에 직접 전달합니다. 예 :

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

스택 추적을 렌더링하는 것은 log4j에 달려 있습니다.


32
로거는 첫 번째 인수에 대한 객체를 가져 와서 toString ()합니다. 그러나 두 번째 인수는 Throwable이어야하며 스택 추적을 표시합니다.
Peter Lawrey

1
나는 첫 번째 문자열에 무엇을 넣을 지 모른다. 일반적으로 나는 log.error(e.getLocalizedMessage(), e)완전히 중복되는 일 을 끝내게된다 . 첫 번째 인수에 대해 널을 처리합니까?
Mark Peters

5
@Mark : 예외 메시지보다 컨텍스트와 관련된 메시지를 제공하십시오. 예를 들어 실제로 실제로 무엇을 시도 했습니까?
skaffman

2
@Mark Peters, 현재 메소드에 인수를 메시지로 기록하거나 FileNotFound 예외의 경우 열려고 시도한 경로의 전체 이름을 기록하는 것이 좋은 예입니다. 무엇이 잘못되었는지 알아내는 데 도움이되는 것은 상황을 디버깅 할 수 없다고 생각하면됩니다.
Thorbjørn Ravn Andersen 님이

1
@skaffman : 실제로 사용 log4j-1.2.8.jar하고 있으며 stackTrace로그 파일에 모두 인쇄하고 싶었 으므로 위에서 언급 한 것처럼 시도했지만 내 로그 파일에만 인쇄하고 nullPointerException있습니다. 내 코드에 사용되어 e.printStackTrace()모든 추적을 인쇄합니다. 왜이 콜라 이어?
유 바라지

9

예외없이 스택 추적을 기록하려면 다음을 수행하십시오.

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 ()에 +1을 사용하면 원격 서비스에서 응답으로 얻은 스택 추적을 인쇄하는 데 도움이되었습니다.
Stephanie

1
내가 무엇을 검색했지만 여기에 StringBuilder를 사용해야합니다
Xerus

9

를 통해 스택 추적을 문자열로 얻을 수도 있습니다 ExceptionUtils.getStackTrace.

참조 : ExceptionUtils.java

나는 간결하게 log.debug유지하기 위해 만 사용합니다 log.error.


4

그것이 나에게 일어난 것이기 때문에 유용 할 수 있습니다. 이렇게하면

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

전체 스택 추적이 아닌 예외 헤더를 가져옵니다. 로거는 문자열을 전달한다고 생각하기 때문입니다. {}skaffman이 말한대로 하지 마십시오


1
확실히 여기에 전체 스택 추적이 표시되지만 {}도 그대로 사용됩니다 (대체없이)?
k1eran

1
내 친구를 확신하지 마십시오! 그것은 나에게 작동하지 않았다, 나는 헤더 만 가지고있다. 그래도 log4j의 버전에 의존 할 수 있습니다
iberbeu

Throwable.toString()스택 트레이스를 반환하지 않기 때문에 @iberbeu가 옳습니다 . ( '{}'과 (와) 관련이있는 로거를 사용한다고 가정합니다.

3

skaffman의 대답은 확실히 정답입니다. 같은 모든 로거 방법은 error(), warn(), info(), debug()두 번째 매개 변수로의 Throwable을 :

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

그러나 stacktrace를 String으로 추출 할 수도 있습니다. "{}"자리 표시자를 사용하여 형식 지정 기능을 활용하려는 경우에 유용 할 수 있습니다 void info(String var1, Object... var2);.이 경우 문자열 참조 stacktrace가 있다고 가정하면 실제로 다음과 같은 작업을 수행 할 수 있습니다.

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

이렇게하면 매개 변수화 된 메시지와 스택 추적이 메소드와 동일한 방식으로 끝에 인쇄됩니다. logger.error("error: ", e);

실제로 스택 트레이스에서 일부 노이즈를 스마트하게 필터링하는 옵션을 사용하여 스택 트레이스를 String으로 추출하는 유틸리티가있는 오픈 소스 라이브러리를 작성했습니다. 즉, 추출 된 스택 추적에 관심이있는 패키지 접두사를 지정하면 관련이없는 부분이 필터링되어 매우 정교 한 정보가 남습니다. 다음은 라이브러리에있는 유틸리티와 라이브러리를 얻을 수있는 위치 (maven 아티팩트 및 git 소스)와 사용 방법을 설명하는 기사 링크입니다. 스택 추적 필터링, 자동 문자열 구문 분석 유니 코드 변환기 및 버전 비교가 포함 된 오픈 소스 Java 라이브러리 "스택 추적 노이즈 필터 " 단락을 참조하십시오.


묻었지만 좋은 대답.
payne

감사합니다, @payne. 나는 좋은 의견을 주셔서 감사합니다
마이클 Gantman

2

이 답변은 질문과 관련된 것이 아니라 질문의 제목과 관련이있을 수 있습니다.

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());
    }
}

또는

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();
}

또는

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

1

Log4j 2에서는 Logger.catching () 을 사용하여 포착 된 예외에서 스택 추적 을 기록 할 수 있습니다 .

    try {
        String msg = messages[messages.length];
        logger.error("An exception should have been thrown");
    } catch (Exception ex) {
        logger.catching(ex);
    }

0

이것은 좋은 log4j 오류 / 예외 로깅이 될 것입니다-splunk / other logging / monitoring s / w로 읽을 수 있습니다. 모든 것이 키-값 쌍의 형태입니다. log4j는 예외 obj에서 스택 추적을 얻습니다.e

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


-1

다음 코드를 사용할 수 있습니다.

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);


    }

}

여기서 당신은 전화 할 수 있습니다 : LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

로그에 stackTrace를 인쇄합니다.


-2

이것을 만드십시오 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);
        }
    };
}
}

코드에서 이것을 호출하십시오.

StdOutErrLog.tieSystemOutAndErrToLog();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.