Skip to main content
Glama
test_logging_config.py14.5 kB
"""Test coverage for logging configuration module.""" from __future__ import annotations import json import logging import uuid from unittest.mock import MagicMock, patch from databeak.utils.logging_config import ( CorrelationFilter, StructuredFormatter, clear_correlation_id, correlation_id, get_correlation_id, set_correlation_id, setup_logging, setup_structured_logging, ) class TestCorrelationFilter: """Test correlation filter functionality.""" def test_filter_adds_correlation_id_when_set(self) -> None: """Test filter adds correlation ID when one is set.""" # Setup test_id = "test-correlation-123" set_correlation_id(test_id) filter_instance = CorrelationFilter() record = logging.LogRecord( name="test", level=logging.INFO, pathname="", lineno=0, msg="test message", args=(), exc_info=None, ) # Execute result = filter_instance.filter(record) # Verify assert result is True assert record.correlation_id == test_id # type: ignore[attr-defined] # Cleanup clear_correlation_id() def test_filter_adds_default_correlation_id_when_none_set(self) -> None: """Test filter adds default when no correlation ID is set.""" # Setup clear_correlation_id() filter_instance = CorrelationFilter() record = logging.LogRecord( name="test", level=logging.INFO, pathname="", lineno=0, msg="test message", args=(), exc_info=None, ) # Execute result = filter_instance.filter(record) # Verify assert result is True assert record.correlation_id == "no-correlation" # type: ignore[attr-defined] def test_filter_adds_default_when_empty_correlation_id(self) -> None: """Test filter adds default when correlation ID is empty string.""" # Setup - set empty string (falsy value) correlation_id.set("") filter_instance = CorrelationFilter() record = logging.LogRecord( name="test", level=logging.INFO, pathname="", lineno=0, msg="test message", args=(), exc_info=None, ) # Execute result = filter_instance.filter(record) # Verify assert result is True assert record.correlation_id == "no-correlation" # type: ignore[attr-defined] class TestStructuredFormatter: """Test structured JSON formatter.""" def test_format_basic_log_record(self) -> None: """Test basic log record formatting.""" formatter = StructuredFormatter() record = logging.LogRecord( name="test.logger", level=logging.INFO, pathname="/test/path.py", lineno=42, msg="Test message", args=(), exc_info=None, func="test_function", ) record.correlation_id = "test-123" # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert log_data["level"] == "INFO" assert log_data["logger"] == "test.logger" assert log_data["message"] == "Test message" assert log_data["correlation_id"] == "test-123" assert log_data["module"] == "path" assert log_data["function"] == "test_function" assert log_data["line"] == 42 assert "timestamp" in log_data def test_format_with_exception_info(self) -> None: """Test formatting with exception information.""" formatter = StructuredFormatter() try: msg = "Test exception" raise ValueError(msg) # noqa: TRY301 except ValueError: import sys exc_info = sys.exc_info() record = logging.LogRecord( name="test.logger", level=logging.ERROR, pathname="/test/path.py", lineno=42, msg="Error occurred", args=(), exc_info=exc_info, func="test_function", ) record.correlation_id = "test-123" # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert "exception" in log_data assert "ValueError: Test exception" in log_data["exception"] def test_format_with_session_id(self) -> None: """Test formatting with session ID.""" formatter = StructuredFormatter() record = logging.LogRecord( name="test.logger", level=logging.INFO, pathname="/test/path.py", lineno=42, msg="Session event", args=(), exc_info=None, func="test_function", ) record.correlation_id = "test-123" record.session_id = "session-456" # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert log_data["session_id"] == "session-456" def test_format_with_operation_type(self) -> None: """Test formatting with operation type.""" formatter = StructuredFormatter() record = logging.LogRecord( name="test.logger", level=logging.INFO, pathname="/test/path.py", lineno=42, msg="Operation event", args=(), exc_info=None, func="test_function", ) record.correlation_id = "test-123" record.operation_type = "data_load" # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert log_data["operation_type"] == "data_load" def test_format_with_user_context(self) -> None: """Test formatting with user context.""" formatter = StructuredFormatter() record = logging.LogRecord( name="test.logger", level=logging.INFO, pathname="/test/path.py", lineno=42, msg="User event", args=(), exc_info=None, func="test_function", ) record.correlation_id = "test-123" record.user_context = {"user_id": "user-789"} # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert log_data["user_context"] == {"user_id": "user-789"} def test_format_without_correlation_id_attribute(self) -> None: """Test formatting when correlation_id attribute is missing.""" formatter = StructuredFormatter() record = logging.LogRecord( name="test.logger", level=logging.INFO, pathname="/test/path.py", lineno=42, msg="Test message", args=(), exc_info=None, func="test_function", ) # Don't set correlation_id attribute # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert log_data["correlation_id"] == "no-correlation" def test_format_without_extra_attributes(self) -> None: """Test formatting when no extra attributes are present.""" formatter = StructuredFormatter() record = logging.LogRecord( name="test.logger", level=logging.INFO, pathname="/test/path.py", lineno=42, msg="Test message", args=(), exc_info=None, func="test_function", ) record.correlation_id = "test-123" # Don't set session_id, operation_type, or user_context # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert "session_id" not in log_data assert "operation_type" not in log_data assert "user_context" not in log_data assert log_data["correlation_id"] == "test-123" def test_format_without_exception_info(self) -> None: """Test formatting when no exception info is present.""" formatter = StructuredFormatter() record = logging.LogRecord( name="test.logger", level=logging.INFO, pathname="/test/path.py", lineno=42, msg="Test message", args=(), exc_info=None, func="test_function", ) record.correlation_id = "test-123" # Execute result = formatter.format(record) # Verify log_data = json.loads(result) assert "exception" not in log_data assert log_data["correlation_id"] == "test-123" class TestSetupStructuredLogging: """Test structured logging setup.""" def test_setup_structured_logging_default_level(self) -> None: """Test setup with default INFO level.""" with patch("logging.getLogger") as mock_get_logger: mock_logger = MagicMock() mock_logger.handlers = [] # No existing handlers mock_get_logger.return_value = mock_logger # Execute setup_structured_logging() # Verify mock_logger.setLevel.assert_called_once_with(logging.INFO) assert mock_logger.addHandler.called def test_setup_structured_logging_custom_level(self) -> None: """Test setup with custom log level.""" with patch("logging.getLogger") as mock_get_logger: mock_logger = MagicMock() mock_get_logger.return_value = mock_logger # Execute setup_structured_logging("DEBUG") # Verify mock_logger.setLevel.assert_called_once_with(logging.DEBUG) def test_setup_structured_logging_clears_existing_handlers(self) -> None: """Test that existing handlers are cleared.""" with patch("logging.getLogger") as mock_get_logger: mock_logger = MagicMock() existing_handler = MagicMock() mock_logger.handlers = [existing_handler] mock_get_logger.return_value = mock_logger # Execute setup_structured_logging() # Verify mock_logger.removeHandler.assert_called_once_with(existing_handler) def test_setup_structured_logging_adds_console_handler(self) -> None: """Test that console handler is added with proper configuration.""" with ( patch("logging.getLogger") as mock_get_logger, patch("logging.StreamHandler") as mock_stream_handler, ): mock_logger = MagicMock() mock_logger.handlers = [] mock_get_logger.return_value = mock_logger mock_handler = MagicMock() mock_stream_handler.return_value = mock_handler # Execute setup_structured_logging() # Verify mock_stream_handler.assert_called_once() mock_handler.setFormatter.assert_called_once() mock_handler.addFilter.assert_called_once() mock_logger.addHandler.assert_called_once_with(mock_handler) class TestCorrelationIdManagement: """Test correlation ID context management.""" def test_get_correlation_id_when_set(self) -> None: """Test getting correlation ID when one is set.""" test_id = "test-correlation-456" set_correlation_id(test_id) result = get_correlation_id() assert result == test_id clear_correlation_id() def test_get_correlation_id_when_not_set(self) -> None: """Test getting correlation ID when none is set.""" clear_correlation_id() result = get_correlation_id() assert result == "no-correlation" def test_get_correlation_id_when_empty_string(self) -> None: """Test getting correlation ID when set to empty string.""" correlation_id.set("") result = get_correlation_id() assert result == "no-correlation" def test_set_correlation_id_with_provided_id(self) -> None: """Test setting correlation ID with provided value.""" test_id = "custom-correlation-789" result = set_correlation_id(test_id) assert result == test_id assert get_correlation_id() == test_id clear_correlation_id() def test_set_correlation_id_with_none_generates_uuid(self) -> None: """Test setting correlation ID with None generates UUID.""" result = set_correlation_id(None) # Verify it's a valid UUID format uuid.UUID(result) # Will raise if not valid assert get_correlation_id() == result clear_correlation_id() def test_set_correlation_id_no_argument_generates_uuid(self) -> None: """Test setting correlation ID with no argument generates UUID.""" result = set_correlation_id() # Verify it's a valid UUID format uuid.UUID(result) # Will raise if not valid assert get_correlation_id() == result clear_correlation_id() def test_clear_correlation_id(self) -> None: """Test clearing correlation ID.""" set_correlation_id("test-id") clear_correlation_id() assert get_correlation_id() == "no-correlation" # NOTE: TestGetLogger, TestOperationLogging, and TestSessionLogging removed # since we now use standard Python logging.Logger which is well-tested by Python itself. class TestBackwardCompatibility: """Test backward compatibility functions.""" def test_setup_logging_calls_setup_structured_logging(self) -> None: """Test setup_logging calls setup_structured_logging for backward compatibility.""" with patch("databeak.utils.logging_config.setup_structured_logging") as mock_setup: setup_logging("WARNING") mock_setup.assert_called_once_with("WARNING") def test_setup_logging_default_level(self) -> None: """Test setup_logging with default level.""" with patch("databeak.utils.logging_config.setup_structured_logging") as mock_setup: setup_logging() mock_setup.assert_called_once_with("INFO")

Latest Blog Posts

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/jonpspri/databeak'

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