Slf4j打印異常的堆棧信息


一、前言

  直接用logger.info("異常信息為:"+e)或者logger.info(e.getMessage())只能記錄到異常的描述信息,卻沒有其異常具體發生在哪一行代碼。
這樣即使通過日志發現出現了異常,也沒法馬上定位問題。
因此就催生了一個想法,打印日志是否能像在IDE本地跑程序時出現未捕獲的異常時,控制台能打印出完整的錯誤堆棧信息。

 

二、問題場景

  日常開發中,經常在service實現層使用try-catch-finally保證代碼的健壯性, 直接用logger.info("異常信息為:"+e)或者logger.info(e.getMessage())只能記錄到異常的描述信息,無法打印完整異常堆棧信息,無法定位其異常具體發生在哪一行代碼,當面對比較復雜的代碼,那么排查問題將會非常麻煩。

下文將簡單重現這類場景,並得到相應的解決方法。

1、不加try-catch

示例:

    @GetMapping("/hello")
    public String sayHello(){
        logger.info("hello Sfl4j + logback......");
        int i = 3/0;
        return helloService.sayHello();
    }

運行結果:

即:當不加try-catch的時候,當出現了意料之外的運行時異常,控制台是能夠能打印出完整的錯誤信息。

2、加上try-catch

示例:

    @GetMapping("/hello")
    public String sayHello(){
        logger.info("hello Sfl4j + logback......");
        try{
            int i = 3/0;
        }catch (Exception e){
            logger.info("計算出錯1:"+e);
            logger.info("計算出錯2:"+e.getMessage());
        }
        return helloService.sayHello();
 }

運行結果:

即:try-catch代碼中使用logger.info("異常信息為:"+e)或者logger.info(e.getMessage()),只能打印異常描述信息,無法打印異常堆棧,無法定位具體出錯位置。

三、解決方法

--->打印出完整的異常堆棧信息方法

方法1:e.printStackTrace();

示例:

    @GetMapping("/hello")
    public String sayHello(){
        logger.info("hello Sfl4j + logback......");
        try{
            int i = 3/0;
        }catch (Exception e){
            e.printStackTrace();
        }
        return helloService.sayHello();
    }

運行結果:

注:

這種方式很占內存空間,尤其生產環境不能過多使用。

並且這種方式只是控制台打印,日志文件中不打印。

 

方法2:

logger.error(String msg, Throwable t);------>logger.error(e.getMessage(),e); 

或者

logger.info(String msg, Throwable t);------>logger.info(e.getMessage(),e); 

示例:

    @GetMapping("/hello")
    public String sayHello(){
        logger.info("hello Sfl4j + logback......");
        try{
            int i = 3/0;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
//            logger.info(e.getMessage(),e);
        }
        return helloService.sayHello();
    }

運行結果:

 

使用擴展:

如果msg含有變量,SLF4J 1.6.0之前版本一般用String.format方法格式化msg。

SLF4J 1.6.0版本之后,

error(String format, Object... arguments) 
info(String format, Object... arguments) 
方法也會打印異常堆棧信息,只不過規定Throwable對象必須為最后一個參數.如果不遵守這個規定,異常堆棧信息不會打印出來。

官網示例:

String s = "Hello world";
try {
  Integer i = Integer.valueOf(s);
} catch (NumberFormatException e) {
  logger.error("Failed to format {}", s, e);
}

使用示例:

    @GetMapping("/hello")
    public String sayHello(){
        logger.info("hello Sfl4j + logback......");
        try{
            int i=3/0;
        }catch(Exception e){
            logger.error("錯誤消息:{}",e.getMessage(),e);
        }
        return helloService.sayHello();
    }
}

運行示例:

 

小結:

1、Slf4j打印異常堆棧信息使用:

logger.error(String msg, Throwable t);------>logger.error(e.getMessage(),e); 

或者

logger.info(String msg, Throwable t);------>logger.info(e.getMessage(),e); 

規范示例:

 logger.error("錯誤消息:{}",e.getMessage(),e);

2、異常信息Exception e 的相關方法

  • e.toString():獲得異常類型和錯誤信息描述
  • e.getMessage():獲得錯誤信息描述
  • e.printStackTrace():在控制台打印出異常堆棧(異常類型、錯誤信息描述和出錯位置等)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM