テクノロジー · 実用ガイド
Python のログが毎回二重?handler と伝播グラフを先に監査する
一つの record に印を付け、root まで全 handler を追跡し、再設定・framework・multiprocess capture を分けて一つの重複 edge だけを外します。

重複した行だけでは診断になりません。一つの LogRecord が child と ancestor handler の両方に届く場合、同じ logger に handler が毎回追加される場合、framework が別 stream を持つ場合、別 process と collector が似た event を作る場合があります。
安全な修正は test record、PID、logger、handler identity を記録し、emitter から sink までの graph を作ることです。一つの ownership boundary だけを変え、元の command を再実行します。
event と line の重複を分ける
unique token、PID、logger name、level、高精度 timestamp を出し、console、file、collector を別々に捕捉します。同じ text が別 event の場合も、異なる format が同じ record の場合もあります。
実際の command、reloader、worker launcher、service unit で再現します。python app.py だけでは別の起動経路を証明できません。
logger-handler graph を出す
emitter の name、disabled、effective level、propagate と全 direct handler の object id、class、level、stream/file、formatter を記録し、parent から root まで進みます。
child と ancestor に同じ handler または同じ sink があり propagation が true なら二つの delivery path です。選んだ owner だけを残すか明示的 boundary で止めます。
再設定と propagation を分ける
import 前、startup 後、request 後、reload 後の handler count を比較します。stable graph の child/root handler は propagation、増える count は非 idempotent configuration です。
setup を一つの startup path に置き、既知 handler を再利用します。class だけで重複判定しません。
framework と process owner を守る
basicConfig 前に framework logger を確認します。Uvicorn の parent、error、access branch は別々に保持し、live graph と current docs を比較します。
probe に PID/process name を含めます。worker は QueueHandler から一つの listener または external collector に送り、stdout/stderr の二重収集も確認します。
一つの edge を外して検証する
sink ごとに application root、framework branch、queue listener、external collector の一 owner を選び、証拠のある edge だけを削除します。
startup、request、warning、framework error、access event を再実行し、一 sink 一 probe、reload 後の安定 count、必要 stream の存続を確認します。
