From 8b6e7f0fc3b656777a69a2e14d1231e105e74892 Mon Sep 17 00:00:00 2001 From: ff225 Date: Mon, 13 Jul 2026 16:36:41 +0200 Subject: [PATCH] fix(communication): replace print() with structured logging request_handler.py and the http_server.py inference endpoint still used print() for server status/error output instead of the project's structured logger, so those messages bypassed log levels and handlers. Closes #12 --- src/server/communication/http_server.py | 4 ++-- src/server/communication/request_handler.py | 18 +++++++++------- tests/unit/test_no_print_statements.py | 24 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 tests/unit/test_no_print_statements.py diff --git a/src/server/communication/http_server.py b/src/server/communication/http_server.py index 08f9748..25c1831 100644 --- a/src/server/communication/http_server.py +++ b/src/server/communication/http_server.py @@ -356,7 +356,7 @@ async def split_inference(request: Request): if ricevuti_elementi != attesa_elementi: error_msg = f"MISMATCH DIMENSIONI: attesi {attesa_elementi} elementi, ricevuti {ricevuti_elementi}." - print(f"[SERVER ERROR] {error_msg}") + logger.error(error_msg) return JSONResponse(status_code=400, content={"error": error_msg}) # Ora puoi fare il reshape in sicurezza @@ -433,7 +433,7 @@ async def split_inference(request: Request): if float(np.max(grid[:, :, 1])) > soglia_client: oggetti_rilevati.append("BICI") if float(np.max(grid[:, :, 2])) > soglia_client: oggetti_rilevati.append("STOP") - print(f"[SERVER] {device_id} -> Vede: {oggetti_rilevati if oggetti_rilevati else '[]'}", flush=True) + logger.info(f"{device_id} -> Vede: {oggetti_rilevati if oggetti_rilevati else '[]'}") # --- 6. RISPOSTA FINALE --- output = np.nan_to_num(input_data, nan=0.0, posinf=0.0, neginf=0.0) if np.issubdtype(input_data.dtype, np.floating) else input_data diff --git a/src/server/communication/request_handler.py b/src/server/communication/request_handler.py index 21a4008..37e3439 100644 --- a/src/server/communication/request_handler.py +++ b/src/server/communication/request_handler.py @@ -206,12 +206,12 @@ def __init__(self): started_at=server_started_at.isoformat(), ) - # Print header once + # Log header once if not RequestHandler.header_printed: - print( - "\nDevice | Offload | Acq Time (ms) | Device Comp (ms) | Edge Comp (ms) | Net Time (ms) | Total (ms)" + logger.info( + "\nDevice | Offload | Acq Time (ms) | Device Comp (ms) | Edge Comp (ms) | Net Time (ms) | Total (ms)\n" + + "-" * 100 ) - print("-" * 100) RequestHandler.header_printed = True # Empty the debug folder every time the server starts @@ -665,7 +665,9 @@ def handle_device_inference_result(self, body, received_timestamp): decision_candidates = offloading_algo.candidate_evaluations # Stampiamo la tabella SOLO se il calcolo รจ andato a buon fine! - print(f"{device_id:13s} | {message_data.offloading_layer_index:7d} | {acq_time:13.2f} | {device_comp_time:16.2f} | {edge_comp_time:14.2f} | {network_time:13.2f} | {total_time:10.2f}") + logger.info( + f"{device_id:13s} | {message_data.offloading_layer_index:7d} | {acq_time:13.2f} | {device_comp_time:16.2f} | {edge_comp_time:14.2f} | {network_time:13.2f} | {total_time:10.2f}" + ) except IndexError: # Se mancano i file restituiamo il layer massimo usando la variabile corretta. @@ -799,7 +801,7 @@ def handle_device_inference_result(self, body, received_timestamp): self.profiler.stop_cprofile("server_deep_analysis") # Lo riavviamo per catturare i prossimi 50 self.profiler.start_cprofile() - print(f"๐Ÿ“Š [PROFILER SERVER] Dati macro e micro (cProfile) esportati.") + logger.info("๐Ÿ“Š [PROFILER SERVER] Dati macro e micro (cProfile) esportati.") return best_offloading_layer, device_id, prediction @@ -897,8 +899,8 @@ def build_model_registry(cls, models_config: dict): "last_offloading_layer": model_config["last_offloading_layer"], "num_layers": model_config["last_offloading_layer"] + 1, } - print( + logger.info( f"Registered model '{model_name}' (dir: {model_dir}) with hash {model_hash}" ) except Exception as e: - print(f"Warning: could not register model {model_name}: {e}") + logger.warning(f"Could not register model {model_name}: {e}") diff --git a/tests/unit/test_no_print_statements.py b/tests/unit/test_no_print_statements.py new file mode 100644 index 0000000..8f12c75 --- /dev/null +++ b/tests/unit/test_no_print_statements.py @@ -0,0 +1,24 @@ +import re +from pathlib import Path + +SRC_ROOT = Path(__file__).resolve().parents[2] / "src" + +# request_handler.py and http_server.py (the endpoint handlers) must use the +# structured logger instead of print(), which bypasses log levels/handlers. +FILES_REQUIRING_STRUCTURED_LOGGING = [ + SRC_ROOT / "server" / "communication" / "request_handler.py", + SRC_ROOT / "server" / "communication" / "http_server.py", +] + +PRINT_CALL_RE = re.compile(r"(?