-
Notifications
You must be signed in to change notification settings - Fork 299
fix(logger): to support logger for multiple runs through port assignment #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,31 +16,101 @@ | |||||||||||||||||||||
| import asyncio | ||||||||||||||||||||||
| import threading | ||||||||||||||||||||||
| from contextlib import contextmanager | ||||||||||||||||||||||
| import socket | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| TASK_CONTEXT_VAR: ContextVar[str | None] = ContextVar("CURRENT_TASK_ID", default=None) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Global variable to store the actual ZMQ address being used | ||||||||||||||||||||||
| _ZMQ_ADDRESS: str = "tcp://127.0.0.1:6000" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def find_available_port(start_port: int = 6000, max_attempts: int = 10) -> int: | ||||||||||||||||||||||
| """Find an available port starting from start_port.""" | ||||||||||||||||||||||
| for port in range(start_port, start_port + max_attempts): | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | ||||||||||||||||||||||
| s.bind(("127.0.0.1", port)) | ||||||||||||||||||||||
| return port | ||||||||||||||||||||||
| except OSError: | ||||||||||||||||||||||
| continue | ||||||||||||||||||||||
| raise RuntimeError( | ||||||||||||||||||||||
| f"Could not find an available port in range {start_port}-{start_port + max_attempts - 1}" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_zmq_address() -> str: | ||||||||||||||||||||||
| """Get the current ZMQ address.""" | ||||||||||||||||||||||
| return _ZMQ_ADDRESS | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def set_zmq_address(address: str) -> None: | ||||||||||||||||||||||
| """Set the ZMQ address.""" | ||||||||||||||||||||||
| global _ZMQ_ADDRESS | ||||||||||||||||||||||
| _ZMQ_ADDRESS = address | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def _extract_port_from_address(addr: str) -> int: | ||||||||||||||||||||||
| """Extract port number from ZMQ address.""" | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| return int(addr.split(":")[-1]) | ||||||||||||||||||||||
| except (ValueError, IndexError): | ||||||||||||||||||||||
| return 6000 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def _bind_zmq_socket(sock, bind_addr: str) -> str: | ||||||||||||||||||||||
| """Bind ZMQ socket to an available port and return the actual address.""" | ||||||||||||||||||||||
| port = _extract_port_from_address(bind_addr) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| available_port = find_available_port(port) | ||||||||||||||||||||||
| actual_addr = f"tcp://127.0.0.1:{available_port}" | ||||||||||||||||||||||
| sock.bind(actual_addr) | ||||||||||||||||||||||
| return actual_addr | ||||||||||||||||||||||
| except RuntimeError: | ||||||||||||||||||||||
| # Fallback to random port | ||||||||||||||||||||||
| return sock.bind_to_random_port("tcp://127.0.0.1") | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class ZMQLogHandler(logging.Handler): | ||||||||||||||||||||||
| def __init__(self, addr="tcp://127.0.0.1:6000", tool_name="unknown_tool"): | ||||||||||||||||||||||
| def __init__(self, addr=None, tool_name="unknown_tool"): | ||||||||||||||||||||||
| super().__init__() | ||||||||||||||||||||||
| ctx = zmq.Context() | ||||||||||||||||||||||
| self.sock = ctx.socket(zmq.PUSH) | ||||||||||||||||||||||
| self.sock.connect(addr) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Use the global ZMQ address if no specific address is provided | ||||||||||||||||||||||
| if addr is None: | ||||||||||||||||||||||
| addr = get_zmq_address() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Try to connect to the address | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| self.sock.connect(addr) | ||||||||||||||||||||||
| print(f"ZMQ handler connected to: {addr}") | ||||||||||||||||||||||
| except zmq.error.ZMQError as e: | ||||||||||||||||||||||
| # If connection fails, disable the handler | ||||||||||||||||||||||
| print(f"Warning: Could not connect to ZMQ listener at {addr}: {e}") | ||||||||||||||||||||||
| print("Disabling ZMQ logging for this handler") | ||||||||||||||||||||||
|
||||||||||||||||||||||
| print(f"ZMQ handler connected to: {addr}") | |
| except zmq.error.ZMQError as e: | |
| # If connection fails, disable the handler | |
| print(f"Warning: Could not connect to ZMQ listener at {addr}: {e}") | |
| print("Disabling ZMQ logging for this handler") | |
| logging.info(f"ZMQ handler connected to: {addr}") | |
| except zmq.error.ZMQError as e: | |
| # If connection fails, disable the handler | |
| logging.warning(f"Could not connect to ZMQ listener at {addr}: {e}") | |
| logging.warning("Disabling ZMQ logging for this handler") |
Outdated
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The emit method should return early when self.sock is None instead of nesting all the logging logic inside an if statement. This would improve readability and reduce indentation depth.
| if self.sock is not None: | |
| msg = f"{record.getMessage()}" | |
| self.sock.send_string(f"{self.task_id}||{self.tool_name}||{msg}") | |
| if self.sock is None: | |
| return | |
| msg = f"{record.getMessage()}" | |
| self.sock.send_string(f"{self.task_id}||{self.tool_name}||{msg}") |
Outdated
Copilot
AI
Oct 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Direct print() statements should be replaced with proper logging calls. Use logger.info() for connection messages and logger.warning() for connection failures to maintain consistent logging practices.
| print(f"ZMQ listener bound to: {actual_addr}") | |
| root_logger.info(f"ZMQ listener bound to: {actual_addr}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
bind_to_random_portmethod returns a port number, not an address string. This should beport = sock.bind_to_random_port('tcp://127.0.0.1')followed byreturn f'tcp://127.0.0.1:{port}'to maintain consistent return type.