
這章要學會什麼
- 把每個統計指標的定義寫清楚:什麼算「工具真的被執行」、什麼算「授權層級就被擋下」、成功率的分子分母怎麼算,並且能自己用查詢語法驗證儀表板上的每一個數字。
- 用「臺灣日期」處理日期篩選:資料庫存的是世界標準時間,但查詢的邊界要換算成臺灣時間的午夜零點,零筆資料要顯示「無資料」而不是很誤導人的 0%。
- 做出後臺儀表板:現況卡片、每日趨勢圖(附表格版本)、服務排名、錯誤分布。
- 做出呼叫紀錄查詢,能用一組追查代碼找到單筆失敗紀錄並看到中文說明;也做出稽核軌跡查詢。
先備知識
從第 8 章起,每次呼叫都會產生一筆呼叫紀錄;從第 11 章起,授權層級的拒絕也會產生一筆。每個管理動作都會寫進稽核紀錄。要知道基本的分組統計語法概念,跟 JSON 是什麼。
觀念白話講
做儀表板最先要做的事:把定義寫死
儀表板最常見的錯誤不是圖畫錯,而是同一個名詞,每個人算法不一樣:「今天呼叫了幾次」要不要算被額度擋下的?「成功率」的分母要不要包含沒有授權而亂猜的請求?這門課把定義先寫死,全平台照這個標準做:
| 指標 | 定義 | 為什麼 |
|---|---|---|
| 授權拒絕 | 錯誤代碼屬於「使用權相關」或「權限範圍」「會員停權」「額度」這幾類其中之一 | 這些是在真正送進安全閘道之前就被擋下,工具根本沒有被執行 |
| 工具執行 | 其餘所有紀錄(成功、參數錯誤、上游失敗、閘道拒絕) | 代表閘道確實接受了這次呼叫、開始處理 |
| 成功率 | 成功的工具執行 ÷ 工具執行總數 | 授權拒絕是「不該執行」,不是「執行失敗」,混在一起會讓服務看起來很不穩定 |
| 平均/P95 延遲 | 只算工具執行的耗時 | 授權拒絕耗時接近 0,混進來會把平均值拉得不合理地低 |
| 零筆資料 | 顯示「無資料」 | 0 筆的成功率不是 0%,是完全沒有意義的數字 |
P95 延遲指的是「95% 的呼叫都在這個時間內完成」,這門課採用把所有耗時由小到大排序、取排在 95% 位置那一筆的算法——這是常見統計函式裡的其中一種算法,另一種取相鄰兩筆內插的算法會得出稍微不同的數字,所以定義沒寫清楚,兩個人拿同一批資料會報出不同的 P95。
時區:資料存世界標準時間,看的卻是臺灣日期
管理員說「9 月 26 日」,指的是臺灣時間那一整天,不是世界標準時間那一整天——如果直接拿世界標準時間去分組,臺灣早上 8 點以前的呼叫全都會被誤算到「前一天」去。所以查詢邊界的換算跟每一筆資料分到哪一天的換算,都要先轉換成臺灣時區再處理。
儀表板上有什麼
| 區塊 | 內容 | 受日期篩選影響嗎 |
|---|---|---|
| 平台現況 | 有效會員數、已發布版本數、待審上架、待審使用申請 | 否(現在的即時狀態) |
| 區間內的呼叫 | 工具執行、成功率、平均延遲、P95 延遲、授權拒絕次數 | 是 |
| 每日趨勢 | 成功、失敗、授權拒絕的每日堆疊長條圖,附表格 | 是 |
| 服務排名 | 工具執行次數前 5 名與各自成功率 | 是 |
| 錯誤分布 | 每個錯誤代碼的次數與類別,可以點進去查詢對應的呼叫紀錄 | 是 |
追查單筆:一組代碼就能找到完整脈絡
當有人回報「剛剛那次呼叫失敗了」,他手上會有回應裡附的一組追查代碼。管理員把這組代碼貼進「呼叫紀錄」查詢,就能看到:時間、會員、哪個 AI 助理程式、呼叫的服務跟工具、用了哪一筆使用權、結果、狀態碼、耗時、錯誤代碼跟中文說明。平台不會存下請求跟回應的實際內容(第 8 章定下的原則),但光是這些欄位,已經足夠判斷問題出在會員、AI 助理程式、平台設定,還是上游服務本身。
老師示範做了什麼
示範情境:打開儀表板看最近幾天的狀況,用查詢語法逐一驗證每一個數字;做一次成功跟一次失敗的呼叫,看數字怎麼變化;用失敗那次的追查代碼去找到單筆紀錄;最後查一次稽核軌跡。
老師用查詢語法對同一個日期區間重新算一次,數字跟儀表板上顯示的完全一致。接著用測試工具做一次成功呼叫跟一次參數錯誤的呼叫,重新整理儀表板:工具執行數增加了 2、成功率跟平均延遲都跟著微調,授權拒絕數沒有變化——因為這兩次呼叫都是通過授權檢查、進到閘道層級才發生結果的。
老師最後示範反向驗證:把日期切到一段完全沒有任何呼叫的區間,五張跟呼叫有關的統計卡片全部顯示「無資料」而不是誤導人的 0%;如果不小心把起日跟迄日的順序填反,頁面會自動幫忙對調回來,不會直接顯示一段荒謬的區間。
自己動手的步驟
步驟一:指標定義與日期邊界寫成程式
寫兩個小工具:一個負責「世界標準時間換算成臺灣日期」跟「臺灣日期換算回對應的世界標準時間」;另一個把「哪些錯誤代碼算是授權拒絕」集中定義成一份清單(直接引用第 11 章已經定義好的常數,新增授權錯誤代碼時只需要改一個地方,兩邊不會兜不起來)。
步驟二:計算儀表板內容
讀出區間內所有呼叫紀錄,先分成「授權拒絕」跟「工具執行」兩群;工具執行群再算出成功數、平均延遲、P95 延遲;成功率的分母是 0 的時候要回傳「沒有意義」而不是 0,讓畫面顯示「無資料」。每日趨勢要注意:區間內每一天都要產生一筆資料,就算那天完全沒有呼叫也要顯示高度 0 的長條,不然圖表看起來會很奇怪、漏掉沒有資料的日子。
// P95:由小到大排序後,取第 ⌈0.95 × 筆數⌉ 筆
static int Percentile(排序後的耗時清單, 0.95)
步驟三:儀表板頁面與圖表
把算好的每日趨勢資料,用一小段安全的方式直接嵌進頁面裡(伺服器算好的數字直接交給前端的圖表元件畫圖,不必再另外呼叫一次 API、也不必再驗證一次權限)。圖表本身只是輔助呈現——旁邊一定附上可以展開查看的表格版本,確保數字才是真正的依據,圖表沒載入完成也不影響頁面正常使用。
步驟四:呼叫紀錄與稽核軌跡查詢
呼叫紀錄查詢的邏輯是:如果有帶追查代碼,就只依它查詢,忽略其他所有條件(包括日期)——因為使用者可能是隔了好幾天才回報問題,不必先猜對日期範圍。其餘條件(服務、結果、錯誤代碼)都是有給值才加進查詢條件。稽核軌跡查詢類似,額外要注意:篩選用的動作欄位不能取跟框架保留字衝突的名稱,否則會被自動繫結成別的意思,篩選永遠失效。
常見錯誤
| 症狀 | 原因 | 怎麼處理 |
|---|---|---|
| 稽核軌跡選了某個動作類別卻查到「無資料」,下拉選單又跳回「全部」 | 篩選欄位的參數名稱剛好撞到框架保留的路由名稱,被誤繫結成別的值 | 把這個參數改名,避開跟框架保留字衝突 |
| P95 卡片上的數字被擠成兩行 | 好幾張卡片並排時,數字加單位超出卡片寬度 | 把單位移到卡片標題,卡片本身只放純數字 |
| 測試腳本抓到的工具名稱是空白,但呼叫其實有成功 | 擷取工具名稱用的比對規則沒有考慮到名稱裡含有數字 | 放寬比對規則,讓數字也算進合法字元範圍 |
怎麼驗收+反向驗證
- 完成一次呼叫後統計有對應變化:記下呼叫前的工具執行與成功數,用測試工具成功呼叫一次後重新整理,兩個數字應該各自增加 1。
- 成功率跟資料表算出來的一致:用查詢語法對同一個臺灣日期區間重算一次,工具執行、成功數、成功率、平均延遲、P95 都要跟儀表板完全相同。
- 能用追查代碼找到單筆失敗:把失敗回應裡的代碼貼進呼叫紀錄查詢,能看到完整脈絡跟中文錯誤說明。
- 反向驗證:沒有資料的日期要顯示「無資料」而不是 0%;授權拒絕(例如額度用完)只會讓授權拒絕數增加,不會影響成功率的分母。