Sentry(直譯為:哨兵)是一個開源錯誤跟蹤服務,幫助開發人員實時監控和修複崩潰 Sentry本質上是一種幫助您實時監控和修複崩潰的服務 1. 安裝客戶端SDK 這裡我們安裝Java平臺的SDK,而且使用logback的方式集成 https://docs.sentry.io/clients/jav ...
Sentry(直譯為:哨兵)是一個開源錯誤跟蹤服務,幫助開發人員實時監控和修複崩潰
Sentry本質上是一種幫助您實時監控和修複崩潰的服務
1. 安裝客戶端SDK
這裡我們安裝Java平臺的SDK,而且使用logback的方式集成
https://docs.sentry.io/clients/java/
1.1. Logback
https://docs.sentry.io/clients/java/modules/logback/
首先,引入maven依賴
<dependency> <groupId>io.sentry</groupId> <artifactId>sentry-logback</artifactId> <version>1.7.16</version> </dependency>
接著,添加logback.xml文件
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- Configure the Console appender --> <appender name="Console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- Configure the Sentry appender, overriding the logging threshold to the WARN level --> <appender name="Sentry" class="io.sentry.logback.SentryAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> </appender> <root level="INFO"> <appender-ref ref="Console" /> <appender-ref ref="Sentry" /> </root> </configuration>
最後,添加sentry.properties配置
主要是設置DSN(Data Source Name)
設置DSN的方式有多種(比如:sentry.properties,或者環境變數SENTRY_DSN,或者運行時參數)
具體參見 https://docs.sentry.io/clients/java/config/#setting-the-dsn
1.2. Spring
https://docs.sentry.io/clients/java/modules/spring/
用Spring Boot的話這樣寫即可
@Bean public ServletContextInitializer sentryServletContextInitializer() { return new io.sentry.spring.SentryServletContextInitializer(); }
1.3. 示例配置
配置項很多,在此不一一列舉,更多請參見 https://docs.sentry.io/clients/java/config/#setting-the-dsn
有兩個必須配置的選項:dsn 和 stacktrace.app.packages
https://docs.sentry.io/clients/java/config/#in-application-stack-frames
工程結構
pom.xml
logback.xml
sentry.properties
接下來,啟動項目,並訪問,令其報錯,然後通過Web管理後臺查看
同時,也收到了郵件
點進去,查看詳情,可以看到異常信息,還可以看到配置文件中我們帶的參數,還可以對異常進行處理
1.4. 手動捕獲異常
/** * An example method that throws an exception. */ void unsafeMethod() { throw new UnsupportedOperationException("You shouldn't call this!"); } /** * Examples using the (recommended) static API. */ void logWithStaticAPI() { // Note that all fields set on the context are optional. Context data is copied onto // all future events in the current context (until the context is cleared). // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept. Sentry.getContext().recordBreadcrumb( new BreadcrumbBuilder().setMessage("User made an action").build() ); // Set the user in the current context. Sentry.getContext().setUser( new UserBuilder().setEmail("[email protected]").build() ); // Add extra data to future events in this context. Sentry.getContext().addExtra("extra", "thing"); // Add an additional tag to future events in this context. Sentry.getContext().addTag("tagName", "tagValue"); /* This sends a simple event to Sentry using the statically stored instance that was created in the ``main`` method. */ Sentry.capture("This is a test"); try { unsafeMethod(); } catch (Exception e) { // This sends an exception event to Sentry using the statically stored instance // that was created in the ``main`` method. Sentry.capture(e); } } /** * Examples that use the SentryClient instance directly. */ void logWithInstanceAPI() { // Retrieve the current context. Context context = sentry.getContext(); // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept. context.recordBreadcrumb(new BreadcrumbBuilder().setMessage("User made an action").build()); // Set the user in the current context. context.setUser(new UserBuilder().setEmail("[email protected]").build()); // This sends a simple event to Sentry. sentry.sendMessage("This is a test"); try { unsafeMethod(); } catch (Exception e) { // This sends an exception event to Sentry. sentry.sendException(e); } }
1.5. 文檔
Sentry還有很多很多配置,更多請參見 https://docs.sentry.io/
錯誤數據 https://docs.sentry.io/enriching-error-data/context/?platform=electron
集成 https://docs.sentry.io/workflow/releases/?platform=electron
用戶和組 https://docs.sentry.io/accounts/membership/
好,接下來說重點
在剛纔的告警中,僅僅只是使用郵件的方式進行通知,這是不夠的,因為你會發現在平時的工作中很少有人去實時關註郵件,因為實在是太多了(GitLab、Jira、Wiki、還有各種會議郵件抄送,都懶得打開),這還是上班時間,下班以後就更不好說了,因此,更通常的做法是採用釘釘群機器人通知。每當出現異常告警,釘釘群機器人都會@指定的負責人,這樣效率更高,能夠更快速的響應線上問題,其實最主要是一般釘釘都是隨時線上的。
很可惜!Sentry預設的服務中是不支持釘釘的,它並沒有集成釘釘。我也是找到好久才發現的
項目告警裡面的集成也沒有
後來,我看到有一個 WebHooks ,於是我就把釘釘群機器人的回調地址填到這裡,發現不行
後來,我猜測應該是數據格式不對,但又不支持自定義發送的數據格式
沒有辦法,最後我決定不用Sentry的伺服器,自己搭建服務端,自定義的應該能夠支持釘釘
2. 搭建Sentry服務端
https://docs.sentry.io/server/installation/
2.1. 安裝前的準備
PostgreSQL : 需要 postgres:9.5
https://www.postgresql.org/download/
https://www.enterprisedb.com/downloads/postgres-postgresql-downloads
Redis : 需要2.8.9以上的版本
brew install redis
2.2. 採用Python安裝
官方提供兩種安裝方式:Docker 和 Python,這裡我採用Python方式安裝
https://docs.sentry.io/server/installation/python/
2.2.1. 安裝Python 2.7
brew install python2
2.2.2. 設置虛擬環境
pip install -U virtualenv virtualenv /www/sentry/ source /www/sentry/bin/activate
2.2.3. 安裝Sentry
pip install -U sentry
git地址:https://github.com/getsentry/sentry
初始化配置
sentry init /etc/sentry
配置postgressql
sentry.conf.py
配置Redis
配置郵件
創建資料庫
接下來的三條命令在我們剛纔設置的虛擬環境下執行
# If you kept the database ``NAME`` as ``sentry`` $ createdb -E utf-8 sentry $ SENTRY_CONF=/etc/sentry sentry upgrade # create a new user $ SENTRY_CONF=/etc/sentry sentry createuser
2.2.4. 啟動Web服務
SENTRY_CONF=/etc/sentry sentry run web
2.2.5. 啟動後臺Worker進程
SENTRY_CONF=/etc/sentry sentry run worker
2.2.6. 啟動Cron進程
SENTRY_CONF=/etc/sentry sentry run cron
以下是我安裝過程中執行的一些命令
2.2.7. 訪問 http://localhost:9000/
登錄(PS:用戶名和密碼就是我們在安裝Sentry的時候設置的用戶名和密碼,這裡我設置用戶名和密碼分別是:[email protected]/12345678)
設置(Root URL是將來上報事件的伺服器地址,沒有功能變數名稱的話可以就寫localhost:9000)
進入主界面,可以先設置一下語言和時區
新建一個項目
查看客戶端秘鑰
接下來可以查看並修改系統設置
3. 釘釘群機器人
Webhook可以理解為是一種回調機制,一個回調地址
添加一個自定義的機器人
於是我們就可以拿到一個webhook地址,這個地址裡面帶著access_token
按照釘釘的消息格式,我們就可以給這個群發消息
4. Sentry集成釘釘插件
4.1. 安裝sentry_dingding插件
我找到兩個相似的插件
插件一:https://github.com/anshengme/sentry-dingding
這個插件相對新一點兒,最近一次提交是5個月前
安裝方式有兩種,
第一種: pip install sentry-dingding
第二種: pip install git+https://github.com/anshengme/sentry-dingding.git
插件二:https://github.com/evilbs/sentry-dingtalk
安裝方式也有兩種,
第一種: pip install git+https://github.com/evilbs/sentry-dingtalk.git
第二中: 先git clone到本地,然後執行 pip install 本地目錄
最後,無論哪個插件,無論哪種方式,這條命令必須在虛擬路徑下執行
安裝完成後可以通過sentry plugins list命令查看
接下來,安裝完了還不算完,最重要的是檢查一下有沒有錯誤
同樣,在虛擬路徑下執行 sentry upgrade
但是,當你執行以後,你會發現報錯了
redis版本衝突是什麼鬼?意思是,Python2.7需要的redis版本是2.10.5,而redis-py-cluster需要依賴的redis版本最新是2.10.6
怎麼辦呢?重新安裝一下吧
pip uninstall redis pip install redis==2.10.5
再執行 sentry upgrade,還是版本衝突,於是又改redis-py-cluster的版本
pip uninstall redis-py-cluster pip install redis-py-cluster==1.3.5
問題又來了,說Sentry 9.0.0需要的redis-py-cluster版本最小是1.3.4,不能大於或等於1.4.0
幾經折騰,終於找到一個既滿足sentry 9.0.0,又滿足python2.7對redis的版本要求,就是1.3.4版本
再次執行sentry upgrade成功
重啟Web服務
lsof -i tcp:9000 kill -9 sentry run web sentry run worker
刷新頁面,終於看到了
填寫token
發個消息看看效果
此處應有掌聲,啊哈哈哈~~
5. 參考文檔
https://docs.sentry.io/server/
https://docs.sentry.io/server/installation/python/
https://github.com/anshengme/sentry-dingding
https://logback.qos.ch/codes.html#appender_order