logging, routing
This commit is contained in:
67
tests/test_tracker_logging.py
Normal file
67
tests/test_tracker_logging.py
Normal file
@@ -0,0 +1,67 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from meshnet_tracker.logging_setup import configure_tracker_file_logging, tracker_logger
|
||||
|
||||
|
||||
def test_tracker_file_logging_writes_separate_level_files(tmp_path):
|
||||
original_stdout = sys.stdout
|
||||
original_stderr = sys.stderr
|
||||
try:
|
||||
log_dir = configure_tracker_file_logging(tmp_path, tee_stdio=False)
|
||||
logger = tracker_logger()
|
||||
|
||||
logger.info("info-event")
|
||||
logger.warning("warning-event")
|
||||
logger.error("error-event")
|
||||
for handler in logger.handlers:
|
||||
handler.flush()
|
||||
|
||||
assert (log_dir / "info.log").read_text().count("info-event") == 1
|
||||
assert "warning-event" not in (log_dir / "info.log").read_text()
|
||||
assert "error-event" not in (log_dir / "info.log").read_text()
|
||||
|
||||
assert "warning-event" in (log_dir / "warning.log").read_text()
|
||||
assert "info-event" not in (log_dir / "warning.log").read_text()
|
||||
assert "error-event" not in (log_dir / "warning.log").read_text()
|
||||
|
||||
assert "error-event" in (log_dir / "error.log").read_text()
|
||||
assert "info-event" not in (log_dir / "error.log").read_text()
|
||||
assert "warning-event" not in (log_dir / "error.log").read_text()
|
||||
finally:
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
|
||||
|
||||
def test_tracker_file_logging_tees_stdio_and_rotates(tmp_path):
|
||||
original_stdout = sys.stdout
|
||||
original_stderr = sys.stderr
|
||||
try:
|
||||
log_dir = configure_tracker_file_logging(
|
||||
tmp_path,
|
||||
max_bytes=120,
|
||||
backup_count=1,
|
||||
)
|
||||
|
||||
print("stdout goes to info", flush=True)
|
||||
print("stderr goes to error", file=sys.stderr, flush=True)
|
||||
for handler in tracker_logger().handlers:
|
||||
handler.flush()
|
||||
|
||||
assert "stdout goes to info" in (log_dir / "info.log").read_text()
|
||||
assert "stderr goes to error" in (log_dir / "error.log").read_text()
|
||||
|
||||
for index in range(12):
|
||||
tracker_logger().info("rotating-info-line-%02d", index)
|
||||
for handler in tracker_logger().handlers:
|
||||
handler.flush()
|
||||
|
||||
assert (log_dir / "info.log.1").exists()
|
||||
finally:
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
logger = tracker_logger()
|
||||
for handler in logger.handlers:
|
||||
handler.close()
|
||||
logger.handlers.clear()
|
||||
logger.setLevel(logging.NOTSET)
|
||||
@@ -502,6 +502,75 @@ def test_tracker_logs_stream_progress_before_request_completes():
|
||||
node_thread.join(timeout=1.0)
|
||||
|
||||
|
||||
def test_tracker_stream_survives_idle_gap_between_sse_chunks():
|
||||
first_chunk_sent = threading.Event()
|
||||
|
||||
class IdleStreamingChatHandler(http.server.BaseHTTPRequestHandler):
|
||||
def log_message(self, format, *args):
|
||||
pass
|
||||
|
||||
def do_POST(self):
|
||||
if self.path != "/v1/chat/completions":
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
return
|
||||
self.rfile.read(int(self.headers.get("Content-Length", 0)))
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "text/event-stream; charset=utf-8")
|
||||
self.end_headers()
|
||||
first = json.dumps({
|
||||
"choices": [{"delta": {"content": "hello"}}],
|
||||
}).encode()
|
||||
second = json.dumps({
|
||||
"choices": [{"delta": {"content": " world"}}],
|
||||
}).encode()
|
||||
self.wfile.write(b"data: " + first + b"\n\n")
|
||||
self.wfile.flush()
|
||||
first_chunk_sent.set()
|
||||
time.sleep(1.0)
|
||||
self.wfile.write(b"data: " + second + b"\n\n")
|
||||
self.wfile.write(b"data: [DONE]\n\n")
|
||||
self.wfile.flush()
|
||||
|
||||
node = http.server.HTTPServer(("127.0.0.1", 0), IdleStreamingChatHandler)
|
||||
node_thread = threading.Thread(target=node.serve_forever, daemon=True)
|
||||
node_thread.start()
|
||||
tracker = TrackerServer(heartbeat_timeout=60.0)
|
||||
tracker_port = tracker.start()
|
||||
response = None
|
||||
try:
|
||||
_post_json(
|
||||
f"http://127.0.0.1:{tracker_port}/v1/nodes/register",
|
||||
{"endpoint": f"http://127.0.0.1:{node.server_address[1]}",
|
||||
"model": "idle-stream-model", "num_layers": 1,
|
||||
"shard_start": 0, "shard_end": 0,
|
||||
"hardware_profile": {}, "score": 1.0},
|
||||
)
|
||||
req = urllib.request.Request(
|
||||
f"http://127.0.0.1:{tracker_port}/v1/chat/completions",
|
||||
data=json.dumps({
|
||||
"model": "idle-stream-model",
|
||||
"stream": True,
|
||||
"messages": [{"role": "user", "content": "hi"}],
|
||||
}).encode(),
|
||||
headers={"Content-Type": "application/json"},
|
||||
method="POST",
|
||||
)
|
||||
response = urllib.request.urlopen(req, timeout=3.0)
|
||||
assert response.readline().startswith(b"data:")
|
||||
assert first_chunk_sent.wait(timeout=1.0)
|
||||
|
||||
remaining = response.read().splitlines()
|
||||
assert b"data: [DONE]" in remaining
|
||||
finally:
|
||||
if response is not None:
|
||||
response.close()
|
||||
tracker.stop()
|
||||
node.shutdown()
|
||||
node.server_close()
|
||||
node_thread.join(timeout=1.0)
|
||||
|
||||
|
||||
def test_tracker_dashboard_can_cancel_inflight_proxy():
|
||||
chunk_sent = threading.Event()
|
||||
release = threading.Event()
|
||||
|
||||
Reference in New Issue
Block a user