想像一下,你在跟資料庫打交道,處理一堆 transaction,結果突然出包。用戶抱怨、老闆在吼,但你根本不知道發生什麼事。這時候正確的錯誤記錄就超重要啦。它可以:
- 把錯誤存進資料庫,方便之後分析。
- 很容易還原錯誤細節:發生時間、訊息、還有相關資料。
- 分析 log 之後,針對常見錯誤優化你的 code。
簡單說,log 就像是你資料庫的監視器錄影帶:所有出錯的時刻和原因都能看到。
建立 error_log 資料表
我們就從基礎開始吧。要先建立一個資料表來存錯誤資訊。這個 table 會有以下欄位:
id— 錯誤的唯一識別碼。error_message— 錯誤訊息內容。error_time— 發生錯誤的時間。- (可選)
context— 錯誤的 context,如果你想存更多細節。
CREATE TABLE error_log (
id SERIAL PRIMARY KEY, -- 錯誤的唯一識別碼
error_message TEXT NOT NULL, -- 錯誤訊息內容
error_time TIMESTAMP NOT NULL DEFAULT NOW(), -- 發生錯誤的時間
context JSONB -- 錯誤的額外資料
);
這段 code 在做什麼?
id SERIAL PRIMARY KEY— 這個欄位會自動產生每筆記錄的唯一 id。error_message TEXT NOT NULL— 這裡會存錯誤訊息,必填。error_time TIMESTAMP NOT NULL DEFAULT NOW()— 記錄事件發生的時間。如果沒給值,會自動用DEFAULT NOW()寫入現在時間。context JSONB— 可選欄位,存放像是哪個操作出錯等額外資訊。
執行 CREATE TABLE 後,你的資料庫就有一個專門存 log 的結構啦。
錯誤寫入資料表的範例
table 建好後,來點實作:把錯誤資訊寫進 table。我們來寫個 function,把錯誤訊息和時間存進 error_log。
寫入錯誤的 function 範例
CREATE OR REPLACE FUNCTION log_error(p_error_message TEXT, p_context JSONB DEFAULT NULL)
RETURNS VOID AS $$
BEGIN
INSERT INTO error_log (error_message, context)
VALUES (p_error_message, p_context);
END;
$$ LANGUAGE plpgsql;
p_error_message— 傳入的參數,用來放錯誤訊息。p_context— 可選參數,傳遞額外資料。預設是NULL。INSERT INTO error_log (error_message, context)— 新增一筆錯誤記錄到error_log。DEFAULT NULL— 如果沒給 context,這欄就會是NULL。
現在要寫錯誤訊息時,你可以這樣呼叫 function:
SELECT log_error('執行查詢時發生錯誤', '{"query": "SELECT * FROM data"}');
這樣就會在 error_log table 新增一筆記錄。
自動錯誤記錄
每次都手動 SELECT log_error(...) 很麻煩。我們來用 exception 處理自動化這流程。
這裡有個帶 exception 處理的 function 範例。
CREATE OR REPLACE FUNCTION divide_numbers(a NUMERIC, b NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
result NUMERIC;
BEGIN
-- 嘗試做除法
result := a / b;
-- 回傳結果
RETURN result;
EXCEPTION
WHEN division_by_zero THEN
-- 記錄錯誤並傳遞 context
PERFORM log_error('除以零', jsonb_build_object('a', a, 'b', b));
-- 丟出 exception 給用戶
RAISE EXCEPTION '無法將 % 除以 % — 除數是零', a, b;
END;
$$ LANGUAGE plpgsql;
- 除法檢查:執行
result := a / b。如果b = 0,PostgreSQL 會丟出division_by_zeroexception。 - exception 處理器(
EXCEPTION)會攔截這個錯誤。 - 在 handler 裡我們呼叫
log_error,把錯誤和參數寫進 table。 - 寫完錯誤後,用
RAISE EXCEPTION再丟出一個錯誤訊息,讓用戶也知道。
呼叫範例:
SELECT divide_numbers(10, 0);
結果:
- 用戶會看到錯誤:
無法將 10 除以 0 — 除數是零。 error_logtable 也會多一筆除以零的記錄。
GO TO FULL VERSION