最近由于工作需要人弓,接觸了兩類監(jiān)控類產(chǎn)品癞季,一類是對于系統(tǒng)資源,系統(tǒng)狀態(tài)阁吝、應(yīng)用狀態(tài)等信息的監(jiān)控砚婆,主要是使用prometheus+grafana
,這個打算以后更熟悉了寫幾篇科普的文章突勇,用起來感覺還是很酷也很實用的装盯;另外一類是error tracking
類的產(chǎn)品,我用的是sentry甲馋,很早以前就聽過它了埂奈,粗略了解之后感覺部署還是不簡單就放棄了,后來突然想到可以使用docker
來進行部署定躏,就仔細(xì)讀了它的部署文檔账磺,使用docker-compose
來部署還是很簡單的,這里我就不說了痊远,網(wǎng)上這類文章也很多垮抗,有問題的讀者可以找一篇比較詳細(xì)的文章進行了解。
由于想對haipproxy再做一些優(yōu)化碧聪,其中一個優(yōu)化點便是如何對其做監(jiān)控冒版。以前面試的時候,面試官問了我一個問題:你日志是通過什么來查看的呢逞姿?我當(dāng)時愣了一下壤玫,說豁护,肉眼看的。確實通過肉眼可以一行一行讀可以大大提升我們trouble shotting
的能力欲间,我也因此受益良多楚里。但是在日志特別大的時候,這種方式就比較低效了猎贴。Sentry將我們從bug trace
中解救了出來班缎,我們可以在項目中將一些重要信息使用Sentry進行上報,它可以通過郵件或者其它方式(如slack
)通知開發(fā)者進行查看她渴,及時發(fā)現(xiàn)問題达址。它的使用也非常簡單,當(dāng)我們在它的頁面通過New Project
建立好項目之后趁耗,它會顯示一個Sentry_DSN
沉唠,比如
http://82c130028fa942f29add1e0aa0ff9cbd:cffa174304d248b9aa2bdb385d3b01b8@127.0.0.1:9000/6
然后我們安裝對應(yīng)語言的客戶端,我用的是Python苛败,則
pip install raven
raven
就是它的客戶端满葛,然后生成一個Client
的實例,用于上報重要信息
client = Client(http://82c130028fa942f29add1e0aa0ff9cbd:cffa174304d248b9aa2bdb385d3b01b8@127.0.0.1:9000/6)
之后罢屈,在需要進行上報信息的地方導(dǎo)入該實例即可嘀韧,比如我在Scrapy
的下載中間件中,使用Sentry的代碼如下
class ErrorTraceMiddleware(object):
def process_response(self, request, response, spider):
if response.status >= 400:
reason = 'error http code {} for {}'.format(response.status, request.url)
self._faillog(request, HttpError, reason, spider)
return response
def process_exception(self, request, exception, spider):
self._faillog(request, DownloadException, exception, spider)
return
def _faillog(self, request, exc, reason, spider):
if USE_SENTRY:
try:
raise exc
except Exception:
message = 'error occurs when downloading {}'.format(request.url)
client.captureException(message=message)
else:
print(reason)
如果同時需要跟蹤頁面解析錯誤的信息缠捌,那么需要實現(xiàn)一個SpiderMiddleware
锄贷,或者通過signals
來做,這里由于篇幅就不介紹了曼月。
下面是在Haipproxy中關(guān)于使用Sentry的一些Bug Trace相關(guān)信息
也有詳細(xì)的錯誤信息
可見還是非常直觀的
如果是非scrapy
的bug trace
谊却,我以前的做法是寫一個裝飾器捕獲可能出現(xiàn)但是自己又沒想到的錯誤,記錄在日志中哑芹,然后通過定期查看日志來完善這部分代碼因惭,有了sentry之后,一切變得更加簡單了绩衷,比如我為爬蟲解析頁面寫的一個捕獲未知錯誤的裝飾器,結(jié)合sentry可以這樣寫
def parse_decorator(return_value):
def page_parse(func):
@wraps(func)
def handle_error(*keys):
try:
return func(*keys)
except Exception as e:
client.captureException()
return return_value
return handle_error
return page_parse
使用sentry激率,我們主要調(diào)用的就是client.captureException()
方法咳燕,它在except
作用域中,用于收集錯誤堆棧乒躺,為了便于復(fù)現(xiàn)或者調(diào)試錯誤招盲,有的時候,我們可能需要附加除了錯誤堆棧之外的一些其它信息嘉冒,這時候可以用message
這個參數(shù)曹货。它可以傳遞一些額外的信息咆繁,這樣更加方便跟蹤錯誤。
還有一個client.captureMessage()
方法顶籽,它的主要作用在于上報一些重要信息而非錯誤堆棧玩般。
目前只是對其的一些簡單使用,后續(xù)還會加深了解礼饱,比如多團隊多用戶協(xié)作坏为,與其它項目管理軟件進行集成(如Gitlab
),如何做高可用等