claude-mpm 3.7.4__py3-none-any.whl → 3.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +0 -106
- claude_mpm/agents/INSTRUCTIONS.md +0 -78
- claude_mpm/agents/MEMORY.md +88 -0
- claude_mpm/agents/WORKFLOW.md +86 -0
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/templates/code_analyzer.json +26 -11
- claude_mpm/agents/templates/data_engineer.json +4 -7
- claude_mpm/agents/templates/documentation.json +2 -2
- claude_mpm/agents/templates/engineer.json +2 -2
- claude_mpm/agents/templates/ops.json +3 -8
- claude_mpm/agents/templates/qa.json +2 -3
- claude_mpm/agents/templates/research.json +2 -3
- claude_mpm/agents/templates/security.json +3 -6
- claude_mpm/agents/templates/ticketing.json +4 -9
- claude_mpm/agents/templates/version_control.json +3 -3
- claude_mpm/agents/templates/web_qa.json +4 -4
- claude_mpm/agents/templates/web_ui.json +4 -4
- claude_mpm/cli/__init__.py +2 -2
- claude_mpm/cli/commands/__init__.py +2 -1
- claude_mpm/cli/commands/agents.py +118 -1
- claude_mpm/cli/commands/tickets.py +596 -19
- claude_mpm/cli/parser.py +228 -5
- claude_mpm/config/__init__.py +30 -39
- claude_mpm/config/socketio_config.py +8 -5
- claude_mpm/constants.py +13 -0
- claude_mpm/core/__init__.py +8 -18
- claude_mpm/core/cache.py +596 -0
- claude_mpm/core/claude_runner.py +166 -622
- claude_mpm/core/config.py +5 -1
- claude_mpm/core/constants.py +339 -0
- claude_mpm/core/container.py +461 -22
- claude_mpm/core/exceptions.py +392 -0
- claude_mpm/core/framework_loader.py +208 -93
- claude_mpm/core/interactive_session.py +432 -0
- claude_mpm/core/interfaces.py +424 -0
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/logging_config.py +444 -0
- claude_mpm/core/oneshot_session.py +465 -0
- claude_mpm/core/optimized_agent_loader.py +485 -0
- claude_mpm/core/optimized_startup.py +490 -0
- claude_mpm/core/service_registry.py +52 -26
- claude_mpm/core/socketio_pool.py +162 -5
- claude_mpm/core/types.py +292 -0
- claude_mpm/core/typing_utils.py +477 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +46 -2
- claude_mpm/dashboard/templates/index.html +5 -5
- claude_mpm/hooks/claude_hooks/hook_handler.py +213 -99
- claude_mpm/init.py +2 -1
- claude_mpm/services/__init__.py +78 -14
- claude_mpm/services/agent/__init__.py +24 -0
- claude_mpm/services/agent/deployment.py +2548 -0
- claude_mpm/services/agent/management.py +598 -0
- claude_mpm/services/agent/registry.py +813 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +592 -269
- claude_mpm/services/agents/deployment/async_agent_deployment.py +5 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +21 -11
- claude_mpm/services/agents/memory/agent_memory_manager.py +156 -1
- claude_mpm/services/async_session_logger.py +8 -3
- claude_mpm/services/communication/__init__.py +21 -0
- claude_mpm/services/communication/socketio.py +1933 -0
- claude_mpm/services/communication/websocket.py +479 -0
- claude_mpm/services/core/__init__.py +123 -0
- claude_mpm/services/core/base.py +247 -0
- claude_mpm/services/core/interfaces.py +951 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +23 -23
- claude_mpm/services/framework_claude_md_generator.py +3 -2
- claude_mpm/services/health_monitor.py +4 -3
- claude_mpm/services/hook_service.py +64 -4
- claude_mpm/services/infrastructure/__init__.py +21 -0
- claude_mpm/services/infrastructure/logging.py +202 -0
- claude_mpm/services/infrastructure/monitoring.py +893 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/project/__init__.py +21 -0
- claude_mpm/services/project/analyzer.py +864 -0
- claude_mpm/services/project/registry.py +608 -0
- claude_mpm/services/project_analyzer.py +95 -2
- claude_mpm/services/recovery_manager.py +15 -9
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/base.py +121 -0
- claude_mpm/services/socketio/handlers/connection.py +198 -0
- claude_mpm/services/socketio/handlers/file.py +213 -0
- claude_mpm/services/socketio/handlers/git.py +723 -0
- claude_mpm/services/socketio/handlers/memory.py +27 -0
- claude_mpm/services/socketio/handlers/project.py +25 -0
- claude_mpm/services/socketio/handlers/registry.py +145 -0
- claude_mpm/services/socketio_client_manager.py +12 -7
- claude_mpm/services/socketio_server.py +156 -30
- claude_mpm/services/ticket_manager.py +377 -51
- claude_mpm/utils/agent_dependency_loader.py +66 -15
- claude_mpm/utils/error_handler.py +1 -1
- claude_mpm/utils/robust_installer.py +587 -0
- claude_mpm/validation/agent_validator.py +27 -14
- claude_mpm/validation/frontmatter_validator.py +231 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/METADATA +74 -41
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/RECORD +101 -76
- claude_mpm/.claude-mpm/logs/hooks_20250728.log +0 -10
- claude_mpm/agents/agent-template.yaml +0 -83
- claude_mpm/cli/README.md +0 -108
- claude_mpm/cli_module/refactoring_guide.md +0 -253
- claude_mpm/config/async_logging_config.yaml +0 -145
- claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
- claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/README.md +0 -121
- claude_mpm/dashboard/static/js/dashboard.js.backup +0 -1973
- claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
- claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
- claude_mpm/hooks/README.md +0 -96
- claude_mpm/schemas/agent_schema.json +0 -435
- claude_mpm/services/framework_claude_md_generator/README.md +0 -92
- claude_mpm/services/version_control/VERSION +0 -1
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/WHEEL +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/top_level.txt +0 -0
| @@ -0,0 +1,444 @@ | |
| 1 | 
            +
            """
         | 
| 2 | 
            +
            Centralized logging configuration for Claude MPM.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            This module provides a standardized logging infrastructure with:
         | 
| 5 | 
            +
            - Consistent logger factory method
         | 
| 6 | 
            +
            - Structured logging with context
         | 
| 7 | 
            +
            - Performance logging decorators
         | 
| 8 | 
            +
            - Context managers for operation tracking
         | 
| 9 | 
            +
            - Standardized log levels and formatting
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            WHY: This centralized approach ensures consistent logging across the entire
         | 
| 12 | 
            +
            codebase, making debugging and monitoring significantly easier. All components
         | 
| 13 | 
            +
            use the same format, level hierarchy, and contextual information structure.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            DESIGN DECISION: Built on top of existing logger.py but provides simplified
         | 
| 16 | 
            +
            interface and enforces consistent patterns. This allows gradual migration
         | 
| 17 | 
            +
            while maintaining backwards compatibility.
         | 
| 18 | 
            +
            """
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            import functools
         | 
