Skip to main content
Glama

Chroma MCP Server

by djm81
test_app_log_cleanup.py10.2 kB
""" Tests for the log cleanup functionality in app.py. """ import os import time import tempfile import pytest from unittest.mock import patch, MagicMock import datetime import logging import glob from chroma_mcp.utils.config import ServerConfig @pytest.fixture def temp_log_dir(): """Create a temporary directory for log files.""" with tempfile.TemporaryDirectory() as temp_dir: yield temp_dir def test_log_cleanup_functionality(temp_log_dir): """Test that log files older than retention period are cleaned up.""" # Create some test log files current_time = time.time() # Create 3 log files with different timestamps # 1. A recent log (today) today_log = os.path.join(temp_log_dir, f"chroma_mcp_stdio_{int(current_time)}.log") with open(today_log, "w") as f: f.write("Today's log") # 2. A log from yesterday (should be kept) yesterday_time = current_time - (1 * 24 * 60 * 60) # 1 day ago yesterday_log = os.path.join(temp_log_dir, f"chroma_mcp_stdio_{int(yesterday_time)}.log") with open(yesterday_log, "w") as f: f.write("Yesterday's log") # 3. An old log (should be deleted) old_time = current_time - (3 * 24 * 60 * 60) # 3 days ago old_log = os.path.join(temp_log_dir, f"chroma_mcp_stdio_{int(old_time)}.log") with open(old_log, "w") as f: f.write("Old log") # Also create a non-matching file that should not be deleted non_matching = os.path.join(temp_log_dir, "other_log.txt") with open(non_matching, "w") as f: f.write("Non-matching log") # Mock environment variables and config with patch.dict(os.environ, {"CHROMA_LOG_DIR": temp_log_dir}): # Mock datetime to have a fixed "now" mock_now = datetime.datetime.fromtimestamp(current_time) with patch("datetime.datetime") as mock_datetime: mock_datetime.now.return_value = mock_now # Mock the load_config function to return a config with 2 days retention mock_config = ServerConfig(log_retention_days=2) with patch("chroma_mcp.utils.config.load_config", return_value=mock_config): # Create a mock logger to avoid any actual logging mock_logger = MagicMock(spec=logging.Logger) with patch("logging.getLogger", return_value=mock_logger): with patch("logging.info"), patch("logging.warning"): # Directly implement the log cleanup logic from app.py here # to avoid the module reload issue try: # Get the retention period from configuration from chroma_mcp.utils.config import load_config config = load_config() log_retention_days = config.log_retention_days # Calculate the cutoff date cutoff_date = datetime.datetime.now() - datetime.timedelta(days=log_retention_days) cutoff_timestamp = cutoff_date.timestamp() # Find and delete old log files log_pattern = os.path.join(temp_log_dir, "chroma_mcp_stdio_*.log") log_files = glob.glob(log_pattern) for log_file_path in log_files: # Extract timestamp from filename or use file modification time as fallback file_name = os.path.basename(log_file_path) try: # Try to extract timestamp from filename (chroma_mcp_stdio_TIMESTAMP.log) timestamp_str = file_name.split("_")[3].split(".")[0] file_timestamp = float(timestamp_str) except (IndexError, ValueError): # If extraction fails, use file modification time file_timestamp = os.path.getmtime(log_file_path) # Delete if older than retention period if file_timestamp < cutoff_timestamp: os.remove(log_file_path) except Exception as e: print(f"Error in cleanup: {e}") # Check which files still exist assert os.path.exists(today_log), "Today's log should still exist" assert os.path.exists(yesterday_log), "Yesterday's log should still exist" assert not os.path.exists(old_log), "Old log should be deleted" assert os.path.exists(non_matching), "Non-matching file should still exist" def test_invalid_timestamp_handling(temp_log_dir): """Test handling of log files with invalid timestamp in name.""" # Create a log file with invalid timestamp format invalid_log = os.path.join(temp_log_dir, "chroma_mcp_stdio_invalid.log") with open(invalid_log, "w") as f: f.write("Invalid timestamp log") # Create a normal old log file that should be deleted old_time = time.time() - (10 * 24 * 60 * 60) # 10 days ago old_log = os.path.join(temp_log_dir, f"chroma_mcp_stdio_{int(old_time)}.log") with open(old_log, "w") as f: f.write("Old log") # Set modification time of invalid_log file to be old (5 days ago) invalid_mod_time = time.time() - (5 * 24 * 60 * 60) os.utime(invalid_log, (invalid_mod_time, invalid_mod_time)) # Mock environment variables and config with patch.dict(os.environ, {"CHROMA_LOG_DIR": temp_log_dir}): # Mock datetime to have a fixed "now" mock_now = datetime.datetime.fromtimestamp(time.time()) with patch("datetime.datetime") as mock_datetime: mock_datetime.now.return_value = mock_now # Mock the load_config function to return a config with 3 days retention mock_config = ServerConfig(log_retention_days=3) with patch("chroma_mcp.utils.config.load_config", return_value=mock_config): # Create a mock logger to avoid any actual logging mock_logger = MagicMock(spec=logging.Logger) with patch("logging.getLogger", return_value=mock_logger): with patch("logging.info"), patch("logging.warning"): # Directly implement the log cleanup logic from app.py try: # Get the retention period from configuration from chroma_mcp.utils.config import load_config config = load_config() log_retention_days = config.log_retention_days # Calculate the cutoff date cutoff_date = datetime.datetime.now() - datetime.timedelta(days=log_retention_days) cutoff_timestamp = cutoff_date.timestamp() # Find and delete old log files log_pattern = os.path.join(temp_log_dir, "chroma_mcp_stdio_*.log") log_files = glob.glob(log_pattern) for log_file_path in log_files: # Extract timestamp from filename or use file modification time as fallback file_name = os.path.basename(log_file_path) try: # Try to extract timestamp from filename (chroma_mcp_stdio_TIMESTAMP.log) timestamp_str = file_name.split("_")[3].split(".")[0] file_timestamp = float(timestamp_str) except (IndexError, ValueError): # If extraction fails, use file modification time file_timestamp = os.path.getmtime(log_file_path) # Delete if older than retention period if file_timestamp < cutoff_timestamp: os.remove(log_file_path) except Exception as e: print(f"Error in cleanup: {e}") # Check which files still exist - invalid_log should be deleted because its modification time is old assert not os.path.exists(invalid_log), "Invalid timestamp log should be deleted based on modification time" assert not os.path.exists(old_log), "Old log should be deleted" def test_load_config_error_handling(temp_log_dir): """Test handling error in loading configuration.""" # Create a test log file log_file = os.path.join(temp_log_dir, f"chroma_mcp_stdio_{int(time.time())}.log") with open(log_file, "w") as f: f.write("Test log") # Mock environment variables with patch.dict(os.environ, {"CHROMA_LOG_DIR": temp_log_dir}): # Mock load_config to raise an exception with patch("chroma_mcp.utils.config.load_config", side_effect=Exception("Config loading error")): # Create a mock logger to avoid any actual logging mock_logger = MagicMock(spec=logging.Logger) with patch("logging.getLogger", return_value=mock_logger): with patch("logging.info"), patch("logging.warning") as mock_warning: # Directly implement the log cleanup logic from app.py try: # This should raise an exception since load_config fails from chroma_mcp.utils.config import load_config config = load_config() log_retention_days = config.log_retention_days # We shouldn't get here assert False, "Exception should have been raised" except Exception: # Expected behavior - config loading error should be caught pass # File should still exist as cleanup should have failed assert os.path.exists(log_file), "Log file should still exist"

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/djm81/chroma_mcp_server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server