跳轉到

錯誤追蹤站(Error Tracking Site)

功能群:系統管理|本檔為非頁面 spec(產品內無 route):錯誤追蹤站是隨落地版安裝的第三方站台(Bugsink 2.6.1),掛在前門的 /bugsink/ 子路徑下,不在產品選單裡。本頁記「哪些錯誤會進站、怎麼進、誰看得到、怎麼設定」,13 節中不適用的標 N/A。

事實基準:2026-10-10 從 core/plugins/api_log.py、api/error_tracking/、app/error_tracking/、common/authz/caller.py、core/plugins/_agent_error_tracking.py、infra/support/diag_event_fetcher.py、scripts/installer/bugsink.sh、scripts/installer/guidantai_bugsink.sh、docker/production/docker-compose.yml、FE src/config/errorTracking.js、jedi-log jedi_api_log/error_tracking/ 掃出。

變更紀錄

日期 FR 變更
2026-10-10 FR-133(1.26.0 之後) 首版:落地版內建錯誤追蹤站(三個專案、裝機自動建站)、前端與 Agent 經登入後轉送端點回報、預設全收、遮罩補位置參數、診斷包改撈 Bugsink

1. 功能描述

每套 Guidant AI 落地版自帶一個錯誤追蹤站:系統各元件發生錯誤時,把當下的堆疊、變數、踩到的使用者、請求編號送進這個站台,原廠人員到客戶現場打開站台就能看出錯在哪一行、當時的值是什麼。站台只在客戶自己的機器上,事件不會送到原廠。

站台由安裝程式在首次安裝與每次升級時自動建好(管理員帳號、三個專案、連線字串),裝機人員不必輸入任何東西。

主要使用者:原廠維運與開發人員(到現場或經客戶授權遠端連入)。客戶的一般使用者看不到這個站台,產品選單也沒有入口。

角色速覽

角色 一句話
原廠人員 用站台管理員帳號登入 https://<主機>/bugsink/ 看錯誤
客戶維運人員 用 guidantai 子命令清資料、改管理員密碼、調收件開關
產品使用者 不接觸站台;登入後在瀏覽器踩到的前端錯誤會自動回報

1.1 功能總覽

# 功能 說明 位置 詳述
1 站台入口 https://<主機>/bugsink/,經前門 443 轉進,不另開埠 前門 nginx location /bugsink/ §5、§11
2 管理員登入 帳號固定 admin@guidantai.com;密碼存在資料目錄 bugsink-admin.secret(root、600) Bugsink 登入頁 §3
3 三個專案 guidant-ai/guidant-ai-fe/guidant-agent 分開收 Bugsink 專案列表 §4
4 後端錯誤自動回報 api/socketio/worker 與證據分類沙箱走內網直送 各容器啟動時初始化 §10
5 前端錯誤回報 登入後才啟用,經後端轉送端點 FE src/config/errorTracking.js UC-ETS-02、§6
6 Agent 錯誤回報 Agent 從註冊/心跳回應拿設定,經同一支轉送端點 evidence-agent 1.4.2 起 UC-ETS-03
7 收件開關 4xx 使用者失誤、ERROR log 行是否另成事件,預設全收 guidant.env 兩個變數 §4
8 事件遮罩 憑證欄位、Bearer 值、無名位置參數送出前遮掉 jedi-log、Agent、分類器各一份 §12
9 請求編號對回 log 事件 tag request_id 與 api log 每行的編號相同 事件 tags UC-ETS-04
10 診斷包撈事件 guidantai diag 經讀取 API 撈三個專案的事件 infra/support/diag_event_fetcher.py §11
11 維運子命令 bugsink-vacuum、bugsink-set-password scripts/installer/guidantai_bugsink.sh §13

UC 展開 1、5、6、9 四條核心路徑。

2. Use Case

角色速覽:同 §1。

視覺慣例:本頁 UC 流程以表格逐步列出(無獨立流程圖),例外分支寫在「例外」列。

UC-ETS-01 後端程式錯誤進站

角色 前置條件 產出後置
系統(api/socketio/worker/沙箱) 安裝程式已寫好 SENTRY_DSN guidant-ai 專案出現一筆事件,含堆疊、release、request_id、使用者帳號
  1. 請求或背景工作拋出例外。
  2. 送出前規則(core/plugins/api_log.py::_extra_before_send):收件開關判斷是否丟棄 4xx → 補使用者帳號 → 補 request_id → 每分鐘節流。
  3. 遮罩(jedi-log scrub_event)後經內網 http://guidant-bugsink:8000 送出。