| 21 | 
            +
            import json
         | 
| 22 | 
            +
            import logging
         | 
| 23 | 
            +
            import time
         | 
| 24 | 
            +
            from contextlib import contextmanager
         | 
| 25 | 
            +
            from pathlib import Path
         | 
| 26 | 
            +
            from typing import Any, Dict, Optional, Union
         | 
| 27 | 
            +
            from datetime import datetime
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            from claude_mpm.core.logger import (
         | 
| 30 | 
            +
                setup_logging as _setup_logging,
         | 
| 31 | 
            +
                get_logger as _get_logger,
         | 
| 32 | 
            +
                log_performance,
         | 
| 33 | 
            +
                log_async_performance,
         | 
| 34 | 
            +
                JsonFormatter,
         | 
| 35 | 
            +
                StreamingHandler,
         | 
| 36 | 
            +
                finalize_streaming_logs
         | 
| 37 | 
            +
            )
         | 
| 38 | 
            +
             | 
| 39 | 
            +
             | 
| 40 | 
            +
            # Standard log format for consistency
         | 
| 41 | 
            +
            STANDARD_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
         | 
| 42 | 
            +
            DETAILED_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(funcName)s() - %(message)s'
         | 
| 43 | 
            +
            SIMPLE_FORMAT = '%(levelname)s: %(message)s'
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            # Log level mapping for consistent usage
         | 
