0731印刷異常のスタック情報

9693 ワード

logger文に異常なスタック情報を記録させる
前言
ログを追加します.
実はCSNDにも似たような文章がありますが、私も考えたことがあるので、私も記録したいです.logger.info(" :"+e)またはlogger.info(e.getMessage())を直接使用すると、異常の記述情報しか記録できませんが、その異常が具体的にどの行のコードで発生しているかは記録されません.これにより、ログで異常が発見されても、すぐに問題を特定することはできません.そのため、ideaローカルでプログラムを走っているときにキャプチャされていない異常が発生したときのように、コンソールが完全なエラースタック情報を印刷し、logger文に記録できるかどうかという考えが生まれた.
説明
インタフェースを書くとき、後でログの位置付けの問題を簡単に見るために、serviceのloggerログを改造し、すべてのlogger文を1つの記録につなぎ、印刷しました.したがって、サービス層の最外層ではtry catch finallyが使用されます.これにより、1つのリクエストのログが統一され、複数のリクエストによるログ挿入レコードは発生しません.ログ:
[2018-06-26 17:09:54.038] -- [http-nio-8079-exec-27] -- [INFO] -- [OrderServiceImpl.java:513 >>>> Method = query] -- [Content = 
********【1121    】  :useruuid==d86a732d-2da6-11e8-xxx-xxxx,source==1,phone==135705xxxxx,orderNo==201806260000xxxxx
********【1121    】  :com.uroad.etc.dto.OrderInput@6ab68cb3[useruuid=d86a732d-2da6-11e8-xxx-xxxx,orderNo=2018062600xxxx,source=1]
********【1121    】  :request decode data:1121110802CCF5B968C014E702xxxxx
********【1121    】  :response deceode data:90001A4B0D01060F103136303832323xxxxxx
********【1121    】updateTradStateAndPushMsgByCardNo      :1,cardNo:1608227140xxx
********【1121    】  :com.uroad.etc.dto.OrderOutput@42879e4b[tradeText=2018-06-26 17:09:31,tradeDate=2018xxx,tradTime=170xxx,orderNo=201806260000003xxx,tradMoney=1,tradState=3,serialNo=,cardNo=160822714xxx,terminalNo=,billState=,orderType=1,cardType=,plateNo=,payChannel=6]]

しかし、このようにして悪い点があります.異常が発生した場合、キャプチャしたり、異常情報を印刷したりしますが、異常情報が誤った情報を正確に位置決めできないということです.
[2018-07-31 21:41:04] -- [main] -- [INFO] -- [TestException.java:17 >>>> Method = main] -- [Content = 
     :java.lang.NullPointerException]

サービス層コードが簡単であれば、異常が発生した場所をすぐに特定することができます.しかし、サービス層がやや複雑で、コードが少し多いと、どこが異常なのか迅速に見つけることができません.
私たちがローカルでテストしたとき、予想外の実行時異常が発生した場合、コンソールは完全なエラー情報を印刷することができます.
public static void main(String[] args) {
    String s = "1";
    if(s.equals("1")){
        s=null;
    }
    s.equals("1");
}

コンソールは完全な情報を印刷できます.
Exception in thread "main" java.lang.NullPointerException
    at TestException.main(TestException.java:14)

これにより、エラーがTestExceptionの14行目、すなわちs.equals("1)であることをすぐに知ることができ、オブジェクトsが空のオブジェクトであることを示すことができます.
しかし、サービス層の最外層でtry catchを使用しているため、私のコードはこのようになっています.
public static void main(String[] args) {
    try {
        String s = "1";
        if(s.equals("1")){
            s=null;
        }
        s.equals("1");
    }catch (Exception e){
        logger.info("     :" + e);
    }
}

これにより、異常が発生した場合、異常情報は次のようになります.
[2018-07-31 21:46:04] -- [main] -- [INFO] -- [TestException.java:17 >>>> Method = main] -- [Content = 
     :java.lang.NullPointerException]

このように,17行目のlogger文で印刷された情報であることしか知ることができない.しかし、私が前に言ったように、サービスレイヤでtry catch finallyを使用してログを処理しているので、logger文が1つしかないので、エラーがどこで発生しているのか分かりません.
解決策
そこで、完全なスタック情報を印刷できる方法があるかどうかを考えてみました.最終的には、ネット上で見つけました.参考記事:https://blog.csdn.net/wwsscc168/article/details/51837662
public static String toStackTrace(Exception e)
{
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);

    try
    {
        e.printStackTrace(pw);
        return sw.toString();
    }
    catch(Exception e1)
    {
        return "";
    }
}

ただ、これでメモリが十分に取られるかどうかはわかりません.とてもスペースがあります.
解決策2
これにより、エラー位置:logger.info(e.getMessage(),e);も印刷できます.
出力:
[2018-07-31 21:52:57] -- [main] -- [INFO] -- [TestException.java:17 >>>> Method = main] -- [Content = 
null]
java.lang.NullPointerException: null
    at TestException.main(TestException.java:15)

これでもいいです.
logger.info("     :",e);

しかし、これには個別のlogger文が必要です.
スレッド番号で追跡できます...
さいてきかいけつほう
JVMの構成を変更する必要もなく、Writeストリームを使用する必要もない新しい方法が見つかりました.
public static String logClzInfo(Exception e) {
    StringBuffer sb = new StringBuffer();
    sb.append(e.getClass() + " " + e.getMessage() + "
"
); StackTraceElement[] stackTraceElement = e.getStackTrace(); for (StackTraceElement traceElement : stackTraceElement) { sb.append("\tat " + traceElement + "
"
); } return sb.toString(); }

これによりcatchでパラメータeにより完全なエラー情報を取得できる.これで、後で問題が発生して、ログを通じて、すぐに問題の所在を見つけることができます.