例外:站台拒收(Host 不在允許清單)時送件端不報錯,事件靜默消失;節流丟棄的筆數寫進 api log 一行警告。

UC-ETS-02 前端錯誤進站(登入後)

角色 前置條件 產出後置
已登入使用者的瀏覽器 SENTRY_DSN 與 SENTRY_PUBLIC_DSN 都有值 guidant-ai-fe 專案出現事件,release guidant-ai-fe@<版號>+<commit>、tag request_id 為最近一次 API 回應的編號
  1. 登入後載入能力點成功 → 前端打 GET /api/1.0/error-tracking/config;enabled=false 就不載入 SDK。
  2. 前端錯誤發生 → SDK 把事件 POST 到 /api/1.0/error-tracking/tunnel,帶 Authorization。
  3. 後端檢查身分、大小、目的地專案、次數 → 轉進站台內網位址,回 204。

例外:未登入 401;目的地專案不符 400(ERT_400002);超過 1 MiB 413;超頻 429。前端遇 401 視同 429,停送 60 秒。登出時關閉 SDK。

UC-ETS-03 Agent 錯誤進站

角色 前置條件 產出後置
受檢主機上的檢測 Agent(1.4.1 起) 雲端已升到含轉送端點的版本;SENTRY_AGENT_DSN 有值 guidant-agent 專案出現事件,tag agent_id 分台
  1. Agent 註冊或心跳 → 回應的 data.error_tracking 帶 {enabled, environment, dsn}。
  2. enabled 為真才初始化 SDK;事件經 Agent 自己的轉送 transport,以 Agent 通行證 POST 到雲端轉送端點。
  3. 後端依通行證判定是 Agent,只准送 guidant-agent 專案。

例外:通行證被拒(401/403)時 Agent 記住那顆通行證,換新前不再送;註冊完成前的錯誤收不到。

UC-ETS-04 從事件對回 api log

角色 前置條件 產出後置
原廠人員 事件 tags 有 request_id(形如 req-xxxxxxxx) 找到同一次請求前後的完整 log
  1. 站台事件頁看 tags 的 request_id。
  2. 在主機上 sudo guidantai logs guidant-api 或診斷包內的 log,以該編號搜尋。
  3. 也可 sudo guidantai diag --request-id <編號> 只打包該次請求相關的紀錄與事件。

背景排程沒有請求脈絡,request_id 為 - 或 job-<名稱>-<8 碼>。

3. 權限矩陣

操作 FE 判定 BE 強制 BE 檢查位置
開站台、看事件 N/A(不在產品內) Bugsink 自己的帳號登入;SINGLE_USER=True、不開放註冊 compose guidant-bugsink 環境變數
GET /error-tracking/config 登入後才呼叫 jwt_required;Agent 通行證打它回 401;不掛能力點 api/error_tracking/routes/error_tracking_route.py
POST /error-tracking/tunnel SDK 自帶 token jwt_or_agent_pass_required:使用者 JWT 或 Agent 通行證擇一,兩條路各自驗簽;不掛能力點 common/authz/caller.py
只能送自己那個專案 — 使用者只准 SENTRY_PUBLIC_DSN 的專案、Agent 只准 SENTRY_AGENT_DSN 的專案 app/error_tracking/service/error_tracking_app_service.py
清資料、改管理員密碼 — 主機 root(sudo guidantai ...) scripts/installer/guidantai_bugsink.sh

管理員密碼全客戶同一組,出包時烙進安裝包;升級不改既有密碼,單台可用 bugsink-set-password 改掉。站台只在客戶內網可達是這組共用密碼的前提。

4. 狀態機與前置條件

無狀態機。站台與各專案的存在與收件行為由下列條件決定:

三個專案各收誰

專案 收誰的錯誤 識別
guidant-ai api、socketio、worker、證據分類沙箱 沙箱事件帶 tag app=guidant-classifier
guidant-ai-fe 已登入使用者的瀏覽器 release guidant-ai-fe@...
guidant-agent 所有受檢主機的檢測 Agent tag agent_id

