add metrics example from grok
This commit is contained in:
parent
361857d362
commit
2b21d62682
114
src/metric_client.py
Normal file
114
src/metric_client.py
Normal file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Minimal metric client with custom binary protocol.
|
||||
"""
|
||||
|
||||
import socket
|
||||
import struct
|
||||
import sys
|
||||
import threading
|
||||
|
||||
# Same constants as server
|
||||
MSG_PING = 0x01
|
||||
MSG_PONG = 0x02
|
||||
MSG_METRIC_REQ = 0x03
|
||||
MSG_METRIC_RESP = 0x04
|
||||
MSG_ERROR = 0xFF
|
||||
|
||||
HEADER_FMT = "!BH"
|
||||
HEADER_SIZE = struct.calcsize(HEADER_FMT)
|
||||
|
||||
|
||||
def send_message(sock: socket.socket, msg_type: int, payload: bytes = b"") -> None:
|
||||
header = struct.pack(HEADER_FMT, msg_type, len(payload))
|
||||
sock.sendall(header + payload)
|
||||
|
||||
|
||||
def recv_exact(sock: socket.socket, n: int) -> bytes:
|
||||
buf = bytearray()
|
||||
while len(buf) < n:
|
||||
chunk = sock.recv(n - len(buf))
|
||||
if not chunk:
|
||||
return b""
|
||||
buf.extend(chunk)
|
||||
return bytes(buf)
|
||||
|
||||
|
||||
def recv_message(sock: socket.socket) -> tuple[int, bytes]:
|
||||
header = recv_exact(sock, HEADER_SIZE)
|
||||
if not header:
|
||||
raise ConnectionError("Server disconnected")
|
||||
msg_type, length = struct.unpack(HEADER_FMT, header)
|
||||
payload = recv_exact(sock, length) if length > 0 else b""
|
||||
return msg_type, payload
|
||||
|
||||
|
||||
def listener_thread(sock: socket.socket, running: threading.Event):
|
||||
while running.is_set():
|
||||
try:
|
||||
msg_type, payload = recv_message(sock)
|
||||
if msg_type == MSG_PONG:
|
||||
print("\n [PONG] server alive")
|
||||
elif msg_type == MSG_METRIC_RESP:
|
||||
value = struct.unpack("!d", payload)[0]
|
||||
print(f"\n [METRIC] {value:.2f}")
|
||||
elif msg_type == MSG_ERROR:
|
||||
print(f"\n [ERROR] {payload.decode('utf-8')}")
|
||||
else:
|
||||
print(f"\n [???] Unknown type 0x{msg_type:02X}")
|
||||
print("> ", end="", flush=True)
|
||||
except ConnectionError:
|
||||
if running.is_set():
|
||||
print("\nServer disconnected.")
|
||||
break
|
||||
|
||||
|
||||
def show_wire_comparison():
|
||||
our_size = HEADER_SIZE + len(b"cpu")
|
||||
http_req = b"GET /metrics/cpu HTTP/1.1\r\nHost: localhost:9999\r\nAccept: application/json\r\n\r\n"
|
||||
print(f"\n--- Wire overhead comparison ---")
|
||||
print(f"Our protocol (METRIC_REQ 'cpu'): {our_size} bytes")
|
||||
print(f"Equivalent HTTP GET: {len(http_req)} bytes")
|
||||
print(f"HTTP is ~{len(http_req) / our_size:.0f}x larger\n")
|
||||
|
||||
|
||||
def main():
|
||||
host = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1"
|
||||
port = int(sys.argv[2]) if len(sys.argv) > 2 else 9999
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect((host, port))
|
||||
print(f"Connected to {host}:{port}")
|
||||
show_wire_comparison()
|
||||
|
||||
running = threading.Event()
|
||||
running.set()
|
||||
threading.Thread(target=listener_thread, args=(sock, running), daemon=True).start()
|
||||
|
||||
print("Commands: ping | get <metric> | quit")
|
||||
print("Metrics: cpu, memory, disk, loadavg, uptime\n")
|
||||
|
||||
try:
|
||||
while True:
|
||||
line = input("> ").strip()
|
||||
if not line:
|
||||
continue
|
||||
parts = line.split()
|
||||
cmd = parts[0].lower()
|
||||
|
||||
if cmd == "quit":
|
||||
break
|
||||
elif cmd == "ping":
|
||||
send_message(sock, MSG_PING)
|
||||
elif cmd == "get" and len(parts) == 2:
|
||||
send_message(sock, MSG_METRIC_REQ, parts[1].encode("utf-8"))
|
||||
else:
|
||||
print(" Unknown command.")
|
||||
finally:
|
||||
running.clear()
|
||||
sock.close()
|
||||
print("Disconnected.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
116
src/metric_server.py
Normal file
116
src/metric_server.py
Normal file
@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Minimal metric server with custom binary protocol (cannibalised from Claude).
|
||||
Demonstrates low-overhead sockets vs HTTP/REST.
|
||||
"""
|
||||
|
||||
import socket
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
import random
|
||||
import threading
|
||||
|
||||
# Protocol constants (shared with client)
|
||||
MSG_PING = 0x01
|
||||
MSG_PONG = 0x02
|
||||
MSG_METRIC_REQ = 0x03
|
||||
MSG_METRIC_RESP = 0x04
|
||||
MSG_ERROR = 0xFF
|
||||
|
||||
HEADER_FMT = "!BH" # 1 byte type + 2 bytes length (big-endian)
|
||||
HEADER_SIZE = struct.calcsize(HEADER_FMT)
|
||||
|
||||
|
||||
def get_metric(name: str) -> float:
|
||||
metrics = {
|
||||
"cpu": lambda: random.uniform(5.0, 95.0),
|
||||
"memory": lambda: random.uniform(30.0, 80.0),
|
||||
"disk": lambda: random.uniform(40.0, 90.0),
|
||||
"loadavg": lambda: os.getloadavg()[0] if hasattr(os, "getloadavg") else random.uniform(0.5, 4.0),
|
||||
"uptime": lambda: float(int(time.time()) % 100000),
|
||||
}
|
||||
fn = metrics.get(name)
|
||||
if fn is None:
|
||||
raise KeyError(f"Unknown metric: {name}")
|
||||
return fn()
|
||||
|
||||
|
||||
def send_message(sock: socket.socket, msg_type: int, payload: bytes = b"") -> None:
|
||||
header = struct.pack(HEADER_FMT, msg_type, len(payload))
|
||||
sock.sendall(header + payload)
|
||||
|
||||
|
||||
def recv_exact(sock: socket.socket, n: int) -> bytes:
|
||||
buf = bytearray()
|
||||
while len(buf) < n:
|
||||
chunk = sock.recv(n - len(buf))
|
||||
if not chunk:
|
||||
return b""
|
||||
buf.extend(chunk)
|
||||
return bytes(buf)
|
||||
|
||||
|
||||
def recv_message(sock: socket.socket) -> tuple[int, bytes]:
|
||||
header = recv_exact(sock, HEADER_SIZE)
|
||||
if not header:
|
||||
raise ConnectionError("Client disconnected")
|
||||
msg_type, length = struct.unpack(HEADER_FMT, header)
|
||||
payload = recv_exact(sock, length) if length > 0 else b""
|
||||
return msg_type, payload
|
||||
|
||||
|
||||
def handle_client(conn: socket.socket, addr: tuple) -> None:
|
||||
print(f"[+] Connected: {addr[0]}:{addr[1]}")
|
||||
try:
|
||||
while True:
|
||||
msg_type, payload = recv_message(conn)
|
||||
|
||||
if msg_type == MSG_PING:
|
||||
print(f" <- PING from {addr[0]}")
|
||||
send_message(conn, MSG_PONG)
|
||||
|
||||
elif msg_type == MSG_METRIC_REQ:
|
||||
name = payload.decode("utf-8")
|
||||
print(f" <- METRIC_REQ: {name}")
|
||||
try:
|
||||
value = get_metric(name)
|
||||
send_message(conn, MSG_METRIC_RESP, struct.pack("!d", value))
|
||||
except KeyError as e:
|
||||
send_message(conn, MSG_ERROR, str(e).encode("utf-8"))
|
||||
|
||||
else:
|
||||
send_message(conn, MSG_ERROR, f"Unknown type 0x{msg_type:02X}".encode("utf-8"))
|
||||
|
||||
except ConnectionError:
|
||||
pass
|
||||
finally:
|
||||
conn.close()
|
||||
print(f"[-] Disconnected: {addr[0]}:{addr[1]}")
|
||||
|
||||
|
||||
def main():
|
||||
host = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1"
|
||||
port = int(sys.argv[2]) if len(sys.argv) > 2 else 9999
|
||||
|
||||
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
srv.bind((host, port))
|
||||
srv.listen(5)
|
||||
|
||||
print(f"Metric server listening on {host}:{port}")
|
||||
print("Available metrics: cpu, memory, disk, loadavg, uptime\n")
|
||||
|
||||
try:
|
||||
while True:
|
||||
conn, addr = srv.accept()
|
||||
threading.Thread(target=handle_client, args=(conn, addr), daemon=True).start()
|
||||
except KeyboardInterrupt:
|
||||
print("\nShutting down.")
|
||||
finally:
|
||||
srv.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue
Block a user