| 46 | 
            +
            LOG_LEVELS = {
         | 
| 47 | 
            +
                'DEBUG': logging.DEBUG,      # Detailed diagnostic information
         | 
| 48 | 
            +
                'INFO': logging.INFO,         # Normal operations, significant events
         | 
| 49 | 
            +
                'WARNING': logging.WARNING,   # Potentially harmful situations
         | 
| 50 | 
            +
                'ERROR': logging.ERROR,       # Error events allowing continued operation
         | 
| 51 | 
            +
                'CRITICAL': logging.CRITICAL  # Events that may cause abort
         | 
| 52 | 
            +
            }
         | 
| 53 | 
            +
             | 
| 54 | 
            +
             | 
| 55 | 
            +
            class LogContext:
         | 
| 56 | 
            +
                """
         | 
| 57 | 
            +
                Context manager for adding contextual information to log messages.
         | 
| 58 | 
            +
                
         | 
| 59 | 
            +
                WHY: Provides consistent way to add context like operation IDs, user info,
         | 
| 60 | 
            +
                or request IDs to all logs within a scope without modifying every log call.
         | 
| 61 | 
            +
                """
         | 
| 62 | 
            +
                
         | 
| 63 | 
            +
                _context: Dict[str, Any] = {}
         | 
| 64 | 
            +
                
         | 
| 65 | 
            +
                @classmethod
         | 
| 66 | 
            +
                def set(cls, **kwargs):
         | 
| 67 | 
            +
                    """Set context values."""
         | 
| 68 | 
            +
                    cls._context.update(kwargs)
         | 
| 69 | 
            +
                
         | 
| 70 | 
            +
                @classmethod
         | 
| 71 | 
            +
                def get(cls) -> Dict[str, Any]:
         | 
| 72 | 
            +
                    """Get current context."""
         | 
| 73 | 
            +
                    return cls._context.copy()
         | 
| 74 | 
            +
                
         | 
| 75 | 
            +
                @classmethod
         | 
| 76 | 
            +
                def clear(cls):
         | 
| 77 | 
            +
                    """Clear all context."""
         | 
| 78 | 
            +
                    cls._context.clear()
         | 
| 79 | 
            +
                
         | 
| 80 | 
            +
                @classmethod
         | 
| 81 | 
            +
                @contextmanager
         | 
| 82 | 
            +
                def context(cls, **kwargs):
         | 
| 83 | 
            +
                    """Context manager for temporary context."""
         | 
| 84 | 
            +
                    old_context = cls._context.copy()
         | 
| 85 | 
            +
                    cls._context.update(kwargs)
         | 
| 86 | 
            +
                    try:
         | 
| 87 | 
            +
                        yield
         | 
| 88 | 
            +
                    finally:
         | 
| 89 | 
            +
                        cls._context = old_context
         | 
| 90 | 
            +
             | 
| 91 | 
            +
             | 
| 92 | 
            +
            class ContextualLogger:
         | 
| 93 | 
            +
                """
         | 
| 94 | 
            +
                Logger wrapper that automatically includes context in all messages.
         | 
| 95 | 
            +
                
         | 
| 96 | 
            +
                WHY: Ensures all log messages from a component include relevant context
         | 
| 97 | 
            +
                without requiring manual addition to each log call.
         | 
| 98 | 
            +
                """
         | 
| 99 | 
            +
                
         | 
| 100 | 
            +
                def __init__(self, logger: logging.Logger):
         | 
| 101 | 
            +
                    self._logger = logger
         | 
| 102 | 
            +
                
         | 
| 103 | 
            +
                def _log_with_context(self, level: int, msg: str, *args, **kwargs):
         | 
| 104 | 
            +
                    """Add context to log message."""
         | 
| 105 | 
            +
                    context = LogContext.get()
         | 
| 106 | 
            +
                    if context:
         | 
| 107 | 
            +
                        # Add context as extra fields for structured logging
         | 
| 108 | 
            +
                        kwargs['extra'] = kwargs.get('extra', {})
         | 
| 109 | 
            +
                        kwargs['extra'].update(context)
         | 
| 110 | 
            +
                        
         | 
| 111 | 
            +
                        # For human-readable logs, prepend context
         | 
| 112 | 
            +
                        if not isinstance(self._logger.handlers[0].formatter, JsonFormatter):
         | 