哪些元件的錯誤會進、哪些不會

元件 進站? 路徑
api/socketio/worker 會 內網直送
證據分類沙箱 會 只通站台的專屬內網網段 guidant-sandbox-errors
前端(登入後) 會 經後端轉送端點
檢測 Agent(1.4.1 起) 會 經後端轉送端點
前端(登入前,如登入頁本身的錯誤) 不會 轉送端點要登入
Agent 註冊完成前 不會 設定從註冊/心跳回應拿
guidant-db-init(資料庫初始化與升級遷移) 不會 未接錯誤追蹤,看安裝畫面與 docker logs

收件開關(guidant.env)

變數 預設 意思
ERROR_TRACKING_CAPTURE_CLIENT_ERRORS true 401/403/404 這類使用者失誤也送站台。站台被灌滿時設 false,只收程式錯誤
ERROR_TRACKING_LOG_EVENTS true 每一行 ERROR 等級的 log 各自成事件。設 false 時 log 只當事件的前情紀錄
ERROR_TRACKING_RATE_LIMIT 60 每個後端行程每分鐘送出上限;轉送端點也用它當每人、每台 Agent 每分鐘上限

兩個開關只認 1/true/yes 與 0/false/no,打錯字回預設值。改完要 sudo guidantai start 才生效(restart 不重讀設定檔)。

站台建不起來的三種情形(安裝只警告、不擋):安裝包沒有管理員密碼檔、讀不到站台網址、stack 內沒有 guidant-db(客戶自備資料庫)。此時站台不建、SENTRY_DSN 留空,產品照常運作,只是錯誤不收。

5. UI 設計

N/A(站台介面是 Bugsink 本身,不由本產品設計)。產品前端沒有任何對應畫面;錯誤回報對使用者完全無感。

站台常用的三個畫面:專案列表(三個專案)、某專案的問題列表(同一個錯誤歸成一個 issue,顯示次數與最後發生時間)、單筆事件(堆疊含每一層的變數、tags、使用者、前情紀錄)。

6. API 規格

6.1 總清單

分類 Method + Path 說明
前端設定 GET /api/1.0/error-tracking/config 登入後取前端的連線設定
轉送 POST /api/1.0/error-tracking/tunnel 收前端或 Agent 的 envelope,檢查後轉進站台
Agent 設定(附帶) 既有註冊、心跳回應的 data.error_tracking 主專案在 Agent blueprint 疊 after_request 補欄位

6.2 GET /error-tracking/config 回應 data

欄位 型別 說明
enabled Bool SENTRY_DSN 與 SENTRY_PUBLIC_DSN 都有值才為 true
dsn Str SENTRY_PUBLIC_DSN;enabled=false 時不帶
environment Str ENV

出處:api/error_tracking/routes/error_tracking_route.py、app/error_tracking/service/error_tracking_app_service.py。

6.3 POST /error-tracking/tunnel

請求本體是 Sentry envelope(application/x-sentry-envelope),第一行 JSON 必須含 dsn。

檢查 結果
呼叫者那個專案的對外 DSN 或 SENTRY_DSN 未設 204,不轉
長度大於 1 MiB 413 ERT_413001
第一行解析失敗或沒有 dsn 400 ERT_400001
dsn 的 project id 或 public key 與呼叫者那個專案不同(不比主機) 400 ERT_400002
同一使用者/同一台 Agent 每 60 秒超過上限 429 ERT_429001
通過 轉到「SENTRY_DSN 的主機+呼叫者專案編號」的內網收件位址,回 204;上游失敗只記 log,仍回 204

送往主機永遠取設定值,不採 envelope 裡的位址——否則這支端點就是開放轉發器。節流以 Redis 計數,Redis 掛掉時放行並記警告。錯誤碼定義在 common/code/error_tracking_error_code.py,FE error-code.json 同步。

6.4 Agent 註冊/心跳回應附帶欄位

data.error_tracking = {enabled, environment, dsn},dsn 取 SENTRY_AGENT_DSN,它或 SENTRY_DSN 缺一則 enabled=false。補欄位失敗只記 log,不影響註冊與心跳。出處:core/plugins/_agent_error_tracking.py。

7. 前端檔案地圖

