🦫

structlogのJSONRendererでマルチバイト文字を表示させる

2025/01/21に公開

忙しい人用

ensure_ascii=Falseを指定すれば良い
https://github.com/1hakusai1/structlog-multibyte-characters/blob/84259d608b449b70362178b590cd1775d25b7ce9/main.py

structlogってなに?

Pythonの構造化logger。ログをJSONで吐かせることもできる。
https://www.structlog.org/en/stable/

困ったこと

公式のexample通りにJSONでログを出力させると、マルチバイト文字はエスケープして表示される。

import structlog


def main():
    structlog.configure(processors=[structlog.processors.JSONRenderer()])
    log = structlog.getLogger("my-logger")
    log.info("こんにちは", hoge="ほげ")


if __name__ == "__main__":
    main()
{"hoge": "\u307b\u3052", "event": "\u3053\u3093\u306b\u3061\u306f"}

原因

JSONRendererはデフォルトでjson.dumpsを使ってレコードをJSONに変換する。
https://github.com/hynek/structlog/blob/a38a5ac5d6e7a461b0c304294b7446a2bf674410/src/structlog/processors.py#L315-L352

json.dumpsはデフォルトでensure_ascii=Trueが指定されており、ascii文字以外はエスケープされるようになっている。
https://docs.python.org/3.13/library/json.html#basic-usage

解決策

JSONRendererdumps_kwで指定された引数をserializerに渡してシリアライズ処理を行うので、ensure_ascii=Falseを渡してあげればよい。

import structlog


def main():
    structlog.configure(
        processors=[structlog.processors.JSONRenderer(ensure_ascii=False)]
    )
    log = structlog.getLogger("my-logger")
    log.info("こんにちは", hoge="ほげ")


if __name__ == "__main__":
    main()

{"hoge": "ほげ", "event": "こんにちは"}

Discussion