| 113 | 
            +
                            context_str = ' '.join(f'[{k}={v}]' for k, v in context.items())
         | 
| 114 | 
            +
                            if context_str:
         | 
| 115 | 
            +
                                msg = f"{context_str} {msg}"
         | 
| 116 | 
            +
                    
         | 
| 117 | 
            +
                    self._logger.log(level, msg, *args, **kwargs)
         | 
| 118 | 
            +
                
         | 
| 119 | 
            +
                def debug(self, msg: str, *args, **kwargs):
         | 
| 120 | 
            +
                    """Log debug message with context."""
         | 
| 121 | 
            +
                    self._log_with_context(logging.DEBUG, msg, *args, **kwargs)
         | 
| 122 | 
            +
                
         | 
| 123 | 
            +
                def info(self, msg: str, *args, **kwargs):
         | 
| 124 | 
            +
                    """Log info message with context."""
         | 
| 125 | 
            +
                    self._log_with_context(logging.INFO, msg, *args, **kwargs)
         | 
| 126 | 
            +
                
         | 
| 127 | 
            +
                def warning(self, msg: str, *args, **kwargs):
         | 
| 128 | 
            +
                    """Log warning message with context."""
         | 
| 129 | 
            +
                    self._log_with_context(logging.WARNING, msg, *args, **kwargs)
         | 
| 130 | 
            +
                
         | 
| 131 | 
            +
                def error(self, msg: str, *args, **kwargs):
         | 
| 132 | 
            +
                    """Log error message with context."""
         | 
| 133 | 
            +
                    self._log_with_context(logging.ERROR, msg, *args, **kwargs)
         | 
| 134 | 
            +
                
         | 
| 135 | 
            +
                def critical(self, msg: str, *args, **kwargs):
         | 
| 136 | 
            +
                    """Log critical message with context."""
         | 
| 137 | 
            +
                    self._log_with_context(logging.CRITICAL, msg, *args, **kwargs)
         | 
| 138 | 
            +
                
         | 
| 139 | 
            +
                def exception(self, msg: str, *args, **kwargs):
         | 
| 140 | 
            +
                    """Log exception with context."""
         | 
| 141 | 
            +
                    kwargs['exc_info'] = True
         | 
| 142 | 
            +
                    self._log_with_context(logging.ERROR, msg, *args, **kwargs)
         | 
| 143 | 
            +
             | 
| 144 | 
            +
             | 
| 145 | 
            +
            def get_logger(name: str, with_context: bool = True) -> Union[ContextualLogger, logging.Logger]:
         | 
| 146 | 
            +
                """
         | 
| 147 | 
            +
                Get a configured logger instance.
         | 
| 148 | 
            +
                
         | 
| 149 | 
            +
                WHY: Centralized logger creation ensures all loggers follow the same
         | 
| 150 | 
            +
                naming convention and configuration patterns.
         | 
| 151 | 
            +
                
         | 
| 152 | 
            +
                Args:
         | 
| 153 | 
            +
                    name: Logger name (typically __name__ from the calling module)
         | 
| 154 | 
            +
                    with_context: Whether to wrap with ContextualLogger for automatic context
         | 
| 155 | 
            +
                    
         | 
| 156 | 
            +
                Returns:
         | 
| 157 | 
            +
                    Configured logger instance
         | 
| 158 | 
            +
                    
         | 
| 159 | 
            +
                Example:
         | 
| 160 | 
            +
                    logger = get_logger(__name__)
         | 
| 161 | 
            +
                    logger.info("Processing request", extra={"request_id": "123"})
         | 
| 162 | 
            +
                """
         | 
| 163 | 
            +
                # Ensure consistent naming
         | 
| 164 | 
            +
                if not name.startswith('claude_mpm'):
         | 
| 165 | 
            +
                    name = f'claude_mpm.{name}'
         | 
| 166 | 
            +
                
         | 
| 167 | 
            +
                logger = _get_logger(name)
         | 
| 168 | 
            +
                
         | 
| 169 | 
            +
                if with_context:
         | 
| 170 | 
            +
                    return ContextualLogger(logger)
         | 
| 171 | 
            +
                return logger
         | 
| 172 | 
            +
             | 
| 173 | 
            +
             | 