檔案 角色
compliance-manager-fe/src/config/errorTracking.js 登入後初始化、自帶 token 的 fetch、附 request_id、登出關閉
compliance-manager-fe/src/config/api/api.js ERROR_TRACKING_CONFIG、ERROR_TRACKING_TUNNEL 兩個端點常數
compliance-manager-fe/nginx.onprem.conf 前門 location /bugsink/:先 rewrite 剝前綴再轉內網 8000

8. 後端檔案地圖

鏈路 Route App Service 底層
前端設定、轉送 api/error_tracking/routes/error_tracking_route.py app/error_tracking/service/error_tracking_app_service.py infra/error_tracking/envelope_forwarder_client.py
雙身分守門 — — common/authz/caller.py(jwt_or_agent_pass_required、current_agent_uid)
後端初始化與送出前規則 — — core/plugins/api_log.py(init_error_tracking、_extra_before_send、capture_handled_exception)
Agent 回應補欄位 — — core/plugins/_agent_error_tracking.py
診斷包撈事件 — — infra/support/diag_event_fetcher.py
安裝建站 — — scripts/installer/bugsink.sh
維運子命令 — — scripts/installer/guidantai_bugsink.sh

9. DB

本產品資料庫 guidant_ai 不新增任何表。站台資料放在同一台 guidant-db 的獨立資料庫 bugsink,帳號 bugsink 只擁有這個庫,對 guidant_ai 無任何權限;表結構由 Bugsink 自己的遷移管理,產品程式碼不讀寫。

10. 頁面邏輯與資料對應

連線字串由安裝程式寫入

變數 檔案 值 誰讀
SENTRY_DSN guidant.env guidant-ai 專案、內網形狀 http://<key>@guidant-bugsink:8000/<id> 後端三容器;轉送端點取它的主機
SENTRY_PUBLIC_DSN guidant.env guidant-ai-fe 專案、對外形狀 https://<key>@<主機>/bugsink/<id> 前端設定端點、轉送端點比對
SENTRY_AGENT_DSN guidant.env guidant-agent 專案、對外形狀 Agent 回應、轉送端點比對
BUGSINK_API_TOKEN guidant.env 跨三專案唯讀權杖 診斷包
GUIDANT_SENTRY_DSN .env 同 SENTRY_DSN compose 帶給證據分類沙箱(沙箱不讀 guidant.env,那份檔含資料庫與登入金鑰)
GUIDANT_BUGSINK_SECRET_KEY、GUIDANT_BUGSINK_DB_PASSWORD .env 隨機產生,缺了才補 compose
GUIDANT_BUGSINK_BASE_URL、GUIDANT_BUGSINK_ALLOWED_HOSTS .env 每次安裝與升級依 SYSTEM_URL 重算;允許主機名會保留既有清單多出的主機名 compose

SENTRY_DSN 預先填了外部站台時,安裝程式保留不動並警告,GUIDANT_SENTRY_DSN 留空。

事件內容:堆疊(每一層的區域變數)、例外訊息、release(guidant-ai@<版號>+<commit>)、environment、tag request_id、tag app、使用者登入帳號(不含 user_id)、前情紀錄(同一請求先前的 log)。不含:HTTP 回應內容、cookie、Authorization 等四個憑證標頭(整支拿掉)、SDK 自動附的個資(send_default_pii=False)。

11. 背景行為與外部依賴

類型 內容
第三方元件 bugsink/bugsink:2.6.1(PolyForm Shield 授權),出貨包內含 image tar,digest 釘死
容器 guidant-bugsink:不對外開埠,內網 8000;mem_limit 1g、cap_drop ALL
網路 default 網段(DB、前門)+ guidant-sandbox-errors(internal: true,成員只有沙箱與站台)
保留 每個專案最多 1 萬筆事件,超過由 Bugsink 收件時依重要性淘汰;不設天數上限
不送原廠 站台只在客戶主機;沒有任何對外回傳(PHONEHOME=false)
告警 無(不寄信、不打 webhook)
診斷包 guidantai diag 用 BUGSINK_API_TOKEN 打 /api/canonical/0/issues/,三個專案編號取三支 DSN 的聯集;寫成 events/bugsink-events.json。讀取 API 不能依 tag 篩,帶 --request-id 時逐筆比對,請求總數上限 80。取不到時 manifest 寫明原因,不讓整包失敗
jedi-* jedi-log 1.3.6(init_error_tracking、capture_exception、scrub_event);jedi-evidence-classification 1.6.5(沙箱自帶的初始化與遮罩)
socket 無

