裏取りステータス: Discrepancy-found(singleton 化は未実装)
sonic-buildimage/src/sonic-py-common/sonic_py_common/syslogger.py L18 class SysLogger: には __new__ も _instance も無く、普通のクラスとして毎回新規インスタンスを返す(singleton 化されていない)。__init__ は L26 で enable_runtime_config=False 引数を受け、L43-45 で True のとき self.update_log_level() を呼んで CONFIG_DB.LOGGER を読む実装は確認 (L48-69)。require_manual_refresh フィールドは L9 FIELD_REQUIRE_REFRESH = 'require_manual_refresh' と L62-66 で初期登録時に 'true' を書く処理として確認。sonic-utilities/config/syslog.py L647-686 で config syslog level CLI と require_manual_refresh 判定分岐を確認。HLD は singleton 採用を明記しているが、現行 master 実装はクラスの 共有 logger オブジェクトを logging.getLogger(name) に委ねる方式に置き換わっており、HLD 文面は古い (verified at: 2026-05-09)。
SysLogger 拡張(runtime log level + LOGGER.require_manual_refresh + SIGHUP)¶
概要¶
SONiC の Python デーモンが使う logger には複数の選択肢があるが、いずれも 動作中にログレベルを変更できない または redis 起動前に呼べない という不足があった1:
| logger | 問題 |
|---|---|
sonic_py_common.logger.Logger |
runtime 変更不可。さらに deprecate 予定 |
sonic_py_common.syslogger.SysLogger |
runtime 変更不可 |
swsscommon.Logger(C++ 実装の Python wrap) |
(1) 起動時に redis を必要とする (2) Linux syslog の制約で daemon 単一 identifier しか持てない |
本 HLD は SysLogger を中心に runtime ログレベル変更 を可能にし、redis 未起動時のフォールバックも担保する。swsscommon.Logger のような 常駐スレッド方式は採らず、CLI 経由で SIGHUP を送って refresh する設計を採用する(Python script は短命なものが多く、スレッド常駐がコストになるため)1。
動作仕様¶
SysLogger クラスの変更¶
- Singleton 化1
__init__にenable_runtime_config: bool = False引数を追加True指定のデーモンだけが runtime 設定を使うTrueのとき初期化で CONFIG_DB から log level を読む(DB に設定があれば)Trueのとき DB に設定が無ければ初期化で デフォルトを DB に書き込む(saveフォールバック)- 新しいクラスメソッド
update_log_level: load / save の制御を集約
起動 / refresh フロー¶
flowchart TB
A[SysLogger 生成] --> B{enable_runtime_config?}
B -->|False| Z[default level で動作]
B -->|True| C{redis 起動済 & LOGGER エントリあり?}
C -->|Yes| D[DB から level を load]
C -->|No, redis OK で エントリなし| E[default を DB に save]
C -->|No, redis 自体未起動| Z
D --> R[runtime に level 反映]
E --> R
R --> RUN[ログ出力]
RUN -.-> SIG[SIGHUP 受信]
SIG --> R2[update_log_level\nDB から再ロード]
「redis が無いと壊れる」を避けるため、redis 未起動時は default level でそのまま動く。swsscommon.Logger のように初期化で接続を必須にしない1。
CLI¶
swssloglevel は swsscommon.Logger のスレッドに依存し、他コンテナの daemon にはシグナルを送れない1。本 HLD では新しい CLI を追加:
config syslog level -c <component> -l <log_level>
[--service <service_name>]
[--program <program_name>]
[--pid <pid>]
| オプション | 意味 |
|---|---|
-c |
component / log identifier。LOGGER テーブルのキー |
-l |
log level(DEBUG / INFO / NOTICE / WARN / ERROR) |
--service |
コンテナ名。SIGHUP を送る対象コンテナ |
--program |
コンテナ内のプログラム名。--service 必須 |
--pid |
プロセス ID。--service 指定時はそのコンテナ内 PID、未指定時はホスト側 PID |
検証ルール(HLD 例より)1:
--programは--serviceと併用必須--service単独は不可(PID か program のどちらかが必要)
例:
# DB 更新のみ(refresh は別途)
config syslog level -c xcvrd -l DEBUG
# DB 更新 + PMON コンテナ内の xcvrd に SIGHUP
config syslog level -c xcvrd -l DEBUG --service pmon --program xcvrd
# DB 更新 + PMON コンテナ内 PID 20 に SIGHUP
config syslog level -c xcvrd -l DEBUG --service pmon --pid 20
# DB 更新 + ホスト側 PID 20 に SIGHUP
config syslog level -c xcvrd -l DEBUG --pid 20
CONFIG_DB スキーマ追加¶
LOGGER テーブルに require_manual_refresh フィールドを新設1:
| フィールド | 型 | 値 |
|---|---|---|
require_manual_refresh |
bool | Python logger は true、C++ logger は 設定しない |
CLI はこのフィールドを見て SIGHUP を送る必要があるか を判断する。C++ logger は swsscommon.Logger のスレッドが自動 reload するため、SIGHUP 不要。Python logger は能動的にシグナルを送る必要がある1。
sequenceDiagram
participant U as user
participant CLI as config syslog level
participant DB as CONFIG_DB.LOGGER
participant DEM as Python daemon
U->>CLI: config syslog level -c xcvrd -l DEBUG --service pmon --program xcvrd
CLI->>DB: SET LOGGER|xcvrd loglevel=DEBUG
CLI->>DB: GET LOGGER|xcvrd require_manual_refresh
alt require_manual_refresh=true
CLI->>DEM: docker exec pmon kill -HUP <pid>
DEM->>DB: load LOGGER|xcvrd loglevel
DEM->>DEM: 反映
else (C++ logger)
Note over DEM: swsscommon.Logger のスレッドが自動で反映
end
📋 検証エビデンス: sonic-net/SONiC/doc/syslog/python-logger-enhancement.md#L36-L46 (sha: 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06)
出典:
sonic-net/SONiC/doc/syslog/python-logger-enhancement.md#L36-L46 (sha: 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06)
抜粋:
- SysLogger class shall be changed to a singleton.
- SysLogger instance shall load log level configuration from DB during initialization stage if DB configuration is available.
- SysLogger instance shall save log level configuration to DB during initialization stage if DB configuration is not available.
- Logger configuration shall be refreshed by CLI which send a SIGHUP signal to the daemon.
判断根拠: 「singleton + 初期化時 load/save + SIGHUP refresh」という設計の核となるルールの根拠。
Scope の限定¶
sonic_py_common.logger.Logger は deprecate 予定 のため、本機能の対象外1。本 HLD は SysLogger のみ を拡張対象とする。
Warmboot / Fastboot¶
影響なし1。
設定¶
CLI¶
| Command | 用途 |
|---|---|
config syslog level -c <component> -l <level> [...] |
当該 logger の level を CONFIG_DB に書き、必要なら SIGHUP |
関連する CONFIG_DB¶
LOGGER|<component>
loglevel : DEBUG | INFO | NOTICE | WARN | ERROR
require_manual_refresh : "true" | (未設定)
関連する YANG¶
HLD 自体は YANG 言及なし。LOGGER テーブルは sonic-buildimage/src/sonic-yang-models/yang-models/sonic-logger.yang の container LOGGER で取り込まれており、require_manual_refresh leaf も定義済。syslog 系設定は sonic-syslog.yang を参照。
制限事項¶
- 対象は
sonic_py_common.syslogger.SysLoggerのみ。logger.Loggerは deprecate 予定で対象外1 swssloglevelは他コンテナへ届かない既知の制約あり。新 CLI を使う必要がある- Python script が 常駐していない場合は SIGHUP できない。短命スクリプトは次回起動時に DB から load するだけ
require_manual_refreshを C++ logger 側に誤って入れるとswsscommon.Loggerのスレッドと競合し得る。未設定が正
干渉する機能¶
swsscommon.Logger(C++): 同じLOGGERテーブルを共有。require_manual_refreshで挙動を区別hostcfgd: 一部 syslog 設定を扱うが、本 HLD のスコープ外docker exec/kill -HUP: コンテナ越しのシグナル送出に依存- 永続化:
LOGGERテーブルの永続化(config save)と整合させる
トラブルシューティング¶
config syslog levelで DB は変わるが反映されない場合、SIGHUP が当該プロセスに届いているか(--service/--program/--pidの組合せ)を確認- redis 未起動で例外になる場合、
enable_runtime_config=Falseのまま使われていないか・初期化順序を確認 - C++ logger と混在する component で動作が不一致な場合、
require_manual_refreshの値が想定どおりか確認
# syslog level の動的変更と確認
config syslog level --container swss --program orchagent --level DEBUG
sonic-db-cli CONFIG_DB hgetall "LOGGER|orchagent"
# SIGHUP 配送確認
ps -ef | grep orchagent
docker exec swss kill -HUP $(docker exec swss pidof orchagent)
HLD と実装の差分
2026-05-11 時点の現行 master を裏取り。
1. ファイル + 行番号¶
- 取り込み済み:
sonic-net/sonic-buildimagesrc/sonic-py-common/sonic_py_common/syslogger.pyL26(enable_runtime_config引数)、同 L34-L36(既存 handler のremoveHandler重複防止)、同 L48-L69(update_log_level()の CONFIG_DB.LOGGER 読み取りと初回require_manual_refresh='true'書き込み、redis 未起動時の(False, msg)返却)。 - 取り込み済み:
sonic-net/sonic-utilitiesconfig/syslog.pyL647-L686(config syslog levelサブコマンド、require_manual_refresh判定、対象プロセスへの SIGHUP 送出)。 - HLD と差分あり: HLD が要求する
SysLoggerの singleton 化(__new__/_instance共有)は 未実装。現行は普通のclass SysLogger:で、同名 logger に対するlogging.getLogger(name)共有 + 既存 handler 除去で重複ハンドラを抑止している。
2. 差分の中身¶
HLD は概ね以下を要求していた:
class SysLogger:
_instances = {}
def __new__(cls, identifier, *args, **kwargs):
if identifier not in cls._instances:
cls._instances[identifier] = super().__new__(cls)
return cls._instances[identifier]
現行実装は __new__ を override せず、毎回新しいインスタンスを返す。同一 identifier で SysLogger("foo") を 2 回呼ぶと 別オブジェクトだが、内部の logging.Logger は getLogger("foo") で共有される。L34-L36 で先に登録された handler を removeHandler することで「同一 logger に同じ handler が複数付く」事故を回避している。
3. 読者への影響¶
- 実用上のログ重複は発生しないため、エンドユーザ運用には影響なし。
- ただし
SysLoggerインスタンスをis比較したり、インスタンス属性に状態を持たせる設計の上位コードを書くと、想定外に複数オブジェクトが存在する。 - redis 未起動状態で
update_log_level()を呼ぶと例外を握って(False, msg)を返すだけで、自動フォールバックは無い。
4. 回避策¶
- 「同じ component で 1 つの logger 状態を共有したい」場合は
logging.getLogger(name)の共有性に依存する(インスタンス側ではなく logger 側に状態を持たせる)。 - redis 未起動時に備えるなら、上位で
update_log_level()の戻り値を(success, msg)で判定し、enable_runtime_config=Falseのフォールバック経路を別途用意する。 - 短命 Python スクリプトは SIGHUP では追従しないので、起動時に必ず
update_log_level()を呼ぶか、config syslog levelの--container/--programで対象プロセスを明示する。
関連 GitHub Issue / PR¶
- [GitHub Issue / PR の関連リンクは未確認] —
SysLogger拡張 (runtime log level /require_manual_refresh/ SIGHUP) はsonic-py-commonの小規模機能追加として段階的に取り込まれており、HLD と 1:1 で紐づくトラッキング Issue / PR は確認できず。
参考リンク¶
関連 reference¶
確認コマンド¶
# 現在の log level 設定 (CONFIG_DB)
sonic-db-cli CONFIG_DB KEYS 'LOGGER|*'
sonic-db-cli CONFIG_DB HGETALL 'LOGGER|orchagent'
# 動的変更
sudo config logging level INFO orchagent
# Python ロガー側 (sonic-py-common.logger) を使うデーモン群
grep -rn 'from sonic_py_common import logger' .cache/sonic-sources/sonic-buildimage/src/ 2>/dev/null | head
トラブルシュート¶
- log level を変更しても反映されない場合、デーモンが
sonic_py_common.logger.Logger.set_min_log_priority_from_cfg_db()を呼んでいない可能性。該当デーモンの再起動で復帰する。 - syslog rate limit (
/etc/rsyslog.d/) によりログが落ちている場合はrsyslogの imuxsock / RateLimit パラメータを確認。 - multi-asic 環境では namespace ごとに
LOGGERテーブルが分かれる点に注意 (sonic-db-cli -n asic0 ...)。
引用元¶
このページを読んだ後の次アクション¶
読み手向け
- 本機能を実運用で使う場合: 実装は存在するが本 HLD の記述と乖離。最新 master の動作を別途確認した上で適用する
- upstream 動向を追う場合: 関連 issue / PR を sonic-net/SONiC で検索(HLD タイトル / CONFIG_DB テーブル名 / Orch クラス名で grep するのが速い)
- 代替手段 / 関連 reference: 本ページの frontmatter
relatedが空のため、Reference 索引 から関連テーブル / CLI / YANG を辿る
本ドキュメントの追跡
- monitor:
evolved_beyond_hld/ last_verified:2026-05-09 - 次回再裏取りトリガ: quarterly。一覧は discrepancy-index を参照(運用詳細は repo の
meta/discrepancy-operations.md)