| 174 | 
            +
            def configure_logging(
         | 
| 175 | 
            +
                level: str = "INFO",
         | 
| 176 | 
            +
                log_dir: Optional[Path] = None,
         | 
| 177 | 
            +
                console_output: bool = True,
         | 
| 178 | 
            +
                file_output: bool = True,
         | 
| 179 | 
            +
                json_format: bool = False,
         | 
| 180 | 
            +
                use_streaming: bool = False
         | 
| 181 | 
            +
            ) -> None:
         | 
| 182 | 
            +
                """
         | 
| 183 | 
            +
                Configure global logging settings.
         | 
| 184 | 
            +
                
         | 
| 185 | 
            +
                WHY: Provides single entry point for configuring all logging behavior
         | 
| 186 | 
            +
                across the application, ensuring consistency.
         | 
| 187 | 
            +
                
         | 
| 188 | 
            +
                Args:
         | 
| 189 | 
            +
                    level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
         | 
| 190 | 
            +
                    log_dir: Directory for log files
         | 
| 191 | 
            +
                    console_output: Enable console output
         | 
| 192 | 
            +
                    file_output: Enable file output
         | 
| 193 | 
            +
                    json_format: Use JSON format for structured logging
         | 
| 194 | 
            +
                    use_streaming: Use streaming handler for progress messages
         | 
| 195 | 
            +
                """
         | 
| 196 | 
            +
                # Configure root logger for claude_mpm
         | 
| 197 | 
            +
                _setup_logging(
         | 
| 198 | 
            +
                    name="claude_mpm",
         | 
| 199 | 
            +
                    level=level,
         | 
| 200 | 
            +
                    log_dir=log_dir,
         | 
| 201 | 
            +
                    console_output=console_output,
         | 
| 202 | 
            +
                    file_output=file_output,
         | 
| 203 | 
            +
                    json_format=json_format,
         | 
| 204 | 
            +
                    use_streaming=use_streaming
         | 
| 205 | 
            +
                )
         | 
| 206 | 
            +
             | 
| 207 | 
            +
             | 
| 208 | 
            +
            @contextmanager
         | 
| 209 | 
            +
            def log_operation(logger: Union[ContextualLogger, logging.Logger], 
         | 
| 210 | 
            +
                              operation: str, 
         | 
| 211 | 
            +
                              **context):
         | 
| 212 | 
            +
                """
         | 
| 213 | 
            +
                Context manager for logging operation start/end with timing.
         | 
| 214 | 
            +
                
         | 
| 215 | 
            +
                WHY: Provides consistent way to track operation execution including
         | 
| 216 | 
            +
                timing, success/failure, and any relevant context.
         | 
| 217 | 
            +
                
         | 
| 218 | 
            +
                Args:
         | 
| 219 | 
            +
                    logger: Logger instance
         | 
| 220 | 
            +
                    operation: Operation name/description
         | 
| 221 | 
            +
                    **context: Additional context to include in logs
         | 
| 222 | 
            +
                    
         | 
| 223 | 
            +
                Example:
         | 
| 224 | 
            +
                    with log_operation(logger, "database_query", query_type="select"):
         | 
| 225 | 
            +
                        # Perform database operation
         | 
| 226 | 
            +
                        pass
         | 
| 227 | 
            +
                """
         | 
| 228 | 
            +
                start_time = time.time()
         | 
| 229 | 
            +
                
         | 
| 230 | 
            +
                # Add operation context
         | 
| 231 | 
            +
                with LogContext.context(operation=operation, **context):
         | 
| 232 | 
            +
                    logger.info(f"Starting {operation}")
         | 
| 233 | 
            +
                    
         | 
| 234 | 
            +
                    try:
         | 
| 235 | 
            +
                        yield
         | 
| 236 | 
            +
                        execution_time = time.time() - start_time
         | 
| 237 | 
            +
                        logger.info(f"Completed {operation}", extra={
         | 
| 238 | 
            +
                            "execution_time": execution_time,
         | 
| 239 | 
            +
                            "status": "success"
         | 
| 240 | 
            +
                        })
         | 
| 241 | 
            +
                    except Exception as e:
         | 
| 242 | 
            +
                        execution_time = time.time() - start_time
         | 