12. 邊界情況與已知坑

  1. 站台拒收時送件端不報錯:Host 不在 ALLOWED_HOSTS、或站台網址換了沒重跑升級,事件靜默消失。驗收一律以「站台上看到事件」為準,不看後端 log 的「已啟用」。
  2. 改了站台網址要重跑升級:改 guidant.env 的 SYSTEM_URL 後跑 sudo ./install.sh --upgrade,站台網址、允許主機名、兩支對外 DSN 會一起重寫。只改不跑,前端與 Agent 的事件送不進去。
  3. 用 IP 裝、外面再掛網域:網域不在允許清單時,用網域開站台回 400(錯誤收集本身不受影響,因為後端、前端、Agent 都走內網)。在 .env 的 GUIDANT_BUGSINK_ALLOWED_HOSTS 補上網域後 sudo guidantai start;之後升級會保留這個網域。站台內的連結仍指向 SYSTEM_URL 的主機。
  4. 改設定要用 start:restart 只重啟現有容器、不重讀設定檔。
  5. 遮罩規則有三份複製品:jedi-log(後端)、evidence-agent core/error_tracking/masking.py、jedi-evidence-classification docker/error_tracking.py。三份都遮憑證欄位名、Bearer 值,以及堆疊裡的 args/kwargs 與含字串的無名清單(後者是為了包裝層以位置參數轉手的密碼)。代價是除錯時看不到 args 內容。改一份要同步另外兩份。
  6. 全收模式下登入失敗會進站:預設全收,打錯密碼也會產生 401 事件;密碼由位置參數遮罩擋下,前提是 jedi-log 1.3.6 以上。
  7. 容器重啟會丟掉還沒處理的事件:Bugsink 的收件佇列在容器內暫存,升級或重啟那幾秒進來的事件可能遺失。
  8. bugsink-vacuum 不刪舊事件:站台沒設事件天數上限,vacuum 只清孤兒檔案與已刪問題的殘留;事件量由每專案 1 萬筆上限封頂。
  9. 管理員密碼共用一組:任何一台安裝目錄外洩,所有客戶站台都能用這組登入;緩解是站台只在內網可達、單台可用 bugsink-set-password 改掉。
  10. 升級順序先雲端、後 Agent:Agent 從雲端回應拿設定,雲端沒升時 Agent 只是不啟用,不會壞。
  11. 弱點白名單到期日:bugsink 2.6.1 image 有三條 Critical 上游未修,登記在 scripts/build/vuln-allowlist.txt,到期 2026-12-31;到期前沒換版,出包會被弱點關卡擋下。

13. 開發與驗證

  • DEV:本機 .env 沒設 SENTRY_DSN 時錯誤追蹤整支不啟用,api log 留一行「錯誤追蹤未啟用」。要測就在本機另起 Bugsink 容器、把 DSN 指過去(步驟見 FR-133 b0-findings.md)。
  • 落地版站台:https://<主機>/bugsink/,帳號 admin@guidantai.com,密碼見主機 <資料目錄>/bugsink-admin.secret(需 root)。
  • 維運子命令:sudo guidantai bugsink-vacuum(印清理前後事件筆數)、sudo guidantai bugsink-set-password(互動輸入兩次、密碼不上命令列,成功後同步覆寫密碼檔)。
  • 快速驗收:登入後在瀏覽器 console 故意 throw → guidant-ai-fe 專案收到;打一支故意 500 的端點 → guidant-ai 專案一分鐘內收到;未登入 curl -X POST https://<主機>/api/1.0/error-tracking/tunnel → 401。
  • 守衛測試:test/security/code/test_route_guard_inventory.py(兩支端點登記在豁免清單)、test/security/code/test_security_shape_external_calls.py(轉送的對外呼叫登記在白名單)、test/test_api_log_client_error_filter.py(收件開關與預設值)。
  • 相關文件:錯誤追蹤接入規範(開發者,BE repo docs/claude/error-tracking-integration.md)、落地版手冊 四、日常維運、FR-133 設計文件(BE repo docs/features/FR-133-2610-bugsink-bundled-error-tracking/design.md)、前作 FR-071(錯誤追蹤接線與診斷包)。