白話說明

Log 轉發送得出去,但客戶的 log server(Graylog)收到流量卻一筆都存不下來。原因是我們送出的封包格式不合 RFC 5424 規格,Graylog 嚴格照規格解析,解不開就整筆丟掉——所以在網路上看得到流量,在 Graylog 畫面上什麼都沒有。

不是 Graylog 設定問題,是我們這邊的 bug。

兩個缺陷

① 每筆訊息尾端多一個 NUL byte(致命,主因)

實際抓到的封包長這樣:

... GET /api/1.0/users/menu\x00
                            ^^^^ 多這個

來源是 Python 標準函式庫的 SysLogHandler——它的 append_nul 預設是 Trueemit() 內寫死 msg += '\000'。那是為了相容某些老式 syslog daemon 留的行為,RFC 5424 沒有這個結尾

修法build_target_handler() 建完 handler 後設 handler.append_nul = False(標準函式庫本來就留這個屬性給人關)。

② 時戳宣告 UTC 但給的是台北時間(每筆早 8 小時)

送出的時戳:2026-08-27T16:37:40.274Z

結尾的 Z 在 RFC 5424 代表 UTC,但容器時區是 CST(UTC+0800),而 logging.Formatter.formatTime() 預設走 time.localtime——所以那個 16:37 其實是台北時間,真正 UTC 是 08:37。等於宣告 UTC 卻給了 +8 的值。

就算 ① 修好,Graylog 上每筆 log 的時間都會早 8 小時

修法_Rfc5424Formatter.converter = time.gmtime。設在 converter 而不是只改手動組的那一段,這樣「本 formatter 產出的所有時間」都是 UTC,不會漏掉其他路徑。

同類坑:CM-1317(agent last_seen_at 時區)。

驗證方式(這次真的解析,不是只看有沒有送到)

起 UDP socket 收下實際封包,然後斷言三件事:

  1. bytes 不以 \x00 結尾
  2. 用 regex 依 RFC 5424 結構(<PRI>VERSION TIMESTAMP HOSTNAME APP-NAME PROCID MSGID SD MSG解析成功
  3. 時戳與當下真 UTC 相差 < 120 秒