| 243 | 
            +
                        logger.error(f"Failed {operation}: {e}", extra={
         | 
| 244 | 
            +
                            "execution_time": execution_time,
         | 
| 245 | 
            +
                            "status": "failure",
         | 
| 246 | 
            +
                            "error": str(e)
         | 
| 247 | 
            +
                        })
         | 
| 248 | 
            +
                        raise
         | 
| 249 | 
            +
             | 
| 250 | 
            +
             | 
| 251 | 
            +
            @contextmanager
         | 
| 252 | 
            +
            def log_performance_context(logger: Union[ContextualLogger, logging.Logger],
         | 
| 253 | 
            +
                                       operation: str,
         | 
| 254 | 
            +
                                       warn_threshold: float = 1.0,
         | 
| 255 | 
            +
                                       error_threshold: float = 5.0):
         | 
| 256 | 
            +
                """
         | 
| 257 | 
            +
                Context manager for performance monitoring with thresholds.
         | 
| 258 | 
            +
                
         | 
| 259 | 
            +
                WHY: Automatically warns or errors when operations exceed performance
         | 
| 260 | 
            +
                thresholds, helping identify performance issues early.
         | 
| 261 | 
            +
                
         | 
| 262 | 
            +
                Args:
         | 
| 263 | 
            +
                    logger: Logger instance
         | 
| 264 | 
            +
                    operation: Operation being monitored
         | 
| 265 | 
            +
                    warn_threshold: Time in seconds to trigger warning
         | 
| 266 | 
            +
                    error_threshold: Time in seconds to trigger error
         | 
| 267 | 
            +
                    
         | 
| 268 | 
            +
                Example:
         | 
| 269 | 
            +
                    with log_performance_context(logger, "api_call", warn_threshold=0.5):
         | 
| 270 | 
            +
                        # Make API call
         | 
| 271 | 
            +
                        pass
         | 
| 272 | 
            +
                """
         | 
| 273 | 
            +
                start_time = time.time()
         | 
| 274 | 
            +
                
         | 
| 275 | 
            +
                try:
         | 
| 276 | 
            +
                    yield
         | 
| 277 | 
            +
                finally:
         | 
| 278 | 
            +
                    execution_time = time.time() - start_time
         | 
| 279 | 
            +
                    
         | 
| 280 | 
            +
                    if execution_time > error_threshold:
         | 
| 281 | 
            +
                        logger.error(f"{operation} took {execution_time:.3f}s (threshold: {error_threshold}s)", extra={
         | 
| 282 | 
            +
                            "execution_time": execution_time,
         | 
| 283 | 
            +
                            "threshold_exceeded": "error"
         | 
| 284 | 
            +
                        })
         | 
| 285 | 
            +
                    elif execution_time > warn_threshold:
         | 
| 286 | 
            +
                        logger.warning(f"{operation} took {execution_time:.3f}s (threshold: {warn_threshold}s)", extra={
         | 
| 287 | 
            +
                            "execution_time": execution_time,
         | 
| 288 | 
            +
                            "threshold_exceeded": "warning"
         | 
| 289 | 
            +
                        })
         | 
| 290 | 
            +
                    else:
         | 
| 291 | 
            +
                        logger.debug(f"{operation} completed in {execution_time:.3f}s", extra={
         | 
| 292 | 
            +
                            "execution_time": execution_time
         | 
| 293 | 
            +
                        })
         | 
| 294 | 
            +
             | 
| 295 | 
            +
             | 
| 296 | 
            +
            def log_function_call(func):
         | 
| 297 | 
            +
                """
         | 
| 298 | 
            +
                Decorator to log function calls with arguments and results.
         | 
| 299 | 
            +
                
         | 
| 300 | 
            +
                WHY: Provides automatic logging of function entry/exit for debugging
         | 
| 301 | 
            +
                without modifying function implementation.
         | 
| 302 | 
            +
                
         | 
| 303 | 
            +
                Example:
         | 
| 304 | 
            +
                    @log_function_call
         | 
| 305 | 
            +
                    def process_data(data: dict) -> dict:
         | 
| 306 | 
            +
                        return {"processed": True}
         | 
| 307 | 
            +
                """
         | 
| 308 | 
            +
                @functools.wraps(func)
         | 
| 309 | 
            +
                def wrapper(*args, **kwargs):
         | 
