国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

日志到底應該怎么打印?

原創
開發 前端
寫代碼的人就沒有不寫日志的,但我們到底該怎么打印日志,打印日志能不能有點章法?

[[385165]]

【51CTO.com原創稿件】前言

寫代碼的人就沒有不寫日志的,但我們到底該怎么打印日志,打印日志能不能有點章法?

針對這個問題,我查閱了《阿里巴巴Java開發手冊》,里面有 8 條日志規約。比如不同作用的日志存放到不同的日志文件里,以 appName_logType_logName.log 方式進行命名。是挺不錯,但屬于是日志分類的問題,依舊解決不了程序員如何有章法的在代碼中書寫日志的問題。

探尋

先來看一個比較常見的日志打印示例:

  1. log.info("開始執行業務邏輯 ----------------->{}",param); 
  2. log.info("業務邏輯執行中 ----------------->{}",param); 
  3. log.info("結束執行業務邏輯 ----------------->{}",param); 
  4. log.error("業務執行異常 ----------------->{}",param, e); 

這種日志打印有什么問題?

第一、沒有綁定事件

在執行什么業務邏輯呢?沒有一個明確的事件,或者說是名字、歸類,我更愿稱之為事件。我們搜索日志時,是要有一個主語的,如果在日志打印中加入事件,我們搜索日志時,只需要輸入關鍵字即可獲取該事件的所有日志。改進后的⽇志打印:

  1. log.info("{}|開始執行業務邏輯 ----------------->{}",EVENT_NAME, param); 
  2. log.info("{}|業務邏輯執行中 ----------------->{}",EVENT_NAME, param); 
  3. log.info("{}|結束執行業務邏輯 ----------------->{}",EVENT_NAME, param); 
  4. log.error("{}|業務執行異常 ----------------->{}",EVENT_NAME, param, e); 

第二、沒有綁定主鍵

一個事件下的日志無時無刻不在產生,而發生問題時,往往只會給你一個 case 進行診斷,所以,我們除了記錄事件,還需要記錄主鍵,通過觀察這個主鍵在執行過程中都產生了哪些日志來定位問題。改進后的日志打印:

  1. log.info("{}|ID={}|開始執行業務邏輯 ----------------->{}",EVENT_NAME, ID, param); 
  2. log.info("{}|ID={}|業務邏輯執行中 ----------------->{}",EVENT_NAME, ID, param); 
  3. log.info("{}|ID={}|結束執行業務邏輯 ----------------->{}",EVENT_NAME, ID, param); 
  4. log.error("{}|ID={}|業務執行異常 ----------------->{}",EVENT_NAME, ID, param, e); 

第三、沒有綁定請求

有了事件,有了主鍵,但是在查詢日志的過程中,發現該主鍵產生了許多重復日志,日志的上下文不連貫,我們想看某一次請求產生的連續日志就非常不方便,這時候就需要考慮并發的情況。改進后的日志打印:

  1. // 可以使用 UUID 生成ReqId 
  2. // final String ReqId = UUID.randomUUID().toString(); 
  3. log.info("{}|ReqId={}|ID={}|開始執行業務邏輯 ----------------->{}",EVENT_NAME, ReqId, ID, param); 
  4. log.info("{}|ReqId={}|ID={}|業務邏輯執行中 ----------------->{}",EVENT_NAME, ReqId, ID, param); 
  5. log.info("{}|ReqId={}|ID={}|結束執行業務邏輯 ----------------->{}",EVENT_NAME, ReqId, ID, param); 
  6. log.error("{}|ReqId={}|ID={}|業務執行異常 ----------------->{}",EVENT_NAME, ReqId, ID, param, e); 

第四、沒有綁定分詞符

