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 | (なし) | パターンに一致するイベントのみを表示(glob、複数指定可) |
-x, --exclude | (なし) | パターンに一致するイベントを非表示にする(glob、複数指定可) |
--no-hide-rate | false | system-rate-report イベントを含める(デフォルトでは非表示 — ノイズが非常に多いため) |
任意のチュートリアル(04-hello-floor、05-position-control、06-combined...)を1つのターミナルで実行し、もう1つのターミナルで --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
チュートリアル10もSDKと一緒にローカルにインストールされています。サービスのインストールディレクトリ内の tutorials/10-haply-inverse-events/ ご確認ください。