| 310 | 
            +
                    logger = get_logger(func.__module__)
         | 
| 311 | 
            +
                    func_name = func.__qualname__
         | 
| 312 | 
            +
                    
         | 
| 313 | 
            +
                    # Log function entry
         | 
| 314 | 
            +
                    logger.debug(f"Calling {func_name}", extra={
         | 
| 315 | 
            +
                        "function": func_name,
         | 
| 316 | 
            +
                        "args_count": len(args),
         | 
| 317 | 
            +
                        "kwargs_keys": list(kwargs.keys())
         | 
| 318 | 
            +
                    })
         | 
| 319 | 
            +
                    
         | 
| 320 | 
            +
                    start_time = time.time()
         | 
| 321 | 
            +
                    try:
         | 
| 322 | 
            +
                        result = func(*args, **kwargs)
         | 
| 323 | 
            +
                        execution_time = time.time() - start_time
         | 
| 324 | 
            +
                        
         | 
| 325 | 
            +
                        logger.debug(f"{func_name} completed", extra={
         | 
| 326 | 
            +
                            "function": func_name,
         | 
| 327 | 
            +
                            "execution_time": execution_time,
         | 
| 328 | 
            +
                            "has_result": result is not None
         | 
| 329 | 
            +
                        })
         | 
| 330 | 
            +
                        
         | 
| 331 | 
            +
                        return result
         | 
| 332 | 
            +
                        
         | 
| 333 | 
            +
                    except Exception as e:
         | 
| 334 | 
            +
                        execution_time = time.time() - start_time
         | 
| 335 | 
            +
                        logger.exception(f"{func_name} failed", extra={
         | 
| 336 | 
            +
                            "function": func_name,
         | 
| 337 | 
            +
                            "execution_time": execution_time,
         | 
| 338 | 
            +
                            "error_type": type(e).__name__
         | 
| 339 | 
            +
                        })
         | 
| 340 | 
            +
                        raise
         | 
| 341 | 
            +
                
         | 
| 342 | 
            +
                return wrapper
         | 
| 343 | 
            +
             | 
| 344 | 
            +
             | 
| 345 | 
            +
            async def log_async_function_call(func):
         | 
| 346 | 
            +
                """
         | 
| 347 | 
            +
                Decorator to log async function calls with arguments and results.
         | 
| 348 | 
            +
                
         | 
| 349 | 
            +
                WHY: Provides automatic logging for async functions, essential for
         | 
| 350 | 
            +
                tracking async operation flow and performance.
         | 
| 351 | 
            +
                
         | 
| 352 | 
            +
                Example:
         | 
| 353 | 
            +
                    @log_async_function_call
         | 
| 354 | 
            +
                    async def fetch_data(url: str) -> dict:
         | 
| 355 | 
            +
                        return {"data": "example"}
         | 
| 356 | 
            +
                """
         | 
| 357 | 
            +
                @functools.wraps(func)
         | 
| 358 | 
            +
                async def wrapper(*args, **kwargs):
         | 
| 359 | 
            +
                    logger = get_logger(func.__module__)
         | 
| 360 | 
            +
                    func_name = func.__qualname__
         | 
| 361 | 
            +
                    
         | 
| 362 | 
            +
                    # Log function entry
         | 
| 363 | 
            +
                    logger.debug(f"Calling async {func_name}", extra={
         | 
| 364 | 
            +
                        "function": func_name,
         | 
| 365 | 
            +
                        "args_count": len(args),
         | 
| 366 | 
            +
                        "kwargs_keys": list(kwargs.keys()),
         | 
| 367 | 
            +
                        "is_async": True
         | 
| 368 | 
            +
                    })
         | 
| 369 | 
            +
                    
         | 
| 370 | 
            +
                    start_time = time.time()
         | 
| 371 | 
            +
                    try:
         | 
| 372 | 
            +
                        result = await func(*args, **kwargs)
         | 
| 373 | 
            +
                        execution_time = time.time() - start_time
         | 
| 374 | 
            +
                        
         | 
| 375 | 
            +
                        logger.debug(f"Async {func_name} completed", extra={
         | 
| 376 | 
            +
                            "function": func_name,
         | 
| 377 | 
            +
                            "execution_time": execution_time,
         | 
| 378 | 
            +
                            "has_result": result is not None,
         | 
| 379 | 
            +
                            "is_async": True
         | 
| 380 | 
            +
                        })
         | 
