📘

【Python】PythonでRFC6587形式のSyslogログを生成する

に公開

PythonでRFC6587形式のSyslogログを生成する

SyslogをTCPで送信する場合、メッセージの区切り方を定義した仕様として RFC6587 があります。
ざっくりいうと、このRFCでは Octet Counting などのフレーミング方式が定義されています。
そこで勉強がてらにRFC6587に基づいたログをPythonを使って簡単に生成するプログラムを書いてみました。


プログラム本体

import argparse
import random
import string
from datetime import datetime

def generate_random_string(length):
    return ''.join(random.choices(string.ascii_letters + string.digits, k=length))

def generate_syslog_message(min_size, max_size, embed_str=None):
    pri = '<34>'
    version = '1'
    timestamp = datetime.utcnow().isoformat() + 'Z'
    hostname = 'localhost'
    app_name = 'testapp'
    procid = str(random.randint(1000, 9999))
    msgid = 'ID' + str(random.randint(100, 999))
    structured_data = '-'
    # メッセージ部分の長さを計算
    base_fields = f"{pri}{version} {timestamp} {hostname} {app_name} {procid} {msgid} {structured_data} "
    # 埋め込み文字列を含める
    embed = embed_str if embed_str else ''
    # 残りの長さを計算
    total_size = random.randint(min_size, max_size)
    msg_len = total_size - len(base_fields) - len(embed)
    if msg_len < 0:
        msg_len = 0
    message = embed + generate_random_string(msg_len)
    syslog_msg = f"{base_fields}{message}"
    return syslog_msg

def main():
    # 件数は内部パラメータで指定
    log_count = 10  # ここを編集することで件数を変更可能
    parser = argparse.ArgumentParser(description='Generate RFC5424 syslog messages in Octet Counting format.')
    # parser.add_argument('--count', type=int, required=True, help='Number of log messages to generate')
    parser.add_argument('--min-size', type=int, default=1024, help='Minimum size of each log message')
    parser.add_argument('--max-size', type=int, default=2048, help='Maximum size of each log message')
    parser.add_argument('--embed', type=str, default='', help='String to embed in each message')
    parser.add_argument('--output', type=str, default='sample.log', help='Output file name')
    args = parser.parse_args()

    with open(args.output, 'w') as f:
        for _ in range(log_count):
            msg = generate_syslog_message(args.min_size, args.max_size, args.embed)
            octet_counted = f"{len(msg)} {msg}\n"
            f.write(octet_counted)

if __name__ == '__main__':
    main()

実行例

$ ls      
mk_RFC_6587.py
$ python mk_RFC_6587.py 
$ ls
mk_RFC_6587.py  sample.log
$ 

上記を実行すると、カレントディレクトリに sample.log が生成されます。

中身はこんな感じ👇

1198 <34>1 2025-08-21T23:31:18.219930Z localhost testapp 4982 ID107 - 0VJYP6rRzYIwXe0xoaoFC2MXsmO6h20HNND51rybtzuJ7TtaI1rjrlgK0j9oy7hUaU94eGvLP93iiWA3ROTcG39bxXvdF80NVEkc0mo36gdHdBNvVINZsQoLO4WI1CJBSw20GiAcbmVTBWjdlOehQw1aiLsiOeuoYfv0LANQsh2TuPHv5QrNsbf3yyHvi1yeTnY2BpGxfivmF7qZhckd8G4ZtEAhoipeltt5DN55YZuRy1RdWMo5E1GmBmsadkEiuygvzQtmWmiics3TrjZOfx6tSkRTXuQTuR61Pt6zZ5TGEPaXRReJaKU2HtgNoJgvqXsAggxYs0Ru40CCOnuFmNjBRWuE40ZBTfmOXZvhO36YMsIY5FxC5L4ZfatcchG3RnyFcY9FjpYNmDgqTfWrDWHYUuCE7wsNm0C61QggfZ7sKHGoXWAk57F2uggf0DXMHGxob209MPvcGRgz1nr0jcqIpm1fSh7pjZzZtUbiFmNVpl8iESzC4wZrNlQ0fSRnPw4Hc2GoKzSma5FbUpLPUBq2eFOsr09wiGG4QwfyZtfhhZ0piEkCpd3zgYbPzwdegpDD8TXZSAjLZ9XmLCvJWdLHuYJoWvQvGmO2jOQblIBphtVw1xjs6Bv3YVPft12fI7QBQepHoQeC9yU5BG3FxIhG0xJRfgZl8qIAxRPwnxYA3zxyCMmQbV3ZMEIbxiRBwffVPAgoN8oPx4GxT9Cy7xjzXWfOy3nfdx9wZQToKcGRNT0us1U8tbuNOq2e2hIhz8IZxqddPDUWQQLwv27peKPFImHy04jcqyAT8yOqI9Jaqz60vNdm6WglNRVUDCRNV983vkJnyAaFE2V8izoU0YsJDOL1zdgtVv42l7FkBIBX9rK5yJqxCtwsfhp28mEa87AbHja18biSJthdiKemXXerhkMqSOwADc2Iyvr9CjL85NoWEDZ2KtHVzpHaAEqbE2DkkNg8M4CKF6cH2MJ8Uw5fmGS0EelsbpJ0wSxY8P0LMsIW7NnzAldw8kd0lfsqXkwcl6MEzzWqUARinZ5sl9JjzIybGHGSHF3vT1IkXmQutdMrip1lfnyfOTy6URd8ZznpyglUJuJvm31ev4zpn5GUXGV53LFq3WwLYNYvEt8y5

先頭の 1198 が Byte数 で、後ろに続く文字列が RFC5424 形式の Syslog メッセージです。


調整ポイント

  • 出力件数は log_count を書き換えることで制御可能
  • 各ログのサイズは --min-size / --max-size オプションで調整可能
  • メッセージ中に固定文字列を埋め込みたい場合は --embed オプションを利用可能

まとめ

  • RFC6587 で定義される Octet Counting は「長さ + スペース + Syslogメッセージ」という形式
  • この Python スクリプトを使えば、簡単にテスト用のサンプルログを生成できる
  • rsyslog / syslog-ng / Fluentd などのログ受信テストにも便利

Discussion