MySQL DB LogWriter / TraceStore 實作前確認
1. 文件目的
本文件承接 MySQL DB LogWriter / TraceStore 邊界設計,整理 MySqlLogWriter、task_log_traces 與 TaskTraceStore 第一版 PoC 的實作前確認項目。
本文件只做實作前確認,不新增 table、不執行 DDL、不連真實 DB、不修改 ILogWriter public method 簽章、不修改 TaskExecutionRecord / TaskNodeExecutionRecord public model,也不修改 ConsoleHost 或專案啟動方式。
2. 目前程式狀態
| 項目 | 狀態 | 判斷 |
|---|---|---|
ILogWriter |
已存在 | Write(LogEntry entry) 可作為 DB log 寫入入口,第一版不需修改介面。 |
LogEntry |
已存在 | 已包含 TaskId、NodeId、NodeName、DeviceId、CommandName、Status、RetryCount、TimeTakenMs、AdapterTimeTakenMs、DataSummary、RawRequestSummary、RawResponseSummary、MetadataSummary、ErrorCode、Message。 |
ConsoleLogWriter / FileLogWriter / MemoryLogWriter |
已存在 | DB writer 應作為可選 writer,不可取代既有 writer。 |
MySqlTaskStore |
已存在 | 已保存 task_executions 與 node_executions,不應再承擔詳細 trace sink。 |
| MySQL schema attribute | 已存在 | 可用 C# schema class 維護欄位、索引、描述與 SQL preview。 |
| 真實 DB manual-only 驗證 | 已存在 | 目前僅用於已確認的 TaskStore / node_executions 驗證,不可自動擴大到 trace table。 |
3. 本批建議目標
第一版目標是讓 DB trace 能用既有 LogEntry 寫入 MySQL,但不影響 Workflow 成功 / 失敗判斷。
建議範圍:
- 新增
task_log_tracesschema class,僅產生 SQL preview,不自動 apply。 - 新增
MySqlLogWriter第一版,承接ILogWriter.Write(LogEntry entry)。 - 新增
LogEntryto trace row mapper。 - 新增 payload sanitizer,遮蔽敏感資訊並控制欄位長度。
- 新增 fake gateway 測試,驗證 SQL 與參數,不連真實 DB。
- 新增 writer failure 測試,確認 DB log 寫入失敗不會改變 Workflow result。
TaskTraceStore第一版先做設計或 internal query helper;若要新增 public 查詢介面,需再次確認。
4. 建議資料表:task_log_traces
task_log_traces 定位為診斷 trace table,用於查詢任務、節點、設備命令與錯誤摘要,不取代 task_executions 或 node_executions。
4.1 欄位草案
| 欄位 | 型別 | 必填 | 來源 | 說明 |
|---|---|---|---|---|
trace_id |
varchar(64) |
是 | writer 產生 | Trace 主鍵。 |
task_id |
varchar(64) |
否 | LogEntry.TaskId |
任務識別碼。 |
node_id |
varchar(64) |
否 | LogEntry.NodeId |
節點識別碼。 |
node_name |
varchar(128) |
否 | LogEntry.NodeName |
節點名稱。 |
device_id |
varchar(64) |
否 | LogEntry.DeviceId |
設備識別碼。 |
command_name |
varchar(128) |
否 | LogEntry.CommandName |
命令名稱。 |
level |
varchar(32) |
是 | LogEntry.Level |
Log 等級。 |
status |
varchar(32) |
否 | LogEntry.Status |
節點或事件狀態。 |
retry_count |
int |
是 | LogEntry.RetryCount |
重試次數。 |
time_taken_ms |
int |
是 | LogEntry.TimeTakenMs |
節點或事件耗時。 |
adapter_time_taken_ms |
int |
是 | LogEntry.AdapterTimeTakenMs |
Adapter 命令耗時。 |
error_code |
varchar(64) |
否 | LogEntry.ErrorCode |
錯誤代碼。 |
message |
varchar(255) |
否 | LogEntry.Message |
訊息摘要。 |
data_summary |
text |
否 | LogEntry.DataSummary |
Adapter Data 摘要。 |
raw_request_summary |
text |
否 | LogEntry.RawRequestSummary |
已遮蔽 request 摘要。 |
raw_response_summary |
text |
否 | LogEntry.RawResponseSummary |
已遮蔽 response 摘要。 |
metadata_summary |
text |
否 | LogEntry.MetadataSummary |
Metadata 摘要。 |
created_at |
datetime |
是 | LogEntry.Timestamp |
Trace 建立時間。 |
4.2 索引草案
| Index | Columns | 用途 |
|---|---|---|
idx_task_log_traces_task_id |
task_id |
查詢指定任務完整 trace。 |
idx_task_log_traces_node_id |
node_id |
查詢指定節點 trace。 |
idx_task_log_traces_device |
device_id |
查詢設備 trace。 |
idx_task_log_traces_command |
command_name |
查詢命令 trace。 |
idx_task_log_traces_level |
level |
查詢錯誤或警告等級。 |
idx_task_log_traces_error_code |
error_code |
查詢特定錯誤代碼。 |
idx_task_log_traces_created_at |
created_at |
依時間排序、稽核與後續清理。 |
5. MySqlLogWriter 實作邊界
| 項目 | 第一版建議 | 原因 |
|---|---|---|
| 寫入入口 | 實作既有 ILogWriter |
不修改 Core log contract。 |
| 寫入方式 | 單筆 insert | 避免導入背景服務、queue 或批次 flush。 |
| 失敗處理 | 捕捉 DB 寫入例外並交給 fallback writer | DB log 失敗不應改變 Workflow result。 |
| fallback writer | 可選 ILogWriter,但需避免遞迴呼叫自己 |
保留可觀察性,避免無限遞迴。 |
| schema apply | 不自動執行 | DDL 需使用者確認。 |
| 真實 DB | 不自動連線 | 只能透過 manual-only gate 驗證。 |
| ConsoleHost | 不自動接入 | 啟動方式變更需另行確認。 |
6. Payload Sanitizer 規則
DB trace 不得保存未遮蔽的敏感資訊。
第一版 sanitizer 建議規則:
| 規則 | 說明 |
|---|---|
| 敏感字遮蔽 | key 或內容包含 password、pwd、token、secret、authorization、connectionstring 時需遮蔽。 |
| 長度限制 | message、data_summary、raw_request_summary、raw_response_summary、metadata_summary 需固定最大長度。 |
| Null 安全 | null 保持 null,不硬轉成空字串。 |
| 二進位摘要 | 若後續遇到 byte array,只保存長度與摘要,不保存完整大 payload。 |
| 可讀性 | 遮蔽後仍需保留 TaskId、NodeId、DeviceId、CommandName、ErrorCode 等判斷線索。 |
7. TaskTraceStore 第一版邊界
TaskTraceStore 建議不要併入 ITaskStore。
若第一版只做 writer,可先不新增 public 查詢介面;若要提供查詢,建議另行確認以下 public contract:
| 查詢能力 | 用途 | 是否本批自動實作 |
|---|---|---|
FindByTaskId(taskId) |
查詢單一任務 trace | 否,需確認 public contract。 |
FindByNodeId(taskId, nodeId) |
查詢單一任務節點 trace | 否,需確認 public contract。 |
FindByDeviceId(deviceId, from, to) |
查詢設備時間區間 trace | 否,需確認 public contract。 |
ListRecentErrors(limit) |
查詢最近錯誤 trace | 否,需確認 public contract。 |
本批建議先完成 writer 與 schema preview,再討論查詢介面。
8. 測試策略
| 測試 | 類型 | 目的 |
|---|---|---|
MySqlTaskLogTraceSchemaTests |
自動測試 | 確認欄位、索引與描述可產生 MySQL 5.6.2 SQL preview。 |
LogEntryTraceRowMapperTests |
自動測試 | 確認 LogEntry 欄位正確映射到 trace row。 |
PayloadSanitizerTests |
自動測試 | 確認敏感資訊遮蔽與長度截斷。 |
MySqlLogWriterTests |
fake gateway 測試 | 確認 insert SQL 與參數正確,不連真實 DB。 |
MySqlLogWriterFailureTests |
fake gateway 測試 | 確認 DB 寫入失敗不會丟出影響 Workflow 的例外。 |
9. 真實 DB manual-only 驗證條件
完成第一版程式後,真實 DB 驗證仍需使用者明確確認,且需符合:
- 測試 DB 已建立
task_log_traces。 - 使用者確認允許本次 INSERT / SELECT / cleanup。
- manual-only gate 已開啟。
- 測試資料需使用固定前綴,cleanup 僅刪除本次測試資料。
- 驗證欄位、索引、comment 與敏感資訊遮蔽結果。
10. 必須停下確認的項目
以下項目不得自動執行:
- 修改
ILogWriter、ITaskStore或新增TaskTraceStorepublic 查詢介面。 - 修改
TaskExecutionRecord/TaskNodeExecutionRecordpublic constructor 或 property。 - 對真實 DB 執行
CREATE TABLE、ALTER TABLE、DROP TABLE。 - 對真實 DB 執行未確認的
INSERT、UPDATE、DELETE。 - 將 DB writer 自動接入 ConsoleHost、ServiceHost、WebApi 或正式啟動流程。
- 導入背景佇列、批次 worker、retention job 或正式排程。
- 新增或更換 MySQL 套件。
- 保存未遮蔽的 password、token、secret、authorization 或完整 connection string。
11. 建議實作順序
建議下一步分成小批:
task_log_tracesschema class 與 SQL preview 測試。- payload sanitizer 與 mapper。
MySqlLogWriterfake gateway 第一版。- writer failure fallback 測試。
- 文件同步與進度更新。
- 另行討論是否需要
TaskTraceStorepublic 查詢介面。 - 使用者確認後再建立 manual-only 真實 DB 驗證節點。
12. 本次結論
目前專案已具備進入 DB LogWriter / TraceStore 第一版的前置條件,且可以先不修改 Core public contract。
建議下一步實作「task_log_traces schema class + payload sanitizer + MySqlLogWriter fake gateway 測試」,但仍不得自動建立 MySQL table、不得自動接入 ConsoleHost,也不得對真實 DB 寫入。