錯誤日誌監控也可稱爲業務邏輯監控, 旨在對業務系統運行過程當中產生的錯誤日誌進行收集概括和監控告警。彷佛有那麼點曾相識?沒錯... 就是提到的「APM應用性能監控」。但它又與APM不一樣,APM系統主要注重應用層的行爲分析,收集的更可能是運營方向的數據。而sentry所作的是收集應用底層代碼的崩潰信息,便於碼儂們排查代碼異常。簡單來講它就是一個面向技術碼儂的排障工具。前端
1. 場景描述java
隨着運維自動化流程的推動, 各種運維工具和系統也像雨後春筍般涌現. 目前咱們自主開發的運維繫統的數量已經接近兩位數. 這些系統部署在多臺機器上, 一般還配套一批後臺運行的腳本. web端若是出現異常, 開發人員能夠及時獲得反饋進行修復. 而腳本由於沒有交互, 可能會出現發生重大故障時才定位到問題的狀況.python
2. 既有方案react
後端和腳本用python內置的日誌模塊記錄程序中間狀態, 同時也將二者的輸出重定向到指定文件, 以獲取未捕獲的異常信息.webpack
同臺服務器上多個系統的日誌集中存放到同個目錄web
使用rsync定時從多臺服務器中拉取日誌文件數據庫
對日誌文件進行關鍵字匹配, 並將過濾結果經過郵件發送給運維開發人員npm
最終整合的通知郵件如圖後端
3. 存在的問題瀏覽器
上面的操做部分解決了腳本運行狀態監控盲區的問題, 但還存在以下問題
沒法第一時間感知錯誤
腳本日誌的拉取不是實時的, web端用戶的反饋也每每存在滯後. 出現問題到解決問題的週期太長, 容易致使工做陷入被動.
錯誤信息的獲取相對低效
用戶反饋和郵件告警包含的錯誤信息很是有限, 最終都不得不在大量的日誌中上下翻看關聯的信息. 可能還須要在測試環境下給代碼埋點多獲取一些中間變量數據, 給定位問題帶來不少麻煩.
日誌的處理方式不夠靈活
一般來講, 除了程序運行出錯, 咱們還關心其餘異常狀況, 好比數據污染, 非法請求, 第三方API調用異常等. 若是將此類等同錯誤記錄下來, 很容易形成告警濫發, 而若是不處理此類異常, 長此以往可能致使嚴重的問題. 咱們但願一樣的日誌內容能夠根據場景不一樣靈活處理
監控覆蓋面有限
完整的監控應該涵蓋腳本, 後端以及前端三個部分. 特別是咱們新的運維繫統實現了先後端分離以後, 不少前端的問題沒法被統一記錄下來.
鑑於此, 咱們瞭解了一些日誌收集和監控方案, 選擇了sentry.
4. sentry初探
4.1 概覽
sentry是一個現代化的錯誤日誌記錄和聚合平臺。支持幾乎全部主流開發語言和平臺, 並提供了現代化UI, 如圖
與ELK, splunk不一樣, sentry專一於應用程序產生的錯誤日誌的聚合和監控. 官方提供了多個語言的SDK.
多達30種集成方式
讓開發者第一時間獲悉錯誤信息, 並方便的整合進本身和團隊的工做流中.
4.2 使用先後對比
爲了直觀的展現sentry的強大, 這裏模擬一個常見的場景, 若有雷同, 純屬巧合.
4.2.1 場景一
接入sentry前
用戶A: 發佈功能用不了
開發者A: 哪一個頁面? 截個圖
用戶A: (發截圖)
開發者A發現bug能夠重現, 登陸服務器查看錯誤日誌, 確認程序邏輯無問題, 查看數據庫數據, 發現有髒數據. 聯繫開發者B檢查負責更新數據的python腳本C.py.
開發者B登陸服務器查看錯誤日誌, 發現一個邏輯錯誤致使腳本罷工, 已持續了一個小時. 影響了數千條數據
接入後
開發者A,B同時收到郵件告警, 一分鐘前腳本C.py異常退出.
開發者B進入sentry後臺查看錯誤信息, 定位問題並將其修復, 再清理受影響的數十條數據.
在此過程當中沒有用戶受到影響, 無需開發者A介入
4.2.2 場景二
接入sentry前
用戶: 提交按鈕點了沒反應
開發者: 哪一個頁面? 截個圖
用戶: (發截圖)
開發者: 我這邊沒這個問題, 你打開開發者工具, 切到console面板, 截個圖我看下
用戶: 怎麼弄??
….省略100字
開發者拿到相關數據, 肯定是代碼問題. 可是js文件通過了壓縮, 沒法定位到有問題的代碼. 只能打開本地開發服務器調試.
接入後
開發者收到郵件告警, 顯示前端有錯誤日誌
開發者進入sentry後臺查看錯誤信息, 好比用戶瀏覽器版本, 產生錯誤的頁面url, 代碼調用過程和最終引起錯誤的代碼, 確認問題所在.
開發者: 兩分鐘前你提交的工單備註字段的校驗有點問題, 你先把那一欄留空再提交, 稍後我會更新一個hotfix版本, 到時跟你說下.
用戶: 好的, 剛想問.
5. sentry的配置
sentry官方提供了詳細的部署文檔, 網上也能夠搜索到中文的安裝教程, 安裝過程不贅述. 想要嚐鮮的小夥伴也能夠直接使用sentry官方提供的saas, 免費版支持天天5000個event. 地址是 https://sentry.io
5.1 概念
使用sentry, 須要弄清楚幾個概念:
event
直譯是"事件", 是可操做數據的基本單位. 每一第二天志輸出就產生一個event. event並不必定就是錯誤, 若是日誌記錄級別設置很低, 那麼後臺會產生不少的event, 因此正確的設置日誌級別很重要
issue
直譯是"工單"或者"問題", 是同一類event的聚合. 某一個錯誤可能由於重複執行而被記錄多出, 在sentry會自動聚合到一塊兒, 方便處理. 一般咱們操做的對象就是issue
DSN
DSN即客戶端密鑰, 用來進行客戶端和服務器的通訊. DSN是一個url, 包含一個公鑰一個私鑰, 項目標記和服務器地址, 好比https://1703147af2094458bevb1bfadcfa1c2:7e00a1d4cbd745c0b780451c3586d7f4@sentry.io/1545. 這類DSN是私密的, 還有一類是非私密的, 在sentry後臺中顯示爲DSN(public), 給前端項目使用.
Raven
整個錯誤日誌監控系統包括客戶端和服務端, Sentry是服務端的名稱, 客戶端名稱是Raver, 須要二者配合才能工做.
5.2 配置
sentry服務端的配置主要是名稱, 告警規則等, 至於被監控項目是前端仍是後端區別不大.
5.2.1 建立項目
進入sentry系統後臺, 點擊右上角新建項目
命名爲[項目名][前|後端], 好比"藍海前端".
在配置應用框架頁面, 點擊能夠查看各個語言或框架的接入文檔(能夠忽略這一步)
點擊左上角項目名稱, 進入項目首頁, 能夠看到頁面顯示"Waiting for events…"
5.2.2 獲取和測試DSN
在"項目設置"頁, 在左側列表中點擊"客戶端密鑰", 進入頁面
拷貝DSN, 後端的是DSN, 前端是DSN(public)
以python爲例, 執行pip install raven安裝客戶端後, 執行raven test DSN, 若是一切順利, 能夠在sentry後臺項目首頁看到新增了一條測試消息
5.2.3 配置警報
在"項目設置"頁面, 在左側列表中點擊"警報", 進入警報配置頁
點擊規則標籤頁, 能夠看到已有一個規則, 當事件首次發生時告警
根據須要修改規則
告警規則的配置至關靈活, 且能夠對多個條件進行與或判斷
5.2.4 集成告警
在"項目設置"頁面, 在左側列表中點擊"全部集成"
勾選須要接入的類型,好比Mail
郵件服務器的配置請參考官方文檔, 本身搭建的sentry服務器若是發現集成類型不多, 能夠安裝官方或第三方插件進行擴展
在服務端配置結束後, 能夠開始配置客戶端.
6. 後端的接入
由於咱們的系統主要用python開發, 在此以python爲例.
python接入sentry十分簡單. 官方提供了十幾種python環境(框架)下使用sentry的例子, 好比在celery中
from raven import Clientfrom raven.contrib.celery import register_signal, register_logger_signalclient = Client(DSN)# register a custom filter to filter out duplicate logsregister_logger_signal(client)# The register_logger_signal function can also take an optional argument# `loglevel` which is the level used for the handler created.# Defaults to `logging.ERROR`register_logger_signal(client, loglevel=logging.INFO)# hook into the Celery error handlerregister_signal(client)# The register_signal function can also take an optional argument# `ignore_expected` which causes exception classes specified in Task.throws# to be ignoredregister_signal(client, ignore_expected=True)
我的推薦借鑑logging使用的例子, 緣由是一般開發者會根據logging模塊定製本身的日誌配置, 不直接使用框架內的日誌模塊. 若是你在應用程序中只用了logging模塊, 那麼接入sentry對已存在的代碼來講是透明的, 無需多加修改.
用logging模塊接入sentry只需兩步:
6.1 安裝客戶端
pip install raven
6.2 初始化配置
在應用程序的入口文件(tornado中的app.py等)中, 或者自定義的日誌模塊中, 插入以下代碼
from raven.handlers.logging import SentryHandlerfrom raven.conf import setup_logginghandler = SentryHandler(DSN)handler.setLevel(logging.ERROR)setup_logging(handler)
完成了這兩步操做以後, 就能夠像以前那樣使用logging模塊
import logginglogger = logging.getLogger(__name__)logger.info('This is a test message')
當上面的代碼被執行時, 除了原有的打log操做以外, raven還會向sentry服務器發送日誌內容, 並向標準輸出添加
Sending message of length xxx to https://xxxx
若是但願向sentry發送更多上下文信息, 能夠帶上extra參數
logger.error('This is a test message', extra={'stack': True})
最終顯示在後臺的日誌信息如圖
包含了日誌級別, python環境信息, SDK信息, 棧調用, 先後n第二天志輸出, 相關的其餘事件等等, 若是是未捕獲的異常或帶上extra參數, 還會顯示中間變量的值, 很方便的定位到出錯的位置和數據, 無需再去代碼埋點.
7. 前端的接入
前端的接入相對來講複雜一些
第一, 須要對sentry服務器的域名進行解析. 內部的系統, 後端監控能夠給線上機器添加hosts指定sentry服務器的IP. 而前端, 由於錯誤日誌是從用戶瀏覽器發出的, 須要用戶能自動解析sentry服務器的域名
第二, 若是前端項目用到了打包工具, 而一般打包工具會對代碼進行壓縮甚至混淆, 就會出現sentry收集到的日誌沒法準肯定位問題代碼的狀況 所幸, sentry支持導入sourcemap自動解析和還原代碼, 讓開發者在後臺能看到development環境同樣詳細的棧調用. (固然若是沒有用打包工具能夠忽略這一步)
前端的接入這裏以reactjs爲例
7.1 安裝依賴
npm i raven-js --save
7.2嵌入raven
在index.js文件(入口文件)中,
import Raven from 'raven-js';# 在適當的地方加入, 儘量讓它早執行Raven.config(DSN(public)).install();
其餘前端框架的接入請參考官方文檔 https://docs.sentry.io/clients/java
7.3導入sourcemap
提早生成好sourcemap文件, 實測source-map級別能夠完美工做, cheap-source-map能定位到, 但顯示不友好. 固然, 最推薦的是cheap-module-source-map
# 安裝npm i -g sentry-cli-binary# 登陸sentrysentry-cli --url SENTRY_URL login# SENTRY_URL指自建服務或官方saas地址, 執行命令後會訪問API TOKEN建立頁面, 生成一個TOKEN, 拷貝進來, 成功後TOKEN會被保留到系統用戶某個配置目錄下, 後續的請求都會重複使用這個TOKEN# 建立一個releasesentry-cli releases -o sentry -p 7d04f2c51f32 new test01 --finalize# 這裏的sentry 和7d04f2c51f32 是指 組織名稱和項目名稱, 均指*簡稱*, 與sentry頁面上默認顯示的不一樣, 須要到配置頁面查看# 上傳dist目錄下的文件sentry-cli releases -o sentry -p 7d04f2c51f32 files test01 upload-sourcemaps dist# 刪除舊的release下的全部文件sentry-cli releases -o sentry -p 7d04f2c51f32 files test01 delete --all# 固然這個命令是不想要release上的文件的時候執行的
注意, 生成的map文件與上傳的相對路徑須要一致. 好比, dist目錄是打包後的文件存放目錄, map文件爲sourcemap/[file].map, 則sentry-cli上傳目錄應該是dist, 這樣map文件纔會顯示在sentry後臺的~/sourcemap/目錄下.
這樣的webpack配置
devtool = 'source-map';output.path: 'dist';output.sourceMapFilename = 'sourcemap/[file].map';
則對應這樣的命令
sentry-cli releases -o sentry -p 7d04f2c51f32 files test02 upload-sourcemaps dist
另外, sentry-cli提供了一個參數--url-prefix, 能夠爲上傳的map文件添加前綴, 默認是~/, 有興趣的同窗能夠試試看
再補充一點, sentry須要根據js文件的sourceMappingURL來解析map文件路徑, 因此sourcemap級別不能用hide-source-map或者相似的.
代碼上傳完畢後, 在版本->工件頁面能夠看到該release上的文件, 如圖
最終錯誤日誌效果如圖
8. sentry管理後臺的使用
篇幅所限, sentry後臺的使用簡要講幾點
第一,自定義過濾
sentry提供了豐富的過濾選項, 默認過濾條件是"Unresolved Issues", 用戶也能夠本身組合過濾條件, 並保存成我的或團隊的默認選項
第二,頁面實時更新
上圖中間的按鈕能夠開啓或關閉issues頁面的實時刷新,
第三,統計和概覽
上圖是系統管理員頁面, 能夠看到系統調用, 等待中的任務隊列等的狀況, 在我的賬號首頁也能看到項目的統計信息.
9. 須要注意的點
用sentry作錯誤日誌監控不能取代原有的日誌存儲方案, 只是在日誌收集和監控方面作了擴展. 使用sentry應着重利用其實時性和快捷性, 作到快速響應. sentry會清除較舊的日誌內容, 這與ELK之類的日誌處理系統也有差異.
sentry可否用得好還取決於打log的開發者的功力. 若是原始日誌記錄缺乏關鍵信息或無效信息過多, 再強大的日誌分析系統也無能爲力. 所以在引入sentry作日誌監控的同時, 也要同步增強開發團隊打log的意識, 規範日誌級別, 格式和內容