diff --git a/src/mcpcat/__init__.py b/src/mcpcat/__init__.py index b2b8eda..39a0d60 100644 --- a/src/mcpcat/__init__.py +++ b/src/mcpcat/__init__.py @@ -11,7 +11,7 @@ from .modules.compatibility import is_compatible_server, is_fastmcp_server from .modules.internal import set_server_tracking_data -from .modules.logging import write_to_log +from .modules.logging import write_to_log, set_debug_mode from .types import ( MCPCatData, MCPCatOptions, @@ -43,6 +43,9 @@ def track( if options is None: options = MCPCatOptions() + # Update global debug_mode value + set_debug_mode(options.debug_mode) + # Validate configuration if not project_id and not options.exporters: raise ValueError( diff --git a/src/mcpcat/modules/logging.py b/src/mcpcat/modules/logging.py index dee3b9a..3bb1559 100644 --- a/src/mcpcat/modules/logging.py +++ b/src/mcpcat/modules/logging.py @@ -3,6 +3,22 @@ import os from datetime import datetime, timezone +from mcpcat.types import MCPCatOptions + + +# Initialize debug_mode from environment variable at module load time +_env_debug = os.getenv("MCPCAT_DEBUG_MODE") +if _env_debug is not None: + debug_mode = _env_debug.lower() in ("true", "1", "yes", "on") +else: + debug_mode = False + + +def set_debug_mode(value: bool) -> None: + """Set the global debug_mode value.""" + global debug_mode + debug_mode = value + def write_to_log(message: str) -> None: timestamp = datetime.now(timezone.utc).isoformat() @@ -12,9 +28,10 @@ def write_to_log(message: str) -> None: log_path = os.path.expanduser("~/mcpcat.log") try: - # Write to log file (no need to ensure directory exists for home directory) - with open(log_path, "a") as f: - f.write(log_entry) + if debug_mode: + # Write to log file (no need to ensure directory exists for home directory) + with open(log_path, "a") as f: + f.write(log_entry) except Exception: # Silently fail - we don't want logging errors to break the server pass diff --git a/src/mcpcat/types.py b/src/mcpcat/types.py index b91b26d..92307f8 100644 --- a/src/mcpcat/types.py +++ b/src/mcpcat/types.py @@ -122,6 +122,8 @@ class MCPCatOptions: identify: IdentifyFunction | None = None redact_sensitive_information: RedactionFunction | None = None exporters: dict[str, ExporterConfig] | None = None + debug_mode: bool = False + @dataclass diff --git a/tests/test_logging.py b/tests/test_logging.py index 0b068ca..2550942 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -8,7 +8,7 @@ import pytest -from mcpcat.modules.logging import write_to_log +from mcpcat.modules.logging import write_to_log, set_debug_mode class TestLogging: @@ -31,6 +31,38 @@ def cleanup_log_file(self): def test_write_to_log_creates_file(self, tmp_path): """Test that write_to_log creates the log file if it doesn't exist.""" + # Enable debug mode + set_debug_mode(True) + + # Use a unique file name for this test + unique_id = str(uuid.uuid4()) + log_file = tmp_path / f"test_mcpcat_{unique_id}.log" + + # Mock os.path.expanduser to use our temp file + with patch( + "mcpcat.modules.logging.os.path.expanduser", return_value=str(log_file) + ): + # Write a test message + test_message = f"Test log message {unique_id}" + write_to_log(test_message) + + # Check that the file was created + assert log_file.exists(), "Log file was not created" + + # Read the file content + content = log_file.read_text() + + # Verify the message is in the file + assert test_message in content, "Log message not found in file" + + # Verify timestamp format (ISO format) + assert "T" in content, "Timestamp not in ISO format" + + def test_write_to_log_checks_debug_mode(self, tmp_path): + """Test that write_to_log writes to file when debug mode is enabled.""" + # Enable debug mode + set_debug_mode(True) + # Use a unique file name for this test unique_id = str(uuid.uuid4()) log_file = tmp_path / f"test_mcpcat_{unique_id}.log" @@ -55,8 +87,29 @@ def test_write_to_log_creates_file(self, tmp_path): # Verify timestamp format (ISO format) assert "T" in content, "Timestamp not in ISO format" + # Check that log file is not created when debug mode is disabled + set_debug_mode(False) + + # Use a unique file name for this test + unique_id = str(uuid.uuid4()) + log_file = tmp_path / f"test_mcpcat_{unique_id}.log" + + # Mock os.path.expanduser to use our temp file + with patch( + "mcpcat.modules.logging.os.path.expanduser", return_value=str(log_file) + ): + # Write a test message + test_message = f"Test log message {unique_id}" + write_to_log(test_message) + + # Check that the file was created + assert not log_file.exists(), "Log file was wrongly created" + def test_write_to_log_appends_messages(self, tmp_path): """Test that write_to_log appends to existing log file.""" + # Enable debug mode + set_debug_mode(True) + # Use a unique file name for this test unique_id = str(uuid.uuid4()) log_file = tmp_path / f"test_mcpcat_{unique_id}.log" @@ -105,6 +158,9 @@ def test_write_to_log_appends_messages(self, tmp_path): def test_write_to_log_handles_directory_creation(self, tmp_path): """Test that write_to_log creates parent directories if needed.""" + # Enable debug mode + set_debug_mode(True) + # Use a unique file name for this test unique_id = str(uuid.uuid4()) log_file = tmp_path / f"test_mcpcat_{unique_id}.log" @@ -123,6 +179,9 @@ def test_write_to_log_handles_directory_creation(self, tmp_path): def test_write_to_log_silently_handles_errors(self, tmp_path, monkeypatch): """Test that write_to_log doesn't raise exceptions on errors.""" + # Enable debug mode + set_debug_mode(True) + # Use a unique file name for this test unique_id = str(uuid.uuid4()) log_file = tmp_path / f"test_mcpcat_{unique_id}.log" @@ -146,6 +205,9 @@ def test_write_to_log_silently_handles_errors(self, tmp_path, monkeypatch): def test_log_format(self, tmp_path): """Test the format of log entries.""" + # Enable debug mode + set_debug_mode(True) + # Use a unique file name for this test unique_id = str(uuid.uuid4()) log_file = tmp_path / f"test_mcpcat_{unique_id}.log"