目錄與 log 配置¶
/opt/Tapio/ 全貌¶
/opt/Tapio/
├── bin/ # 所有受管 binary(tapio-core、tapio-quote-receiver、tapioctl 等)
├── etc/ # 設定檔與 TLS 憑證;RPM 安裝,runtime 不修改
│ ├── Tapio.toml # 主設定檔
│ ├── Tapio.toml.example # 範本設定,供安裝參考;不影響 runtime
│ └── certs/
│ ├── gateway.crt # gRPC 伺服器 TLS 憑證
│ └── gateway.key # gRPC 伺服器 TLS 私鑰
├── libexec/ # tapioctl 呼叫的 helper(不直接執行)
│ ├── tapio_check
│ └── tapio-daemon-wrapper.sh # daemon 啟動 wrapper:轉發 SIGTERM/INT 並在停止後寫出 exit marker
├── data/ # broker/行情原始資料交換區
│ ├── preopen/
│ │ ├── current -> 20260416/ # symlink,rollover 維護(操作者便利用)
│ │ └── 20260416/ # 從期貨商拋檔目錄複製過來的原始檔案(flat 檔名,如 BALANCE_S.TXT)
│ ├── quote/
│ │ └── quote.shm # `tapio-quote-receiver` 行情資料串流
│ └── taifex/
│ └── 20260416/ # tapio-taifex-fetcher 從期交所 SFTP 拉取的盤前檔
├── run/ # 所有 daemon 的 pid + lock + exit marker,生命週期真值來源
│ ├── core.pid
│ ├── core.lock
│ ├── live-sync.pid
│ ├── live-sync.lock
│ ├── quote-receiver.pid
│ ├── quote-receiver.lock
│ ├── quote-writer.lock
│ ├── taifex-fetcher.pid
│ ├── taifex-fetcher.lock
│ ├── mail.lock
│ ├── mail.exit # 由 tapio-daemon-wrapper.sh 寫入;記錄 daemon 停止原因
│ └── archive.lock
├── log/ # spdlog per-run 檔、stdout 重導、封包側錄、稽核日誌
│ ├── current -> 20260416/ # symlink,rollover 維護(操作者便利用)
│ └── 20260416/
│ ├── stdout/ # tapioctl 重導的 stdout/stderr
│ │ ├── core.log
│ │ ├── quote-receiver.log
│ │ ├── live-sync.log
│ │ ├── mail.log
│ │ └── taifex-fetcher.log
│ ├── tapio-core.121719.txt # per-run spdlog(每次 start 開新檔)
│ ├── tapio-live-sync.121719.txt
│ ├── tapio-load-balance.121719.txt
│ ├── tapio-load-fee.121719.txt
│ ├── tapio-load-investor-setting.121719.txt
│ ├── tapio-load-position.121719.txt
│ ├── admin_api_log.jsonl # admin API RPC 稽核日誌(每次呼叫一行;append-only)
│ └── packet.121719.jsonl # 封包側錄(客戶端↔`tapio-core`、`tapio-core`↔交易所雙向;僅 Tapio)
├── archived/ # tapioctl archive 壓縮封存;等待搬到 NAS
│ ├── 20260310.tar.zst # 每日一顆(zstd)
│ └── ...
├── share/
│ └── tapioctl/
│ └── tapioctl-completion.bash # tapioctl bash completion 腳本
└── storage/ # 持久化層:snapshot、append-only 紀錄、API key 等
├── system_date # 當前交易日(單行 YYYYMMDD)
├── current -> 20260416/ # symlink,rollover 維護(操作者便利用)
├── persistent/
│ ├── api_keys.jsonl # 跨日 API key store(append-only)
│ ├── processed_balance_refs.jsonl # `tapio-live-sync` 餘額更新去重紀錄(跨日保留)
│ ├── setting_override.jsonl # 投資人設定變更(跨日保留,啟動時 replay)
│ └── system_allow_trading.jsonl # 全域交易開關狀態(跨日保留,啟動時 replay)
├── mail_queue/
│ ├── pending/
│ ├── sent/
│ ├── fail/
│ └── tmp/
└── 20260416/
├── meta.json
├── conn_id.watermark # 4-byte binary;`tapio-core` 擁有
├── r02.jsonl # runtime:委託回報
├── r03.jsonl # runtime:錯誤回報
├── order_filled.jsonl # runtime:成交紀錄
├── order_risk.jsonl # runtime:下單風控紀錄
├── pre_open_position.jsonl # 盤前檔轉檔後通用格式:部位
├── pre_open_balance.jsonl # 盤前檔轉檔後通用格式:帳戶餘額
├── pre_open_investor.jsonl # 盤前檔轉檔後通用格式:投資人設定
├── fee.jsonl # 盤前檔轉檔後通用格式:手續費
├── balance_updates.jsonl # runtime:`tapio-live-sync` 每筆餘額更新帳本(append-only)
└── user.jsonl # 投資人登入憑證快照;ops 維護,啟動時讀取
Log 兩條路徑:spdlog vs stdout¶
兩種 log 分別寫,互不干擾:
| 來源 | 路徑 | 內容 | 切檔策略 |
|---|---|---|---|
| spdlog(binary 內部寫) | log/$today/<process>.<HHMMSS>.txt |
application log(業務邏輯、warning、error) | 每次 process 啟動開新檔,filename 是啟動時間 |
| tapioctl 重導 stdout | log/$today/stdout/<process>.log |
binary 印到 stdout/stderr 的東西(崩潰前 trace、libc 錯誤) | append;同一天重啟多次皆追加同一檔 |
| 封包側錄(僅 Tapio) | log/$today/packet.<HHMMSS>.jsonl |
exchange wire bytes tracer | 每次 start 開新檔 |
為什麼分兩條¶
- spdlog 有 buffer/flush 控制,崩潰時可能來不及 flush 最後一段 — 看 stdout 才能看到真正的死前訊息
- tapioctl daemon 化時必須重導 stdout/stderr,否則 setsid 後就丟了
- 兩者寫到不同檔避免互鎖
同一天重啟多次,tapioctl log core 以 mtime 最新的 spdlog 為現役;stdout log 則全部追加同一檔。
範例¶
ls -la /opt/Tapio/log/20260416/
# tapio-core.121719.txt # spdlog(process 啟動於 12:17:19)
# tapio-core.130149.txt # spdlog(同日重啟,啟動於 13:01:49)
# tapio-live-sync.121719.txt # spdlog
# tapio-load-balance.121719.txt # spdlog
# packet.121719.jsonl # PacketLogger wire tracer
# admin_api_log.jsonl # admin API 稽核
# stdout/
# core.log # 整天累積的 stdout/stderr
# quote-receiver.log
storage/system_date 與 storage/current¶
storage/system_date 是交易日的單一真值來源,由 tapioctl rollover 寫入。storage/current symlink 是操作者 cd/ls 的便利工具。
兩者必須一致;若不一致,tapio-core 啟動時會 fatal,攔截「只升了其中一個」的操作失誤。
storage/ 各類檔案說明¶
| 類別 | 檔案 | 寫入者 | 說明 |
|---|---|---|---|
| Loader snapshot | pre_open_*.jsonl、fee.jsonl、user.jsonl |
tapio-load-*、ops 維護 |
tapio-core 啟動時讀取 |
| Runtime append-only | r02.jsonl、r03.jsonl、order_filled.jsonl、order_risk.jsonl |
tapio-core 交易日中 |
append mode;啟動時 replay |
tapio-live-sync append-only |
balance_updates.jsonl |
tapio-live-sync |
每筆餘額更新一行;append mode |
| Watermark | conn_id.watermark |
tapio-core |
binary 檔 |
| 跨日 persistent | persistent/api_keys.jsonl |
admin 工具 | API key 列表;tapio-core 永不寫入 |
| 跨日 persistent | persistent/setting_override.jsonl |
tapio-core |
投資人設定開關;append-only,啟動時 replay |
| 跨日 persistent | persistent/system_allow_trading.jsonl |
tapio-core admin API |
全域交易開關狀態;append-only,啟動時 replay |
| 跨日 persistent | persistent/processed_balance_refs.jsonl |
tapio-live-sync |
餘額更新去重紀錄;防重啟後重複寫入帳本 |
storage/persistent/¶
跨交易日要保留的狀態放這。不要跟每日目錄的資料混淆 — 每日目錄每天重建,這裡的資料跨日保留。
| 檔案 | 寫入者 | 說明 |
|---|---|---|
api_keys.jsonl |
admin 工具 | API key 列表(格式 tapio-NNNNNNN-YYYYMMDD-<41hex>);tapio-core 永不寫入 |
setting_override.jsonl |
tapio-core |
投資人設定開關(deny_trading / deny_open_position);append-only,啟動時 replay |
system_allow_trading.jsonl |
tapio-core admin API |
全域交易開關狀態;append-only,啟動時 replay |
processed_balance_refs.jsonl |
tapio-live-sync |
餘額更新去重紀錄;防 handler 重啟後重複寫入帳本 |
保留 / 封存策略¶
系統不會自動壓縮或封存舊資料,需由 ops 手動或透過排程定期執行。建議以 --older-than 7d 為基準,執行前先 dry-run 確認候選範圍:
每日一顆 archived/<YYYYMMDD>.tar.zst,涵蓋四棵 per-date 樹(storage/、log/、data/preopen/、data/taifex/)。
保留期依稽核需求調整
下表為建議值,請依貴公司稽核或法遵規定調整。
| 本機保留 | NAS 保留 | 處理方式 | |
|---|---|---|---|
log/YYYYMMDD/ |
7 天 | 1 年 | tapioctl archive --older-than 7d 打包後移至 NAS |
storage/YYYYMMDD/ |
7 天 | 1 年 | 同上 |
data/preopen/YYYYMMDD/ |
7 天 | 1 年 | 同上 |
data/taifex/YYYYMMDD/ |
7 天 | 1 年 | 同上 |
archived/*.tar.zst |
7 天 | — | 打包後盡快 mv 至 NAS;本機僅暫存 |
執行 tapioctl check disk 可檢查磁碟使用率:使用率 ≥ 80% 時回傳警告、≥ 95% 時回傳失敗。若看到警告,應安排執行 archive。
archive 只會動已過期的 YYYYMMDD 目錄,不影響當日運作,任何時間點執行均安全。建議排週六或週日低峰時段定期跑即可。
排錯¶
-
storage/current是 stale symlink →tapioctl rollover沒跑成功。重跑一次 -
storage/system_date與storage/current/meta.json日期不符 →tapio-core啟動時會 fatal。確認 rollover 流程是否中途中斷,手動修正後重啟 -
某天 spdlog 沒檔(
log/20260416/tapio-core.*.txt缺) → process 那天根本沒啟動。檢查log/20260416/stdout/core.log看tapioctl start是否成功 -
stdout log 過大 → 通常是 binary 一直印錯誤訊息或 libc warning。看內容定位 → 短期解:手動 truncate/archive;長期解:修 binary 的噪音
-
tapio-core啟動失敗:.staging檔殘留 → 某個 loader 在 commit 前 crash。重新執行對應的tapioctl preopen或手動呼叫對應的tapio-load-*工具