| 381 | 
            +
                        
         | 
| 382 | 
            +
                        return result
         | 
| 383 | 
            +
                        
         | 
| 384 | 
            +
                    except Exception as e:
         | 
| 385 | 
            +
                        execution_time = time.time() - start_time
         | 
| 386 | 
            +
                        logger.exception(f"Async {func_name} failed", extra={
         | 
| 387 | 
            +
                            "function": func_name,
         | 
| 388 | 
            +
                            "execution_time": execution_time,
         | 
| 389 | 
            +
                            "error_type": type(e).__name__,
         | 
| 390 | 
            +
                            "is_async": True
         | 
| 391 | 
            +
                        })
         | 
| 392 | 
            +
                        raise
         | 
| 393 | 
            +
                
         | 
| 394 | 
            +
                return wrapper
         | 
| 395 | 
            +
             | 
| 396 | 
            +
             | 
| 397 | 
            +
            # Logging standards and guidelines as constants for reference
         | 
| 398 | 
            +
            LOGGING_STANDARDS = {
         | 
| 399 | 
            +
                "INFO": "Normal operations, significant events (e.g., service started, request completed)",
         | 
| 400 | 
            +
                "DEBUG": "Detailed diagnostic information (e.g., variable values, execution flow)",
         | 
| 401 | 
            +
                "WARNING": "Potentially harmful situations (e.g., deprecated API usage, retry attempts)",
         | 
| 402 | 
            +
                "ERROR": "Error events that allow continued operation (e.g., single request failure)",
         | 
| 403 | 
            +
                "CRITICAL": "Events that may cause abort (e.g., database connection lost, out of memory)"
         | 
| 404 | 
            +
            }
         | 
| 405 | 
            +
             | 
| 406 | 
            +
             | 
| 407 | 
            +
            def log_with_level(logger: Union[ContextualLogger, logging.Logger],
         | 
| 408 | 
            +
                              level: str,
         | 
| 409 | 
            +
                              message: str,
         | 
| 410 | 
            +
                              **extra):
         | 
| 411 | 
            +
                """
         | 
| 412 | 
            +
                Log a message with dynamic level selection.
         | 
| 413 | 
            +
                
         | 
| 414 | 
            +
                WHY: Allows log level to be determined at runtime, useful for
         | 
| 415 | 
            +
                configurable logging or conditional severity.
         | 
| 416 | 
            +
                
         | 
| 417 | 
            +
                Args:
         | 
| 418 | 
            +
                    logger: Logger instance
         | 
| 419 | 
            +
                    level: Log level as string
         | 
| 420 | 
            +
                    message: Log message
         | 
| 421 | 
            +
                    **extra: Additional fields for structured logging
         | 
| 422 | 
            +
                """
         | 
| 423 | 
            +
                log_level = LOG_LEVELS.get(level.upper(), logging.INFO)
         | 
| 424 | 
            +
                logger.log(log_level, message, extra=extra)
         | 
| 425 | 
            +
             | 
| 426 | 
            +
             | 
| 427 | 
            +
            # Export main functions and decorators
         | 
| 428 | 
            +
            __all__ = [
         | 
| 429 | 
            +
                'get_logger',
         | 
| 430 | 
            +
                'configure_logging',
         | 
| 431 | 
            +
                'log_operation',
         | 
| 432 | 
            +
                'log_performance_context',
         | 
| 433 | 
            +
                'log_function_call',
         | 
| 434 | 
            +
                'log_async_function_call',
         | 
| 435 | 
            +
                'log_with_level',
         | 
| 436 | 
            +
                'LogContext',
         | 
| 437 | 
            +
                'ContextualLogger',
         | 
| 438 | 
            +
                'LOGGING_STANDARDS',
         | 
| 439 | 
            +
                'LOG_LEVELS',
         | 
| 440 | 
            +
                # Re-export from core.logger for backwards compatibility
         | 
| 441 | 
            +
                'log_performance',
         | 
| 442 | 
            +
                'log_async_performance',
         | 
| 443 | 
            +
                'finalize_streaming_logs'
         | 
| 444 | 
            +
            ]
         |