不要在日志打印時使用 --- 這種分隔符,沒意義、不標準,非常不好做分詞。一定要將不變的文字說明和變化的參數用分詞符分開打印,因為不變的文字說明也是可以成為關鍵詞進行搜索的。改進后的日志打印:

  1. log.info("{}|ReqId={}|ID={}|開始執行業務邏輯|參數={}",EVENT_NAME, ReqId, ID, param); 
  2. log.info("{}|ReqId={}|ID={}|業務邏輯執行中|參數={}",EVENT_NAME, ReqId, ID, param); 
  3. log.info("{}|ReqId={}|ID={}|結束執行業務邏輯|參數={}",EVENT_NAME, ReqId, ID, param); 
  4. log.error("{}|ReqId={}|ID={}|業務執行異常|參數={}",EVENT_NAME, ReqId, ID, param, e); 

第五、錯誤日志需要輸出異常信息

對于異常日志的打印一定要帶上堆棧信息,異常堆棧不能使用 e.printStackTrace() 輸出到控制臺,這樣異常堆棧是寫入不了日志文件的,需要將異常對象寫進最后的參數里,這點相信大家都懂。

除此之外,還需要將異常信息的 toString() 內容打印進同一行日志里。因為異常堆棧都是另起一行,對于一些單行日志記錄的系統,比如阿里云sls,根本看不到異常信息,還得爬進服務器找日志堆棧。所以,還是很有必要將 e.toString() 寫進參數里的,有些異常只看 e.toString() 的內容就可以定位了。為什么我這里要求使用 e.toString() 而不是 e.getMessage() ?因為如果是NullPointerException異常, e.getMessage() 返回空。改進后的代碼:

  1. log.error("{}|ReqId={}|ID={}|業務執行異常|參數={}|e={}",EVENT_NAME, ReqId, ID, param, e.toString(), e); 

第六、若有循環,需要綁定循環主鍵

