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...)을 실행하고, 다른 터미널에서 --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
읽기 상태 필드
수신되는 각 메시지는 하나의 이벤트입니다:
level— 문자열 심각도(info...panic)name— 이벤트 이름(예:device-connected,system-rate-report)category— 카테고리(예:device,session,system)message— 선택 사항인, 사람이 읽을 수 있는 문자열data— 선택 사항인 중첩 JSON 페이로드(구조는 이벤트에 따라 다름)
전체 이벤트 목록은 ‘이벤트 및 모니터링’을참조하십시오.
송신 / 수신
수동 구독이므로 recv()만 사용하며 아무것도 반환하지 않습니다. 세 가지 변형 모두 동일한 필터 파이프라인을 구현하며, Inverse API에 특화된 부분 중 주목할 점은 이벤트 구조체의 형태입니다.
- 파이썬
- 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/에서 확인해 주십시오.
소스 코드: Python · C++ · C++ Glaze
관련 문서: 이벤트 및 모니터링 · WebSocket 프로토콜