跳轉到

目錄與 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 是操作者 cdls 的便利工具。

兩者必須一致;若不一致,tapio-core 啟動時會 fatal,攔截「只升了其中一個」的操作失誤。

storage/ 各類檔案說明

類別 檔案 寫入者 說明
Loader snapshot pre_open_*.jsonlfee.jsonluser.jsonl tapio-load-*、ops 維護 tapio-core 啟動時讀取
Runtime append-only r02.jsonlr03.jsonlorder_filled.jsonlorder_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 確認候選範圍:

tapioctl archive --older-than 7d --dry-run
tapioctl archive --older-than 7d

每日一顆 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 symlinktapioctl rollover 沒跑成功。重跑一次

  • storage/system_datestorage/current/meta.json 日期不符tapio-core 啟動時會 fatal。確認 rollover 流程是否中途中斷,手動修正後重啟

  • 某天 spdlog 沒檔(log/20260416/tapio-core.*.txt 缺) → process 那天根本沒啟動。檢查 log/20260416/stdout/core.logtapioctl start 是否成功

  • stdout log 過大 → 通常是 binary 一直印錯誤訊息或 libc warning。看內容定位 → 短期解:手動 truncate/archive;長期解:修 binary 的噪音

  • tapio-core 啟動失敗:.staging 檔殘留 → 某個 loader 在 commit 前 crash。重新執行對應的 tapioctl preopen 或手動呼叫對應的 tapio-load-* 工具