將上面例子加個業務上的循環,再來看下代碼:

  1. log.info("{}|ReqId={}|ID={}|開始執行業務邏輯|參數={}",EVENT_NAME, ReqId, ID, param); 
  2. for (Key key : KeyList) { 
  3. log.info("{}|ReqId={}|ID={}|業務邏輯執行中|參數={}",EVENT_NAME, ReqId, ID, param); 
  4. log.info("{}|ReqId={}|ID={}|結束執行業務邏輯|參數={}",EVENT_NAME, ReqId, ID, param); 

這樣產生的日志,非常不方便定位到具體的某次循環。如果循環體內出了異常,也不清楚具體是哪個Key 引發的。所以,遇到業務邏輯位于循環內的代碼,應該打印出每次處理的 Key。改進后的代碼:

  1. log.info("{}|ReqId={}|ID={}|開始執行業務邏輯|參數={}",EVENT_NAME, ReqId, ID, param); 
  2. for (Key key : KeyList) { 
  3. log.info("{}|ReqId={}|ID={}|Key={}|業務邏輯執行中|參數={}",EVENT_NAME, ReqId, ID, key, param); 
  4. log.info("{}|ReqId={}|ID={}|結束執行業務邏輯|參數={}",EVENT_NAME, ReqId, ID, param); 

公式

經過上面的分析之后,我們可以總結出日志打印的公式:

  1. EVENT_NAME={}|ReqId={}|Key={}|childKey={}|doing something|result={} 

如果沒有過程的話,ReqId 是可以省略的,Key 的數量也不一定只是一個,你也可以看情況給日志加一列 [start|end] ,表示業務過程的開始和結束。

JSON日志

之前有段時間寫過 JSON 格式的日志,就是每一個行日志都是一個 JSON 串,上面講到的日志可以稱為單行日志。

舉個例子:

  1. Map<String, Object> logMap = new HashMap<>(); 
  2. try{ 
  3. logMap.put("EVENT_NAME""monitor"); 
  4. // .... 
  5. }finally { 
  6. LogUtil.save(JSON.toJSONString(logMap)); 

輸出日志(為了方便查看,我已格式化):

  1. "EVENT_NAME""monitor"
  2. "ReqId""654321"
  3. "ID""123456"
  4. "success"true
  5. "param": { 
  6. "name""zs"
  7. "age": 14 
  8.  } 

JSON 日志天然綁定了請求過程,它最大的優勢是輸出序列化好的 JSON 串,非常方便離線對其各種操作。但對比于單行日志,代碼嵌入性太高,需要通過 try..finally 代碼塊進行捕捉。

主⻚:https://github.com/onblog

PS:以前我喜歡用 JSON 日志,現在我更喜歡用單行日志

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

責任編輯:華軒 來源: 51CTO
相關推薦

2021-01-15 19:10:32

日志打印原則

2016-06-01 11:27:24

2020-09-15 12:59:48

KotlinFlutter移動

2021-01-21 05:51:52

Chrome FlashWindows

2021-05-10 06:58:41

ChromeFlash版本號

2015-09-08 09:20:49

案例研究混合云云部署

2020-06-23 14:28:24

MySQL商品數據

2020-05-11 23:18:09

內存條CPU插槽

2023-11-24 08:17:38

金額類型存儲

2011-08-29 09:45:09

2014-01-07 13:54:40

Hadoop日志

2022-12-29 07:24:55

打印日志Python

2019-03-18 10:32:33

容災雙活同城

2024-06-27 08:04:39

2015-11-05 09:26:34

Fedora發行版Linux

2023-03-24 12:52:22

2021-08-30 11:43:46

程序員技能開發者

2020-04-30 14:38:51

數據庫連接池線程

2020-06-17 10:35:16

機器學習AI人工智能

2010-01-07 10:09:38

千兆網絡交換機
點贊
收藏

51CTO技術棧公眾號

在线观看日韩羞羞视频| www.99.热| 伊人久久噜噜噜躁狠狠躁| 91精品国产91久久久久久最新毛片| av丝袜天堂网| 国产精品一区二区x88av| 成人性色av| 欧美限制电影| 2019av中文字幕| 99这里只有精品视频| 久久久国产精品x99av| 草草在线视频| 欧美一区二区三区电影| 在线免费av网站| 色综合久久66| 久草网在线视频| 亚洲一区免费在线观看| xxav视频| 一区二区三区欧美视频| 免费看成一片| 亚洲成人动漫av| a视频在线看| 亚洲国产欧美日韩另类综合| 女人裸体免费网站| 亚洲成在人线免费| 粉嫩欧美一区二区三区| 天天做天天摸天天爽国产一区| 黄页网址大全在线观看| 日韩欧美在线视频日韩欧美在线视频 | 欧美综合一区| 国产精品精品视频| 猫咪成人在线观看| 国产成人精品av| 日韩国产欧美| 成人综合电影| 六月丁香婷婷久久| 日本一级黄视频| 国产日韩欧美麻豆| 黄色免费看网站| 日韩欧美亚洲成人| 91精品国产91久久久久久青草| 欧美大胆人体bbbb| gogo亚洲高清大胆美女人体| 久久91亚洲精品中文字幕| 香蕉视频一区| 成人在线免费观看一区| 美女任你摸久久| 日日摸日日碰夜夜爽无码| 国产三级精品视频| 调教视频在线观看| 日韩一级二级三级精品视频| 91麻豆精品国产91久久久更新资源速度超快| 久久久久久91香蕉国产| 亚州av乱码久久精品蜜桃| 婷婷久久青草热一区二区| 激情影院在线观看| 在线观看视频91| 超碰99在线| 98精品国产自产在线观看| 亚洲小说欧美另类社区| 成年人网站国产| 亚洲mv在线观看| 日本三级在线观看网站| 高清欧美一区二区三区| 一本不卡影院| 99视频在线视频| 欧美调教femdomvk| 成人av色网站| 99re在线观看视频| 成人在线综合网站| 五丁香在线视频| 有码中文亚洲精品| 久久影院一区| 99er在线视频| 欧美性xxxxx| 国产一区二区三区免费观看在线| 成人激情视频小说免费下载| 国产一区二区91| 日本视频在线观看一区二区三区| 亚洲欧美综合另类中字| av在线不卡顿| 男女猛烈激情xx00免费视频| 欧美色视频在线观看| 波多野结衣一区二区三区免费视频| 久久久久久久久久码影片| 国产精品狼人久久影院观看方式| 操你啦视频在线| 国产欧美精品一区二区三区-老狼| 国产成都精品91一区二区三| h网站视频在线观看| 欧美亚洲国产日韩2020| 国产酒店精品激情| 成人动漫在线播放| 日韩av片免费在线观看| 成人爱爱电影网址| 欧美午夜大胆人体| 9a蜜桃久久久久久免费| 亚洲人亚洲人成电影网站色| 视频在线日韩| 久久综合中文色婷婷| 亚洲激情自拍视频| 欧美成人免费全部网站| 国产日韩精品一区观看| 亚洲综合久久av| 国产区一区二| 91.com在线| 亚洲国产精品大全| 激情亚洲网站| 亚洲一区二区三区精品中文字幕| 欧美黑人性猛交| 成人国产一区二区三区精品| 精精国产xxxx视频在线中文版| 成人在线一区二区| 亚洲一区二区四区蜜桃| 欧美三级自拍| 成人观看网站a| 欧美激情久久久久久| 成人精品视频网站| 免费福利视频一区二区三区| 无码免费一区二区三区免费播放| 欧美三级视频在线| 欧美精品aa| 青青草超碰在线| 国产精品美女av| 综合婷婷亚洲小说| 国产精品3区| 国模杨依粉嫩蝴蝶150p| 久久精品视频在线播放| 不卡视频在线看| 成人黄色毛片| 日本福利视频一区| 色播久久人人爽人人爽人人片视av| 国产成人综合精品三级| 在线天堂资源www在线污| 亚洲一区不卡在线| 欧美精品一区二区三区高清aⅴ | 成人午夜电影网站| 欧美成人免费电影| 五月天av影院| 国产一区二区动漫| 99视频在线精品| 免费一区二区三区在线视频| 污版视频在线观看| 2019中文字幕全在线观看| 国产精品视频免费看| 日本欧美高清| 91欧洲在线视精品在亚洲| 国产日韩欧美视频在线| 色婷婷一区二区三区四区| 亚洲每日更新| 9765激情中文在线| 成人一区二区免费视频| 久久久噜噜噜久久| 偷拍日韩校园综合在线| 99热免费精品在线观看| 九九色在线视频| 男女午夜激情视频| 国产精品pans私拍| 在线精品观看国产| 久久99精品久久久久久| 亚洲伊人伊成久久人综合网| 先锋影音成人资源| 成人午夜一级二级三级| 在线综合视频播放| 国产91丝袜在线播放九色| 成人性生交大片免费看96| 一区二区电影网| 日韩av一区二区三区在线观看| 中国日韩欧美久久久久久久久| 国产亚洲精品免费| 久久久久久久久国产一区| 青青草视频在线免费直播| 人妻夜夜添夜夜无码av| 欧美一级黄色网| 欧美日韩一区在线观看| 国模无码大尺度一区二区三区| 国产精品色婷婷在线观看| 久草在线中文888| 亚洲v国产v在线观看| 欧美激情视频在线免费观看 欧美视频免费一 | 国产精品美女主播| 欧美视频三区在线播放| 国产精品影视网| 欧美女王vk| heyzo在线欧美播放| 成人观看网站a| 日韩国产高清一区| 18一19gay欧美视频网站| 欧美精品在线观看一区二区| 成人av先锋影音| 欧美福利视频| 成人永久在线| 亚洲妇熟xxxx妇色黄| 免费一区二区三区在线观看| 欧洲一区二区在线观看| 欧洲成人性视频| 亚洲情综合五月天| 在线免费视频一区二区| 日本一区二区三区四区| 日韩电影在线免费|