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/ を確認してください。
関連: イベントとモニタリング · WebSocket プロトコル