10. イベントストリームリスナー
に接続します イベントチャンネル (ポート 10020) システムイベントを出力し、レベル、名前パターン、除外条件によるフィルタリングをオプションで指定できます。読み取り専用 — セッションプロファイルは作成されず、コマンドも送信されません。
学習内容:
- 「」を購読する イベント WebSocket (ポート
10020()として、ただ傍観者として - 構文解析 イベントのJSON —
level,name,category,data,message - 深刻度の最低レベルでフィルタリングする
- ワイルドカードによる名前の照合と除外
- このチュートリアルを使用して、他のチュートリアルと並行して制御ループのベンチマークを行う
ワークフロー
- CLI オプションを解析する (
--level,--name,--exclude,--no-hide-rate,--port). - 接続する
ws://localhost:10020(その イベントチャンネル) — これは読み取り専用のオブザーバーであるため、セッションプロファイルは送信されません。 - 受信したメッセージごとに、イベントのJSONを解析し、フィルタを適用します:
- 以下の場合はドロップ
level深刻度が最低レベルを下回っています。 - もし
--nameパターンが指定されている場合、いずれか一つに一致しない限りドロップする(以下のいずれかと照合して)name単独で、またはcategory/name). - もしあれば
--excludeパターンに一致した場合、破棄する。
- 以下の場合はドロップ
- 残存するイベントを、そのレベル、修飾名、オプションのメッセージ、およびオプションの
dataペイロード。
パラメータ
| 旗 | デフォルト | 目的 |
|---|---|---|
--port | 10020 | イベントチャネルポート |
-l, --level | info | 最小の深刻度 — 以下のいずれか info, notice, warning, error, critical, panic |
-n, --name | (なし) | パターンに一致するイベントのみを表示(グロブ、繰り返し可能) |
-x, --exclude | (なし) | パターンに一致するイベントを非表示にする(グロブ、繰り返し可能) |
--no-hide-rate | false | 含める system-rate-report イベント(デフォルトでは非表示 — ノイズが多すぎる) |
1つのターミナルで任意のチュートリアル(04-hello-floor、05-position-control、06-combined...)を実行し、 --no-hide-rate 別の場所で。その system-rate-report このイベントには、デバイスの実効ティックレートが含まれています。同じチュートリアルのPython版、C++版(nlohmann)、およびC++版(Glaze)を比較することで、約4 kHzの制御ループにおけるシリアライゼーションのオーバーヘッドを確認できます。
# Terminal 1 — pick a variant
./04-haply-inverse-hello-floor # C++ nlohmann
./04-haply-inverse-hello-floor-glz # C++ Glaze
python 04-haply-inverse-hello-floor.py # Python
# Terminal 2 — watch the rate
./10-haply-inverse-events --no-hide-rate
状態フィールドを読み取る
受信する各メッセージは、1つのイベントです:
level— 文字列の重大度 (info...panic)name— イベント名(例:device-connected,system-rate-report)category— カテゴリ(例:device,session,system)message— 任意の、人間が読みやすい文字列data— オプションのネストされたJSONペイロード(形式はイベントによって異なります)
イベント一覧:イベントとモニタリング。
送信/受信
パッシブ・サブスクリプションのみ recv() が使用され、何も返されません。3つのバリエーションはすべて同じフィルタパイプラインを実装しています。Inverse-API特有の興味深い点は、イベント構造体の形状です。
- Python
- C++ (nlohmann)
- C++ (Glaze)
async for msg in websocket これは、受信専用ループの最も短い形式です。
async with websockets.connect(uri) as websocket:
async for msg in websocket:
try:
event = json.loads(msg)
except json.JSONDecodeError:
continue
if accept_event(event, min_level_index, name_patterns, exclude_patterns):
print(format_event(event))
libhv コールバックモデル — onmessage I/Oスレッド上で実行され、メインスレッドはENTERでブロックされます。イベントは型指定のないJSONとして扱われ、各フィールドは .value(...) デフォルトで。
ws.onmessage = [&](const std::string &msg) {
json event;
try { event = json::parse(msg); } catch (...) { return; }
if (accept_event(event, opts.min_level, opts.name_patterns, opts.exclude_patterns))
print_event(event);
};
ws.open("ws://localhost:10020");
while (std::cin.get() != '\n') {} // block main thread
既知のイベントフィールドは、型付き event_data 構造体。その data フィールドはそのまま glz::raw_json_view そのため、(イベントに依存する)任意のネストされたペイロードを、完全なスキーマを定義することなく、そのまま転送することができます。
// Struct model — known fields typed, nested `data` kept as raw JSON
struct event_data {
std::string level;
std::string name;
std::string category;
std::string message;
glz::raw_json_view data{};
};
// Send / receive
ws.onmessage = [&](const std::string &msg) {
event_data event{};
if (glz::read<glz_settings>(event, msg)) return; // drop malformed
if (accept_event(event, opts.min_level, opts.name_patterns, opts.exclude_patterns))
print_event(event);
};
ws.open("ws://localhost:10020");
while (std::cin.get() != '\n') {} // block main thread